Я работаю над написанием нескольких алгоритмов 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
?
Приветствия!=)