субнормальная поддержка чисел с плавающей запятой IEEE 754 на устройствах iOS ARM (iPhone 4)

При переносе приложения с Linux x86 на iOS ARM (iPhone 4) я обнаружил разницу в поведении арифметики с плавающей запятой и малых значений.

64-битные числа с плавающей запятой (двойные) меньше, чем [+ / -] 2.2250738585072014E-308 в IEEE 754-1985 / IEEE 754-2008.

На iPhone 4 такие маленькие числа обрабатываются как ноль (0), тогда как на x86 для вычислений можно использовать субнормальные числа.

Мне не удалось найти никаких объяснений относительно соответствия стандартам IEEE-754 в документации Apple Страница руководства Mac OS X для float (3).

Но благодаря некоторым ответам на переполнение стека (поведение сброса до нуля в арифметика с плавающей запятой, Double против float на iPhone) , Я нашел несколько подсказок.

Согласно некоторым поисковым запросам, кажется, что VFP ( или NEON) математический сопроцессор, используемый в ядре ARM, использует Flush- Режим To-Zero (FTZ) (например, субнормальные значения преобразуются в 0 на выходе) и режим Denormals-Are-Zero (DAZ) (например, субнормальные значения преобразуются в 0 при использовании в качестве входных параметров) для обеспечения быстрой аппаратной обработки IEEE 754 вычисление.

  • Полное соответствие IEEE754 с кодом поддержки ARM
  • Режим Run-Fast для соответствия стандарту IEEE754 (только оборудование)

Хорошее объяснение FTZ и DAZ можно найти в x87 и поддержка чисел с плавающей запятой SSE в IA-32: Flush-To-Zero (FTZ) и Denormals-Are- Ноль (DAZ):

Режимы FTZ и DAZ обрабатывают случаи, когда возникают недопустимые данные с плавающей запятой или обрабатываются с недополнением или ненормальными условиями. [...]. Разница между номерами, которые обрабатываются ЗСТ и DAZ, очень тонкая. FTZ обрабатывает условия недостаточного заполнения, в то время как DAZ обрабатывает отклонения от нормы. Состояние потери значимости возникает, когда вычисление приводит к отклонению от нормы. В этом случае режим FTZ устанавливает выход на ноль. DAZ исправляет случаи, когда денормальные значения используются в качестве входных данных, либо как константы, либо путем чтения недопустимой памяти в регистры. В режиме DAZ перед вычислением входные данные вычисления обнуляются. Тогда можно сказать, что FTZ обрабатывает [вывод], а DAZ обрабатывает [ввод].

Единственное, что касается FTZ на сайте разработчиков Apple, похоже, находится в Руководство по вызову функций ABI в iOS:

Регистр статуса VFP | FPSCR | Специальное | Биты кода условия (28–31) и биты насыщения (0–4) не сохраняются при вызовах функций. Управление исключениями (8–12), режим округления (22–23) и биты сброса до нуля (24) следует изменять только с помощью определенных подпрограмм, которые влияют на состояние приложения (включая функции API платформы. ). Биты длины короткого вектора (16-18) и шага (20-21) должны быть равны нулю при входе в функцию и выходе из нее. Все остальные биты изменять нельзя.

Согласно техническому справочному руководству ARM1176JZF-S, режимы 18.5 операции (первый процессор iPhone), VFP можно настроить для полной поддержки IEEE 754 (субнормальная арифметика), но в этом случае потребуется некоторая программная поддержка (захват ядра для вычислений в программном обеспечении).

Примечание. Я также прочитал ARM Hard Float Port Debian и страницы сравнения VFP.

Мои вопросы:

  • Где можно найти исчерпывающие ответы о работе с субнормальными числами на устройствах iOS?

  • Можно ли настроить систему iOS на поддержку субнормальных чисел, не требуя от компилятора создания только полного программного кода с плавающей запятой?

Спасибо.


person Yann Droneaud    schedule 08.09.2011    source источник
comment
Эта проблема затрагивает только 64-битные значения с плавающей запятой? Это пока влияет на все железо armv7?   -  person Steven Lu    schedule 26.08.2013
comment
@StevenLu AFAIK это влияет на вычисления с плавающей запятой, 32-битные и 64-битные значения с плавающей запятой.   -  person Yann Droneaud    schedule 05.09.2013


Ответы (1)


Можно ли настроить систему iOS на поддержку субнормальных чисел, не требуя от компилятора создания только полного программного кода с плавающей запятой?

да. Этого можно добиться, установив бит FZ в FPSCR на ноль:

static inline void DisableFZ( )
{
    __asm__ volatile("vmrs r0, fpscr\n"
                     "bic r0, $(1 << 24)\n"
                     "vmsr fpscr, r0" : : : "r0");
}

Обратите внимание, что это может привести к значительному снижению производительности приложения при обнаружении значительного количества денормальных значений. Вы можете (и должны) восстановить состояние с плавающей запятой по умолчанию перед вызовом любого кода, который не гарантирует правильную работу ABI в нестандартных режимах:

static inline void RestoreFZ( ) {
    __asm__ volatile("vmrs r0, fpscr\n"
                     "orr r0, $(1 << 24)\n"
                     "vmsr fpscr, r0" : : : "r0");
}

Отправьте отчет об ошибке, чтобы запросить более качественную документацию по режимам работы FP в iOS.

person Stephen Canon    schedule 08.09.2011
comment
Спасибо за код. Я думал, что это в первую очередь основные системные функции. Не могли бы вы подробнее рассказать о режиме ABI по умолчанию: это RunFast по умолчанию? - person Yann Droneaud; 08.09.2011
comment
@ydroneaud: Да, состояние fpscr по умолчанию, установленное при создании процесса, - DN = 1, FZ = 1 (0x03000000). Однако я не верю, что это явно гарантируется документом платформы ABI, поэтому это может измениться в будущем. - person Stephen Canon; 08.09.2011
comment
Я думаю, что ответ старшего инженера-программиста в Apple достаточно хорош: ответ принят. Спасибо. - person Yann Droneaud; 08.09.2011
comment
ошибка открыта, идентификатор проблемы # 10093675 - person Yann Droneaud; 08.09.2011