Neon VLD потребляет больше циклов, чем ожидалось?

У меня есть простой ассемблерный код, который загружает 12 счетверенных регистров NEON и имеет параллельную инструкцию попарного добавления вместе с инструкцией загрузки (для использования возможности двойной задачи). Я проверил код здесь:

http://pulsar.webshaker.net/ccc/sample-d3a7fe78

Как видно, код занимает около 13 циклов. Но когда я загружаю код на плату, инструкции загрузки, кажется, занимают более одного цикла на загрузку, я проверил и обнаружил, что VPADAL занимает 1 цикл, как указано, но VLD1 занимает более одного цикла. Это почему?

Я позаботился о следующем:

  1. Адрес выровнен по 16 байтам.
  2. Предоставили подсказку по выравниванию в инструкции vld1.64 {d0, d1} [r0,:128]!
  3. Пробовал предварительно загружать инструкцию pld [r0, #192] местами, но это, похоже, увеличивает количество циклов, а не уменьшает задержку.

Может кто-нибудь сказать мне, что я делаю неправильно, почему эта задержка?

Другие детали:

  • Со ссылкой на кору-а8
  • Цепочка инструментов кросс-компилятора arm-2009q1
  • кодирование на ассемблере

person nguns    schedule 14.02.2013    source источник
comment
Отражает ли это больше реальности? pulsar.webshaker.net/ccc/beta-sample-d3a7fe78 (используя ' бета-симулятор)   -  person Aki Suihkonen    schedule 14.02.2013
comment
@AkiSuihkonen, как это возможно? VPADAL и VLD должны работать параллельно, это не похоже на ссылку на симулятор, которую вы дали, а также почему NEON должен запускаться так поздно?   -  person nguns    schedule 14.02.2013
comment
вы ожидаете, что нагрузки будут выполнены за один цикл? В зависимости от расстояния (l1, l2, динамический таран) потребуется много циклов. Я считаю, что было бы очень полезно, если бы вы сначала выпускали нагрузки, а затем добавляли.   -  person auselen    schedule 14.02.2013
comment
@auselen, TRM говорит: «VLD1 2-reg (@ 128)» должен занимать только 1 цикл. Поскольку я буду загружать только 128-битные данные за цикл, указал подсказку выравнивания и убедился, что адрес начинается со 128-битной границы, загрузка должна быть завершена за 1 цикл, верно?   -  person nguns    schedule 14.02.2013
comment
ни в коем случае :) вы используете память DDR правильно? на какую страницу вы ссылаетесь - может быть, я смогу найти для вас описательный ответ.   -  person auselen    schedule 14.02.2013
comment
Если в каком-то руководстве говорится, что загрузка составляет 1 цикл, они, вероятно, имеют в виду, что для помещения нагрузки в очередь загрузки требуется 1 цикл. После того, как он перемещен в очередь загрузки, ЦП приложит все усилия, чтобы загрузить его в регистр назначения. Однако время для «системы» для загрузки данных из любого места (кэш, оперативная память, даже диск :)) потребовало бы значительного количества циклов.   -  person auselen    schedule 14.02.2013
comment
Страница @auselen: 16–28 из DDI0344K_cortex_a8_r3p2_trm   -  person nguns    schedule 14.02.2013
comment
Кроме того, как вы можете видеть в той же таблице на той же странице, он говорит, что регистры результатов (Dn и Dn+1) должны быть доступны на этапе N1, что означает в том же цикле, верно?   -  person nguns    schedule 14.02.2013
comment
извините, не смог найти простой копипасты. Однако ответ на ваш вопрос / путаница заключается в том, что ЦП не может гарантировать синхронизацию с внешней памятью. Пусть это будет кеш (если он не наглухо интегрирован) или того хуже внешняя память. Вот почему люди говорят о ddr2, ddr3 и т.д. У них разные характеристики производительности. На этом этапе вы должны прочитать обо всей вашей системе, чтобы понять, сколько остановок вы можете получить от l1, l2 и оперативной памяти.   -  person auselen    schedule 14.02.2013
comment
Просто добавлю еще одну вещь (позже я попытаюсь создать правильный ответ, если кто-то не сделает этого раньше), что время в TRM предназначено для выполнения/выдачи, поэтому я полагаю, что они относятся к загрузке вашего запроса на загрузку /сохранить очередь.   -  person auselen    schedule 14.02.2013
comment
Конечно, я буду рад, если вы, как обычно, процитируете текст из TRM или других связанных документов в качестве ссылки. Будет ждать вашего ответа.   -  person nguns    schedule 14.02.2013
comment
В руководстве действительно утверждается, что загрузка qX @128 - это операция с одним циклом, но она должна что-то предполагать - например. что адрес был предварительно выбран.   -  person Aki Suihkonen    schedule 14.02.2013
comment
Предварительная выборка в кеше? трубопровод? PLD должен иметь возможность выполнять предварительную выборку, верно? Я использовал PLD, но, похоже, не помогает.   -  person nguns    schedule 14.02.2013


Ответы (1)


Ваш код выполняется намного медленнее, чем ожидалось, потому что в том виде, в котором он написан в настоящее время, он вызывает идеальный шторм остановок конвейера. На любом современном процессоре с конвейерной архитектурой инструкции могут выполняться за один цикл в идеальных условиях. Идеальные условия состоят в том, что инструкция не ожидает памяти и не имеет каких-либо регистровых зависимостей. То, как вы написали код, не допускает задержки при чтении из памяти и делает следующую инструкцию зависимой от результатов чтения. Это приводит к наихудшей возможной производительности. Кроме того, я не уверен, почему вы накапливаете попарные добавления в несколько регистров. Попробуйте что-то вроде этого:

    veor.u16 q12,q12,q12     @ clear accumulated sum
top_of_loop:
    vld1.u16 {q0,q1},[r0,:128]!
    vld1.u16 {q2,q3},[r0,:128]!
    vpadal.u16 q12,q0
    vpadal.u16 q12,q1
    vpadal.u16 q12,q2
    vpadal.u16 q12,q3
    vld1.u16 {q0,q1},[r0,:128]!
    vld1.u16 {q2,q3},[r0,:128]!
    vpadal.u16 q12,q0
    vpadal.u16 q12,q1
    vpadal.u16 q12,q2
    vpadal.u16 q12,q3
    subs r1,r1,#8
    bne top_of_loop

Поэкспериментируйте с различным количеством инструкций загрузки перед выполнением операций добавления. Дело в том, что вам нужно дать время для чтения, прежде чем вы сможете использовать целевой регистр.

Примечание. Использование Q4-Q7 рискованно, поскольку они являются энергонезависимыми регистрами. На Android вы получите случайный мусор, появляющийся в них (особенно Q4).

person BitBank    schedule 18.02.2013
comment
спасибо за ваш ответ, я проверил свой код на плате, и кажется, что зависание происходит для запросов более 64 байт (одна строка кэша в cortex-a8), т.е. после четырех запросов загрузки в моем коде, но я не уверен насчет причина еще. Таким образом, vpadal сразу после запроса на загрузку vld не кажется проблемой. Я попробовал ваш код и мальчик .. !! киоски дали мне небольшой сердечный приступ..!! Проблема с использованием одного и того же регистра для накопления результата приводит к серьезной остановке, прочитайте ответ @auselen здесь - person nguns; 19.02.2013
comment
Полезно знать об использовании одного и того же регистра для накопления результата. Чередование нескольких регистров решит эту проблему. Еще одна вещь, на которую следует обратить внимание, это не использовать слишком много PLD подряд, иначе вы также остановите чтение памяти, так как она будет ждать выполнения всех этих запросов на чтение. Скорость памяти сильно зависит от вашего железа. В последнее время я работал с Qualcomm MSM8074 с памятью DDR3, и пропускная способность памяти весьма впечатляет; задержки инструкций и памяти в этой системе примерно равны. - person BitBank; 19.02.2013