Авто векторизация по двойному и быстрому математике - PullRequest
5 голосов
/ 18 мая 2010

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

Ответы [ 3 ]

8 голосов
/ 17 сентября 2011

Вы не обязательно теряете точность с -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.

2 голосов
/ 14 июня 2010

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

Если вы компилируете для 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 может также помочь

0 голосов
/ 21 октября 2016

Поскольку -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 раз быстрее, для этого простого вычисления.

Предпочитаете ли вы быстрый или точный? - A7. Авто-Vectorization

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

Дополнительные показания

...