ARM Neon Assembler — странная проблема с конвейером

Я пытаюсь увеличить производительность кода, написанного на ARM Assembler, используя инструкции Neon.

Для тестирования и расчета я использую этот калькулятор: http://pulsar.webshaker.net/ccc/sample-706454b3

Я заметил, что в строке «n.34-0 1c n0» блоку Neon внезапно приходится ждать (?) 10 циклов. С чем это может быть связано или это просто глюк калькулятора?

Также мне понадобится общая информация о том, как повысить производительность в ARM/Neon Assembler.

Целью является ARM Cortex-A9. Для компиляции я использую новейший android-ndk со встроенным ассемблером. Спасибо.


person HectorLector    schedule 15.03.2012    source источник


Ответы (3)


На самом деле это немного сложнее. BitBank прав, NEON придется ждать D4.

Но вам нужно подождать 10 циклов, потому что у Neon есть очередь загрузки/сохранения. И очередь заполняется другой инструкцией перед

vld1.64 d4, [r7, :64]

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

person webshaker    schedule 19.03.2012

Блок NEON должен ждать этой инструкции, потому что вы ссылаетесь на регистр (D4), который был загружен в предыдущей инструкции NEON (n.33-0 1c n0). Загрузки не мгновенны, и из-за конвейерной обработки данные доступны с задержкой, даже если они поступают из кеша. Вам нужно переупорядочить инструкции ARM и NEON, чтобы не пытаться использовать регистры сразу после их загрузки, иначе вы получите потраченные впустую циклы (конвейерные киоски).

person BitBank    schedule 15.03.2012
comment
эти опасности составляют всего 1 ~ 2 цикла, если кеш попал. В данном случае это что-то другое. - person Jake 'Alquimista' LEE; 18.03.2012

Вы не должны обращаться к памяти через ARM, пока NEON выполняет свою работу. Это вызывает полный тормоз на NEON.

По-видимому, вы пытаетесь выполнить какую-то параллельную обработку, которая является разрушительной по указанной выше причине.

Кроме того, слишком много ldrb. Байтовый доступ на ARM тоже чуть ли не грех.

Я предлагаю вам сначала полностью переписать свой код на C, используя только 32-битный доступ к памяти, а затем оценить, предназначен ли он вообще для NEON,

person Jake 'Alquimista' LEE    schedule 18.03.2012
comment
Спасибо за комментарий. Мне нужен только один байт, поэтому, если бы я читал 32 бита сразу, мне нужно снова сдвинуть/и все это, и это будет медленнее. Код уже существует в виде ассемблера C и ARM, и мне нужно проверить, могу ли я ускорить его с помощью инструкции Neon. Теоретически должно быть на 30-40% быстрее. Какие операции можно выполнять параллельно. Арифметика ARM и загрузка/сохранение Neon, но не (?) арифметика Neon и загрузка/сохранение ARM? - person HectorLector; 18.03.2012
comment
Вы не поверите: 32-битное чтение + маскирование намного быстрее, чем байтовое чтение. - person Jake 'Alquimista' LEE; 19.03.2012
comment
Забудьте о параллельной обработке. Перемещение значений из Neon в ARM также приводит к тому, что сброс конвейера тратит впустую 11 циклов. ARM будет служить только в качестве блока управления, в то время как Neon выполняет всю работу. - person Jake 'Alquimista' LEE; 19.03.2012
comment
Я попробую загрузить 32-битную и маскировку, но я думаю, что кто-то уже тестировал это раньше, и это было медленнее. Хорошо, спасибо за информацию. Кажется, в моем случае я не могу увеличить производительность с помощью инструкций Neon :-( - person HectorLector; 20.03.2012
comment
Почему бы вам не попробовать полностью переписать свою функцию в NEON? Neon чрезвычайно способен выполнять целочисленные операции и не требует трудоемких операций маскирования. Если ваша функция содержит менее двух операторов if-else в цикле, вам подойдет Neon. - person Jake 'Alquimista' LEE; 21.03.2012
comment
Скорость чтения байтов может варьироваться в зависимости от SoC. Есть несколько трюков для ускорения операций маскирования, которые делают маскирование ВСЕГДА быстрее, чем чтение байтов на ARM: const unsigned int mask=0xff; byte0=maskbyte1=mask&(data››8);byte2=mask&(data››16);byte3=mask&(data››24); - person Jake 'Alquimista' LEE; 21.03.2012
comment
Вышеупомянутый трюк выигрывает от встроенного барабанного переключателя ARM и 1 цикла каждый. Вы можете опустить маскирование byte3, встроив его в нужную операцию, например: result += (data››24); Обратите внимание, что этот трюк работает только в режиме ARM, так как Thumb не поддерживает IBS. В любом случае вам следует компилировать все критичные к производительности подпрограммы в режиме ARM. - person Jake 'Alquimista' LEE; 21.03.2012
comment
проблема в том, что большую часть времени я вычисляю адреса (смещение + сдвиг значений), из которых снова загружаю значения. Если я выполняю вычисления в Neon, мне снова приходится перемещать полученные адреса в регистры ARM, что очень медленно. Поэтому я выполняю вычислительную часть в ARM Assembler и просто использую Neon для загрузки из полученных адресов и некоторого XOR. Я предполагаю, что это не совсем враг Neon, но я надеюсь, что это принесет хоть какое-то улучшение. Спасибо за информацию, я попробую Bitmasking. Я знаю о манетке ARM Barrel - так что я скажу вам, сработало ли это ;-) - person HectorLector; 27.03.2012