gcc on raspberry с плавающей точкой половинной точности (binary16, альтернатива, __fp16) использует библиотечную функцию - PullRequest
0 голосов
/ 31 декабря 2018

Я использую алгоритм машинного обучения на основе 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}    @

Я что-то пропустил?

Ответы [ 2 ]

0 голосов
/ 01 января 2019

Флаг компилятора -mfpu=neon переопределяет ранее -mfpu=neon-fp16, поскольку -mfpu= может быть указан только один раз.

Было ошибкой, что он был установлен дважды (он был добавлен в другом месте вMakefile).

Но так как raspberry 3 имеет vfpv4, который всегда имеет поддержку fp16, наилучшей спецификацией будет -mfpu=neon-vfpv4.

. В этом случае компилятор не генерирует библиотечные вызовы дляпреобразование.

редактировать: в соответствии с этим ghist -mfpu=neon-fp-armv8 -mneon-for-64bits может использоваться для Raspberry 3.

0 голосов
/ 31 декабря 2018

На сайте ARM: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0774d/chr1421838476257.html

Примечание. Тип __fp16 является только форматом хранения.Для арифметических и других операций значения __fp16 в выражениях C или C ++ автоматически переводятся в плавающее.

...