Тест ARM Cortex A8: может кто-нибудь помочь мне разобраться в этих цифрах? - PullRequest
5 голосов
/ 08 ноября 2011

Я работаю над написанием нескольких алгоритмов DSP в реальном времени для Android, поэтому я решил запрограммировать ARM непосредственно в Assembly, чтобы максимально оптимизировать все и сделать математику максимально легкой.Сначала я получал тесты скорости, которые не имели особого смысла, поэтому я начал читать об опасностях конвейера, возможностях с двумя проблемами и так далее.Я все еще озадачен некоторыми числами, которые я получаю, поэтому я публикую их здесь в надежде, что кто-то сможет пролить свет на то, почему я получаю то, что я получаю.В частности, меня интересует, почему NEON тратит разное время на выполнение вычислений для разных типов данных, даже если он утверждает, что выполняет каждую операцию ровно за один цикл.Мои выводы следующие:

Я использую очень простой цикл для бенчмаркинга и запускаю его для 2 000 000 итераций.Вот моя функция:

hzrd_test:

    @use received argument an number of iterations in a loop
    mov r3 , r0

    @come up with some simple values
    mov r0, #1
    mov r1, #2

    @Initialize some NEON registers (Q0-Q11)
    vmov.32 d0, r0, r1
    vmov.32 d1, r0, r1
    vmov.32 d2, r0, r1

    ...

    vmov.32 d21, r0, r1
    vmov.32 d22, r0, r1
    vmov.32 d23, r0, r1

hzrd_loop:

    @do some math
    vadd.s32 q0, q0, q1
    vadd.s32 q1, q0, q1
    vadd.s32 q2, q0, q1
    vadd.s32 q3, q0, q1
    vadd.s32 q4, q0, q1
    vadd.s32 q5, q0, q1
    vadd.s32 q6, q0, q1
    vadd.s32 q7, q0, q1
    vadd.s32 q8, q0, q1
    vadd.s32 q9, q0,s q1
    vadd.s32 q10, q0, q1
    vadd.s32 q11, q0, q1

    @decrement loop counter, branch to loop again or return
    subs r3, r3, #1
    bne hzrd_loop

    @return
    mov r0, r3
    mov pc, lr

Обратите внимание на операцию вычисления и тип данных, указанные как векторное добавление (vadd) и 32-битное целое со знаком (s32).Эта операция завершается в течение определенного времени (см. Таблицу результатов ниже).Согласно этому документу ARM Cortex-A8 и последующим страницам, почти все элементарные арифметические операции в NEON должны выполняться за один цикл, но вот что я получаю:

vmul.f32 ~62ms
vmul.u32 ~125ms
vmul.s32 ~125ms

vadd.f32 ~63ms
vadd.u32 ~29ms
vadd.s32 ~30ms

Я делаюих просто заменяя операции и типы данных всего в вышеуказанном цикле.Есть ли причина, по которой vadd.u32 в два раза быстрее, чем vadd.f32, а vmul.f32 в два раза быстрее, чем vmul.u32?

Приветствия!=)

Ответы [ 2 ]

6 голосов
/ 09 ноября 2011

Вау, ваши результаты ОЧЕНЬ точны:

  • 32-битное целое число Q умножается на 4 цикла, в то время как float занимает 2.
  • 32-битное целое число Q добавляет затраты на 1 цикл, в то время как float занимает 2.

Хороший эксперимент.

Возможно, вы уже знаете, но будьте осторожны при кодировании для NEON:

  • не обращайтесь к памяти с помощью ARM, пока NEON делаеттяжелая работа
  • не смешивайте инструкции VFP с NEON.(кроме этих общих)
  • не получают доступ к регистрам S.
  • не переводят из регистров NEON в ARM

Все вышеперечисленное вызовет ОГРОМНЫЙ сбой.

Удачи!

PS: Я бы предпочел вместо этого оптимизировать для A9 (немного отличаться по времени цикла), поскольку практически все новые устройства идут с A9.И график времени A9 от ARM гораздо более читабелен.: -)

4 голосов
/ 08 ноября 2011

Я собираюсь догадаться (поскольку у меня нет удобных ссылок на документы), что вы сталкиваетесь с проблемами конвейера.Я знаю, что FPU-err, теперь называемый VFPU, имеет другую длину конвейера, чем у CPU для выполнения целочисленной математической части вашего цикла.Я вижу, что 2-я арифметическая операция зависит от первой, которая остановит любой конвейер и, возможно, покажет различия, которые вы видите.

Кроме того, я полагаю, что умножение - это не инструкция 1 цикла для целых чисел, а 2-5 циклов в зависимости от мсб 2-го значения - здесь 2 цикла из-за небольшого размера числа, который объясняет эту разницу.Чтобы убедиться в этом, начните с большего числа умножения и посмотрите, не замедляется ли оно при большем размере.

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

Я бы также ознакомился с разделом «Двойное выполнение» чуть выше, так как там есть все виды остановок конвейера, которые также происходят там, когда вещи взаимозависимы.

...