Я использую алгоритм машинного обучения на основе raspberry pi 3 с огромными массивами хранимых коэффициентов, которым не требуется полная точность float32.
Я пытался использовать половинную точность с плавающей запятой для хранения этих данных, чтобы уменьшитьобъем памяти программ (и, возможно, пропускной способности памяти).
Остальная часть алгоритма осталась прежней.
Сравнение float32 с версией float16, которую я получил (значительное: + 33% времени выполнения моеготестовая программа) потеря производительности при использовании __fp16
, хотя преобразование должно поддерживаться процессором.
Я посмотрел на вывод asembler, а также создал функцию sinple, которая просто читает значение __fp16
ивозвращает его как float
, и кажется, что для преобразования используется какой-то вызов библиотечной функции.(вызывается та же функция, что и в реальном коде)
Процессор rapspberry должен иметь аппаратную поддержку с половинной точностью, поэтому я ожидал увидеть некоторые инструкции, загружающие данные, и не увидеть никакого влияния на производительность (или увидеть улучшениеиз-за уменьшенных требований к пропускной способности памяти)
Я использую следующие флаги компилятора:
-O3 -mfp16-format=alternative -mfpu=neon-fp16 -mtune=cortex-a53 -mfpu=neon
здесь небольшой фрагмент кода и выходные данные ассемблера для небольшой тестовой функции:
const float test(const Coeff *i_data, int i ){
return (float)(i_data[i]);
}
с использованием float
для Coeff
:
.align 2
.global test
.syntax unified
.arm
.fpu neon
.type test, %function
test:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
add r1, r0, r1, lsl #2 @ tmp118, i_data, i,
vldr.32 s0, [r1] @, *_5
bx lr @
с использованием __fp16
для Coeff
(-mfp16-format=alternative
):
.align 2
.global test
.syntax unified
.arm
.fpu neon
.type test, %function
test:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
lsl r1, r1, #1 @ tmp118, i,
push {r4, lr} @
ldrh r0, [r0, r1] @ __fp16 @, *_5
bl __gnu_h2f_alternative @
vmov s0, r0 @,
pop {r4, pc} @
с использованием __fp16
для Coeff
(-mfp16-format=ieee
):
.align 2
.global test
.syntax unified
.arm
.fpu neon
.type test, %function
test:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
lsl r1, r1, #1 @ tmp118, i,
push {r4, lr} @
ldrh r0, [r0, r1] @ __fp16 @, *_5
bl __gnu_h2f_ieee @
vmov s0, r0 @,
pop {r4, pc} @
Я что-то пропустил?