Правильное использование инструкции ARM PLD (ARM11) - PullRequest
4 голосов
/ 20 июня 2011

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

Мой вопрос заключается в том, что при наличии 256-байтового цикла с точным копированием ldm/stm инструкций, скажем, r4-r11 x 8, было бы лучше предварительно выбирать каждую строку кэша перед копированием, между каждой парой инструкций или нетсделайте это вообще, так как рассматриваемый memcpy не читает и не записывает в одну и ту же область памяти.Я уверен, что мой размер строки кэша составляет 64 байта, но это может быть 32 байта - в ожидании подтверждения об этом, прежде чем писать окончательный код здесь.

Ответы [ 3 ]

5 голосов
/ 20 июня 2011

Из Руководства программиста серии Cortex-A , глава 17.4 (Примечание: некоторые детали могут отличаться для ARM11):

Лучшая производительность для memcpy () достигается с помощью LDM всего кэша линия, а затем записать эти значения с STM всей строки кэша. Выравнивание магазинов больше важнее, чем выравнивание нагрузок. Инструкция PLD должна использоваться где возможно. Есть четыре PLD слоты в блоке загрузки / хранения. PLD инструкция имеет приоритет над автоматический предварительный сборщик и не имеет стоимости с точки зрения целочисленного конвейера спектакль. Точное время PLD Инструкция для лучшего memcpy () может немного различаются между системами, но PLD на адрес три строки кеша впереди текущей копирующей строки является полезная отправная точка.

3 голосов
/ 21 июня 2011

Пример достаточно общего цикла копирования, в котором используются блоки размером LDM / STM и / или PLD размера кэшированной строки, где это доступно, можно найти в ядре Linux, arch/arm/lib/copy_page.S. Это реализует то, что Игорь упоминает выше относительно использования предварительных нагрузок, и иллюстрирует блокировку.

Обратите внимание, что в ARMv7 (где размер строки кэша обычно составляет 64 байта) невозможно LDM заполнить всю строку кэширования как одну операцию (есть только 14 регистров, которые вы можете использовать, поскольку SP / PC не может быть тронутым за это). Поэтому вам, возможно, придется использовать две / четыре пары LDM / STM.

1 голос
/ 06 июля 2013

Чтобы действительно получить «самый быстрый» из возможных ARM-кодов ARM, вам необходимо протестировать различные подходы в вашей системе. Что касается цикла ldm / stm, этот мне кажется наиболее подходящим:

  // Use non-conflicting register r12 to avoid waiting for r6 in pld

  pld [r6, #0]
  add r12, r6, #32

1:
  ldm r6!, {r0, r1, r2, r3, r4, r5, r8, r9}
  pld   [r12, #32]
  stm r10!, {r0, r1, r2, r3, r4, r5, r8, r9}
  subs r11, r11, #16
  ldm r6!, {r0, r1, r2, r3, r4, r5, r8, r9}
  pld   [r12, #64]
  stm r10!, {r0, r1, r2, r3, r4, r5, r8, r9}
  add r12, r6, #32
  bne 1b

В вышеприведенном блоке предполагается, что вы уже настроили r6, r10, r11, и этот цикл ведет обратный отсчет на словах r11, а не байтах. Я проверил это на Cortex-A9 (iPad2), и, похоже, на этом процессоре он показывает неплохие результаты. Но будьте осторожны, потому что на Cortex-A8 (iPhone4) петля NEON кажется быстрее, чем ldm / stm, по крайней мере для больших копий.

...