Что именно означает «ненормальный ввод» в сборке, когда мы рассматриваем использование флага DAZ для плавающих точек SSE - PullRequest
2 голосов
/ 27 апреля 2020

Я прочитал Эта статья и do-denormal-flags-like-denormals-are-zero-daz-effect-сравнение-для-равенства и я понимаю использование и различие между флагами FTZ и DAZ.

DAZ применяется на входе, FTZ на выходе из операции FP.

Меня смущает то, откуда исходит денормальное значение в виде сборки, если FTZ установлен . Я думаю, что это могут быть только константные значения либо в виде непосредственных операндов, либо из раздела .rodata (доступ с помощью относительной RIP-адресации).

Но я обнаружил, что в моем двоичном файле нет ненормальных значений в этих местах, но все еще страдает от проблем FP-ASSIST, приводящих к плохой производительности.

Если я установлю DAZ и FTZ, проблема исчезнет, ​​и производительность улучшится. На самом деле я даже не нахожу какие-либо ненормальные входы в моем исходном коде. Я действительно запутался, откуда берутся ненормальные значения?


Кстати, еще один вопрос, для инструкции vmovsd 0x9498(%rip),%xmm0, предположим, 0x9498(%rip) является ненормальным значением, что происходит с xmm0 после эта инструкция выполняется, если мы установим FTZ или DAZ соответственно?

В моем понимании, DAZ будет принимать 0x9498(%rip) в качестве нуля и mov 0 в xmm0; FTZ переместится на 0x9498(%rip) в xmm0 и обнаружит, что это ненормальное значение, поэтому грипп sh xmm0 равен нулю. Я не уверен, это правильно?

1 Ответ

2 голосов
/ 27 апреля 2020

Денорма, иначе субнормальный, - это значение с полем экспоненты = 0 в двоичном формате IEEE. https://en.wikipedia.org/wiki/Double-precision_floating-point_format

Когда математическая инструкция FP (не перемещаемая или чисто побитовая логическая) считывает такое число как входной операнд, она должна обрабатывать этот особый случай при выравнивании мантиссы с другой операнд, и при применении неявного верхнего бита мантиссы, который подразумевается показателем степени, равным 0 или отличным от нуля.

Да, большую часть времени FTZ на выходе является достаточным, поскольку большинство значений с плавающей запятой являются результаты других вычислений ФП. И да, FTZ необходим, потому что mul / div / add / sub для нормальных чисел может создать ненормальный результат . (Для добавления входов нужны противоположные знаки). Другая точно округленная операция IEEE "basi c", sqrt, не может создавать субнормалей, потому что она приближает числа к 1.0.

Очевидной вещью будет использование perf record, чтобы выяснить, где вы Вы получаете FP-помощь и добавляете некоторые дополнительные чеки, чтобы напечатать или что-то еще, когда вы найдете там ненормальный. (Затем установите точку останова в этой ветви, чтобы вы могли изучить ситуацию.)


Возможные источники ненормальных значений (не исчерпывающих) с установленным FTZ, т. Е. Отличных от математических операций FP:

  • String-to-float, который формирует битовый шаблон FP с целым числом расширенной точности, как Glib c 'strtod
  • Входные файлы / сеть, если вы' повторное чтение двоичных данных.
  • Другие потоки или через разделяемую память из других процессов, работающих без FTZ. (FTZ / DAZ и режим округления в MXCSR являются архитектурным состоянием для каждого потока. Кстати, если вы установите FTZ только в главном потоке после запуска другого потока, он не будет действовать для уже начатый поток.) ​​
  • Возможно целочисленное манипулирование битовыми шаблонами FP, например nextafter. Также возможно как часть внутренних компонентов реализации exp, которая вставляет целое число в поле экспоненты double.
  • Постоянные значения времени компиляции. Они не должны появляться в исходном коде как буквальное значение. например, static double foo = DBL_MIN / 4.0; будет денормальным во время компиляции. Но вы найдете их в .rodata или .data. Неконстантные ненулевые состояния c / глобальные переменные go в .data.

Очевидно, что любое ручное манипулирование битовыми шаблонами FP с использованием целочисленных данных тоже может это сделать. Как использовать биты в байте для установки слов в регистре ymm без AVX2? (Инверсия vmovmskps) мог бы привести к ненормальным входам для сравнения, если бы я не потратил лишнюю инструкцию, чтобы ее избежать, но это необычный трюк ручной векторизации, который компиляторы не сделали бы для вас.

непосредственные операнды

x86 не имеет немедленных FP; вам нужно будет mov rax, imm64 / movq xmm0, rax или подобное. Но компиляторы этого не делают, потому что обычно более эффективно загружать из .rodata.

для инструкции vmovsd 0x9498(%rip),%xmm0

vmovsd - это просто загрузка и всегда точно копирует 64 бита; архитектурно эквивалентен vmovq SIMD-целочисленной загрузке.

Он не пропускает значение через ALU, поэтому никакие биты MXCSR не влияют на vmovsd, FP shuffles и т. д. c. Это влияет только на инструкции, которые выполняют фактическую математику FP и могут вызывать исключения FP Вы можете сказать, посмотрев на раздел исключений в записи руководства asm. Например, roundsd подчиняется DAZ для возможного округления ввода до нуля до округления в соответствии с указанным режимом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...