November 15th, 2007

nyaload

Денормализованые числа

Оказывается, на PC можно случайно получить сверх-маленькие (денормализованные) числа, после чего программа с расчётами может начать очень сильно тормозить. (Получить можно разными способами, например взять две матрицы поворота на 355.99998 градусов, и перемножить, где "почти нулевые" элементы могут получится денормализоваными.
Страшно, что это невозможно отключить (_control87(_DN_FLUSH, _MCW_DN) похоже ничего не делает, флажка у сопроцессора нет), может появиться в коде который ничего особенно не делает, просто камера и монстр так встали, что появилось сверх-малое число. А потом оно уползёт в AI и физику, и всё будет плохо.
Попробуйте запустить код ниже, увидете что скорость работы зависит от того, что перемножается.

Collapse )
Collapse )

updated: обнаружил в физике шариков нашего маджонга кучу таких underflow после pos + dt*velocity; и чо с этим делать - пока не очень понятно. Возможно, в вашей физике тоже полно такого, а вы об этом не знаете ;)
updated: Проверка показала, что с SSE - таже фигня.
updated: Если компилятору удаётся всё-всё засунуть в регистры, то возможно что промежуточных денормализованых чисел не будет, так как внутри регистры 80-битные. Таким образом, производительность может фантастически меняться при очень небольших правках кода. В SSE - 32 битные регистры. Поэтому на денормализованых числах FPU может работать в 100 раз быстрей, пока они в регистрах, а не в памяти. А от добавления /arch:SSE - оно начинает работать резко медленней.

Вот такой вот подарок от Intel. Как с ним бороться - непонятно. Учитывая что денормализованые числа не нужны, но отключить их нельзя.

updated:
Бинго!
/arch:SSE + _mm_setcsr(_mm_getcsr() | _MM_FLUSH_ZERO_MASK);
Источник информации:
http://softpixel.com/~cwright/programming/simd/sse.php
Intel автоматически включает этот флажок, MSVC нет.
Вроде если установить флажок DAZ (0x40), то оно подействует на FPU. У меня не получилось.