Расширенная (80-разрядная) двойная с плавающей запятой в x87, а не SSE2 – мы ее не пропустили?

Я читал сегодня об исследователях, обнаруживших, что библиотеки Phys-X NVidia используют x87 FP против SSE2 . Очевидно, что это будет субоптимально для параллельных наборов данных, где скорость превосходит точность. Однако автор статьи далее цитирует:

Intel начала обескураживать использование x87 с введением P4 в конце 2000 года. AMD отказалась от x87 с K8 в 2003 году, поскольку x86-64 определен с поддержкой SSE2; VIA C7 поддерживает SSE2 с 2005 года. В 64-разрядных версиях Windows x87 устарел для пользовательского режима и полностью запрещен в режиме ядра. Практически все в отрасли рекомендовали SSE по сравнению с x87 с 2005 года, и нет причин использовать x87, если только программное обеспечение не должно работать на встроенном Pentium или 486.

Я подумал об этом. Я знаю, что x87 использует 80-битные расширенные двойники для вычисления значений, а SSE2 – нет. Разве это никому не важно? Мне это кажется удивительным. Я знаю, когда я выполняю вычисления по точкам, линиям и полигонам в плоскости, значения могут быть неожиданно ошибочными при выполнении вычитаний, а области могут разрушаться, а линии – друг другу из-за отсутствия точности. Я бы предположил, что использование 80-битных значений по сравнению с 64-битными значениями может помочь.

Это неверно? Если нет, что мы можем использовать для выполнения расширенных двойных операций FP, если x87 будет постепенно прекращено?

    Самая большая проблема с x87 заключается в том, что все операции с регистром выполняются в 80 бит, тогда как большинство людей используют только 64-битные поплавки (т. Е. Плавающие с двойной точностью). Что происходит, вы загружаете 64-битный float в стек x87 и преобразуете его в 80 бит. Вы выполняете некоторые операции над ним в 80 бит, затем сохраняете его обратно в память, преобразуя его в 64 бит. Вы получите другой результат, чем если бы вы выполнили все операции всего с 64 битами, а с оптимизирующим компилятором это может быть очень непредсказуемо, сколько конверсий может иметь значение, поэтому трудно проверить, что вы получаете ” правильный “ответ при выполнении регрессионных тестов.

    Другая проблема, которая имеет значение только с точки зрения того, что кто-то пишет сборку (или опосредованно записывает сборку, в случае кого-то, пишущего генератор кода для компилятора), заключается в том, что x87 использует стек регистров, тогда как SSE использует индивидуально доступные регистры. С x87 у вас есть куча дополнительных инструкций по манипулированию стеком, и я полагаю, что Intel и AMD предпочли бы, чтобы их процессоры быстро работали с кодом SSE, чем пытались быстро выполнить эти дополнительные инструкции x87 по управлению стеками.

    BTW, если у вас возникли проблемы с неточностями, вы захотите взглянуть на статью « Что каждый программист должен знать о арифметике с плавающей запятой », а затем, возможно, вместо этого использовать произвольную математическую библиотеку точности (например, GMP).

    Чтобы правильно использовать математику с расширенной точностью, необходимо, чтобы язык поддерживал тип, который можно использовать для хранения результатов промежуточных вычислений, и может быть заменен выражениями, дающими эти результаты. Таким образом, учитывая:

    void print_dist_squared(double x1, double y1, double x2, double y2) { printf("%12.6f", (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); } 

    должен быть некоторый тип, который можно было бы использовать для захвата и замены общих подвыражений x2-x1 и y2-y1 , позволяя переписать код следующим образом:

     void print_dist_squared(double x1, double y1, double x2, double y2) { some_type dx = x2-x1; some_type dy = y2-y1; printf("%12.6f", dx*dx + dy*dy); } 

    без изменения семантики программы. К сожалению, ANSI C не смог указать какой-либо тип, который можно было бы использовать для some_type на платформах, которые выполняют вычисления с высокой точностью, и стало гораздо более распространенным явлением обвинять Intel в существовании типов с расширенной точностью, чем обвинять поддержку ANSI.

    На самом деле, типы с расширенной точностью имеют такую ​​же ценность для платформ без блоков с плавающей запятой, как и для процессоров x87, поскольку на таких процессорах вычисление, такое как x + y + z, влечет за собой следующие шаги:

    1. Распакуйте мантиссою, экспоненту и, возможно, знак x в отдельные регистры (показатель и знак часто могут быть «двухъярусными»)
    2. Распакуйте также.
    3. Справа сдвиньте мантиссу значения с нижним показателем, если таковой имеется, а затем добавьте или вычтите значения.
    4. В случае, если x и y имеют разные знаки, сдвиньте левую мантиссу до тех пор, пока крайний левый бит не станет равным 1 и соответствующим образом отрегулируйте показатель.
    5. Упакуйте экспонента и мантиссу обратно в двойной формат.
    6. Распакуйте этот временный результат.
    7. Распаковать z.
    8. Справа сдвиньте мантиссу значения с нижним показателем, если таковой имеется, а затем добавьте или вычтите значения.
    9. В случае, если предыдущий результат и z имели разные знаки, сдвиньте влево мантису до тех пор, пока левый бит не станет равным 1 и соответствующим образом настройте экспоненту.
    10. Упакуйте экспонента и мантиссу обратно в двойной формат.

    Использование расширенного типа позволит устранить шаги 4, 5 и 6. Так как 53-битная мантисса слишком велика для размещения менее четырех 16-разрядных регистров или двух 32-битных регистров, выполнение добавления с помощью 64-битной мантиссы не является более медленным, чем использование 53-битной мантиссы, поэтому использование математика с расширенной точностью предлагает ускоренное вычисление без искажений на языке, который поддерживает правильный тип для хранения временных результатов . Нет причин для отказа Intel в предоставлении FPU, который мог бы выполнять математику с плавающей запятой, что также было самым эффективным методом для чипов, отличных от FPU.

    Другой ответ кажется, что использование 80-битной точности – плохая идея, но это не так. Он выполняет иногда жизненно важную роль в поддержании неточности в страхе, например, в работах В. Кахана.

    Всегда используйте 80-битную промежуточную арифметику, если вы можете ускользнуть от нее по скорости. Если это означает, что вам нужно использовать математику x87, ну, сделайте это. Поддержка этого является вездесущей и до тех пор, пока люди продолжают поступать правильно, она останется повсеместной.

    Двойная прецессия на 11 бит меньше, чем f80 (около 2,5 гб / цифр), для многих приложений (в основном игр) это не повредит. Но вам понадобится вся необходимая точность, например, космическая программа или медицинское приложение.

    Это немного вводит в заблуждение, когда некоторые говорят, что f80 (и обескуражен им) работает в стеке. Регистры FPU и операции аналогичны операциям стека, возможно, что то, что заставляет людей путать. Он фактически основан на памяти (load / store), а не стек per se, по сравнению, например, с вызовом, например cdecl stdcall, который фактически передает параметры через стек. и ничего плохого в этом.

    Большим преимуществом SSE на самом деле является сериализация операции, 2, 4, 8 значений одновременно, со многими вариантами varian. Да, вы можете напрямую перенести в регистр, но вы будете передавать эти значения в память в конце концов.

    Большим недостатком f80 является его нечетный 10-байтовый длинный, он нарушает выравнивание. вам нужно будет выровнять их 16 для более быстрого доступа. но не очень практично для массива.

    Вы все еще должны использовать fpu для тригонометрических и других трансатлантических математических операций. Для asm существует множество трюков f80, которые действительно забавны и полезны.

    Для игр и обычного простого приложения (почти все) вы можете просто использовать double без того, чтобы кто-то умер. Но для нескольких серьезных, математических или научных приложений вы просто не можете остановить f80.

    Interesting Posts

    Требования к преобразованию информационного фрейма Spark в рамку данных Pandas / R

    Открыть с помощью нескольких файлов?

    Как сообщить интерпретатору R, как использовать прокси-сервер?

    Безопасно ли дать кому-то мой ноутбук с моей папкой Dropbox, сохраненной на нем?

    Применение параметров от объекта групповой политики к макинтошу

    FFMPEG добавляет аудио в видео, но привязывает его к длине видео

    Найти каталог / папку с CMD без знания полного пути

    Отношения «многие ко многим»

    Использование Mac в качестве беспроводного маршрутизатора и запуск всего беспроводного трафика через прокси / VPN?

    Решения для представления слайдов PDF с примечаниями ведущего на втором дисплее

    Можно ли динамически определять имена столбцов в Hibernate / JPA?

    Как изменить точку входа программы C с помощью gcc?

    Spring Security с ролями и разрешениями

    Почему бы не использовать java.util.logging?

    Могу ли я исчезать в фоновом изображении (CSS: background-image) с помощью jQuery?

    Давайте будем гением компьютера.