Вопрос

Почему это обязательно для использования -ffast-math с помощью g ++ для достижения векторизации циклов используется doubleс?Мне не нравится -ffast-math потому что я не хочу терять точность.

Это было полезно?

Решение

Вы не обязательно теряете точность с -ffast-math. Отказ Это только влияет на обработку NaN, Inf и т. Д. И порядок, в котором выполняется операции.

Если у вас есть определенный кусок кода, в котором вы не хотите, чтобы GCC изменить или упростить вычисления, вы можете пометить переменные как использование с помощью asm утверждение.

Например, следующий код выполняет операцию округления на f. Отказ Тем не менее, два f += g и f -= g Операции, вероятно, будут оптимизированы GCC:

static double moo(double f, double g)                                      
{                                                                          
    g *= 4503599627370496.0; // 2 ** 52                                    
    f += g;                                                                
    f -= g;                                                                
    return f;                                                            
}                                                                     

На x86_64 вы можете использовать это asm Заявление для инструктажа GCC не выполнять эту оптимизацию:

static double moo(double f, double g)                                      
{                                                                          
    g *= 4503599627370496.0; // 2 ** 52                                    
    f += g;                                                                
    __asm__("" : "+x" (f));
    f -= g;
    return f;
}

Вам нужно будет адаптировать это для каждой архитектуры, к сожалению. На PowerPC, используйте +f вместо +x.

Другие советы

Очень вероятно, потому что векторизация означает, что у вас могут быть разные результаты или могут означать, что вы пропускаете сигналы / исключения с плавающей точкой.

Если вы собираетесь для 32-битного X86, затем GCC и G ++ по умолчанию, чтобы использовать X87 для математики с плавающей точкой, на 64-битах они по умолчанию для SSE, однако X87 может и приведет к разным значениям для тех же вычислений, поэтому он вряд ли G ++ рассмотрит вектору, если он не может гарантировать, что вы получите те же результаты, если вы не используете -ffast-math Или некоторые флаги, которые он включается.

В основном это сводится к среде с плавающей точкой для векторизованного кода, может быть не такой, как тот, который для неизолизованного кода, иногда в том, что это важно, если различия не имеют значения для вас, что-то вроде

-fno-math-errno -fno-trapping-math -fno-signaling-nans -fno-rounding-math

Но сначала посмотрите эти варианты и убедитесь, что они не повлияют на правильность вашей программы. -ffinite-math-only может помочь также

Потому что -ffast-math позволяет изменение порядка операндов это позволяет векторизовать множество кодов.

Например, чтобы вычислить это

sum = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + … a[99]

компилятор является требуемый чтобы сделать дополнения последовательно без -ffast-math, потому что математика с плавающей запятой не является ни коммутативной, ни ассоциативной.

Это по той же причине почему компиляторы не могут оптимизировать a*a*a*a*a*a Для (a*a*a)*(a*a*a) без -ffast-math

Это означает, что векторизация недоступна, если у вас нет очень эффективного добавления горизонтальных векторов.

Однако , если -ffast-math если включено, выражение может быть вычислено вот так (Посмотрите на A7. Auto-Vectorization)

sum0 = a[0] + a[4] + a[ 8] + … a[96]
sum1 = a[1] + a[5] + a[ 9] + … a[97]
sum2 = a[2] + a[6] + a[10] + … a[98]
sum3 = a[3] + a[7] + a[11] + … a[99]
sum’ = sum0 + sum1 + sum2 + sum3

Теперь компилятор может легко векторизовать его, добавив каждый столбец параллельно, а затем выполнить горизонтальное добавление в конце

Делает sum’ == sum?Только если (a[0]+a[4]+…) + (a[1]+a[5]+…) + (a[2]+a[6]+…) + ([a[3]+a[7]+…) == a[0] + a[1] + a[2] + … Это справедливо в соответствии с ассоциативностью, которой поплавки не придерживаются все время.Уточняющий /fp:fast позволяет компилятору преобразовать ваш код, чтобы он выполнялся быстрее – до 4 раз быстрее, для этого простого вычисления.

Вы предпочитаете Быстроту или Точность? - А7.Автоматическая векторизация

Это может быть включено с помощью -fassociative-math флаг в gcc

Дальнейшие показания

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top