Проблема с плавающей точностью на ARM FPU (Neon-vfvp3) на IMX.6 Sabre lite

Привет, я запускаю простую программу для тестирования модуля с плавающей запятой на Imx6.sabre_lite

    double z = 2.2250738585072014e-308;
    double x = 3.0594765554474019e-308;
    double ans = x-z;

Теперь ans оказывается равным нулю, тогда как на архитектуре x86 он не равен нулю (8.344026969402e-309 # DEN), я предполагаю, что есть некоторая проблема с точностью, например, блок ARM FPU на cortex-A9 (IMX.6 Sabre) не работает » Я поддерживаю такие расчеты, но по каким-то причинам я не могу это проверить. Я использую следующие флаги сборки для компиляции.

-mfloat-abi=hard -mfpu=neon-vfpv3 

Я искал другие ответы, и все они, похоже, указывают на то, что Neon поддерживает только числа с плавающей запятой одинарной точности на Aarch32, но я прочитал в следующем документе для cortex-A9 https://developer.arm.com/documentation/ddi0409/i/preface/about-this-book Хотя SIMD только для чисел с плавающей запятой одинарной точности, VFPv3 поддерживает числа с плавающей запятой двойной точности, так что не понимаю, в чем проблема. Сгенерированный код сборки выглядит следующим образом

21          double z = 2.2250738585072014e-308;
1009baa8:   mov     r2, #0
1009baac:   mov     r3, #1048576    ; 0x100000
1009bab0:   strd    r2, [r11, #-12]
22          double x = 3.0594765554474019e-308;
1009bab4:   mov     r2, #0
1009bab8:   mov     r3, #1441792    ; 0x160000
1009babc:   strd    r2, [r11, #-20] ; 0xffffffec
23          double ans = x-z;
1009bac0:   vldr    d17, [r11, #-20]        ; 0xffffffec
1009bac4:   vldr    d16, [r11, #-12]
1009bac8:   vsub.f64        d16, d17, d16
1009bacc:   vstr    d16, [r11, #-28]        ; 0xffffffe4

Эта инструкция, которая выполняет вычитание vsub.f64 d16, d17, d16, является vsub.f64 инструкцией VFP.


person Fahad Mubeen    schedule 08.02.2021    source источник
comment
VFP не NEON, хотя у них общий регистрационный банк и некоторые инструкции. И да, vsub.f64 - это VFP инструкция.   -  person Jake 'Alquimista' LEE    schedule 02.03.2021
comment
Как вы думаете, проблема в том, что я использую неон, а не VFP -mfpu=neon-vfpv3 . Флаг упоминает как neon, так и vfpv3, которые из них включаются.   -  person Fahad Mubeen    schedule 03.03.2021
comment
Спасибо, @ Jake'Alquimista'LEE, что вы упомянули VFP не NEON заставили меня поискать и прийти к этому ответу stackoverflow.com/questions/66102892/   -  person Fahad Mubeen    schedule 03.03.2021


Ответы (2)


VFP на ARM полностью соответствует стандарту IEEE-754, и поэтому я сомневаюсь, что он дает неправильные результаты, когда речь идет о ненормальных числах.

Я предполагаю, что вы указали неверные параметры для printf.

Самый простой способ выяснить это - проверить регистр или память, содержащую ans.


Редактировать:

Я запустил следующую тестовую функцию на своем Nexus-S (Cortex-A8)

    double dsub(double a, double b)
    {
        return a-b;
    }

    ans = dsub(3.0594765554474019e-308, 2.2250738585072014e-308);


ans: 8.3440269694020052E-309

Cortex-A8 - самый первый из серии Cortex с худшими VFP (VFP Lite)

Думаю, вы что-то не так делаете при проверке результата. (Машинный код в порядке)

person Jake 'Alquimista' LEE    schedule 01.03.2021
comment
Я проверил, что регистр равен нулю, я не использовал printf, я использовал IDE, чтобы проверить, каковы значения переменной ans, кроме того, я также проверил ans by if(ans==0), и он действительно был равен нулю, эта же программа правильно работает на Aarch64 (ARM -V8A) и машины X86). - person Fahad Mubeen; 03.03.2021

РЕДАКТИРОВАТЬ: (Это не окончательный и полный ответ, в настоящее время ведется расследование.)

Я наконец нашел ответ из документации GCC о флаге компилятора, neon не полностью реализует стандарт IEEE 754, и я думаю, что это причина потери точности.

If the selected floating-point hardware includes the NEON extension (e.g. -mfpu=neon), note that floating-point operations are not generated by GCC’s auto-vectorization pass unless -funsafe-math-optimizations is also specified. This is because NEON hardware does not fully implement the IEEE 754 standard for floating-point arithmetic (in particular denormal values are treated as zero), so the use of NEON instructions may lead to a loss of precision.

Источник: https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html (см. Документацию по -mfpu)

Так как результат в моих расчетах был # 8.344026969402e-309, который является DEN (денормальное число), и неон обрабатывает его как ноль, в отличие от блоков FPU, совместимых с IEEE 754.

person Fahad Mubeen    schedule 03.03.2021
comment
Неправильный. Сгенерированный код не содержит единственной инструкции neon. - person Jake 'Alquimista' LEE; 03.03.2021
comment
@ Jake'Alquimista'LEE, тогда в чем может быть проблема? Кажется, у вас гораздо больше знаний по этому вопросу. Я попытался изменить флаги сборки на -mfpu=vfpv3-d16, чтобы использовать только VFP. Тем не менее я видел, что результат был оценен как ноль. `` '' - person Fahad Mubeen; 05.03.2021