2017-02-11 4 views
2

Я пытаюсь улучшить производительность от this кода, векторизаций этой функции:Является ли это хорошей практикой для векторизации?

inline float calcHaarPattern(const int* origin, const SurfHF* f, int n) 
{ 
    double d = 0; 
    for(int k = 0; k < n; k++) 
     d += (origin[f[k].p0] + origin[f[k].p3] - origin[f[k].p1] - origin[f[k].p2])*f[k].w; 
    return (float)d; 
} 

Из моего знания, вы можете векторизацию петли, которые включают в себя точно один математической операции. В приведенном выше коде мы имеем 5 математических операций, поэтому (используя OMP):

#pragma omp simd 
for(int k = 0; k < n; k++) 
     d += (origin[f[k].p0] + origin[f[k].p3] - origin[f[k].p1] - origin[f[k].p2])*f[k].w; 

Не собираюсь работать. Однако я думал, что если перерыв цикла выше в несколько циклов с помощью одной математической операции является хорошей практикой для векторизации? Итоговый код будет:

double p0[n], p3[n], p1[n], p2[n]; 
#pragma omp simd 
for(int k = 0; k < n; k++) 
     p0[k] = origin[f[k].p0]*f[k].w; 
#pragma omp simd 
for(int k = 0; k < n; k++) 
     p3[k] = origin[f[k].p3]*f[k].w; 
#pragma omp simd 
for(int k = 0; k < n; k++) 
     p1[k] = origin[f[k].p1]*f[k].w; 
#pragma omp simd 
for(int k = 0; k < n; k++) 
     p2[k] = origin[f[k].p2]*f[k].w; 
#pragma omp simd 
for(int k = 0; k < n; k++) 
     d += p0[k]; 
#pragma omp simd 
for(int k = 0; k < n; k++) 
     d -= p1[k]; 
#pragma omp simd 
for(int k = 0; k < n; k++) 
     d -= p2[k]; 
#pragma omp simd 
for(int k = 0; k < n; k++) 
     d += p3[k]; 

Это хорошее решение, или лучше? Современные компиляторы (скажем, gcc) собираются сделать это (или лучше) вроде оптимизаций (например, включив -O3) сами (так что на самом деле нет выигрыша в производительности)?

+0

, как вы вводите некоторые неконстантные переменные, это, вероятно, будет медленнее. – felix

+1

@felix Ehm [nope] (http://stackoverflow.com/questions/6313730/does-const-correctness-give-the-compiler-more-room-for-optimization) – justHelloWorld

ответ

1

Это, как правило, плохо программирование ГПЦ практика по нескольким причинам:

  1. В эти дни обычно вы должны сделать свой код как вычислительно плотной насколько это возможно. Чтобы достичь этого, вы должны иметь более высокую Арифметическую интенсивность (AI) для цикла, когда можете. Для простоты подумайте об ИИ как о рационе [количества вычислений], разделенном на [количество байтов, перемещенных в/из памяти, чтобы выполнить эти вычисления]. . Разбирая петли, вы делаете AI для каждого цикла намного ниже в вашем случае, потому что вы больше не будете использовать те же байты для разных вычислений.
  2. (Vector- or Thread-) - Параллельное сокращение (в вашем случае переменной «d») имеет стоимость/накладные расходы, которые вы не хотите умножать на 8 или 10 (то есть по количеству произведенных вами циклов руками).
  3. Во многих случаях алгоритмы векторизации компилятора Intel/CGG могут немного улучшить оптимизацию, когда несколько полей данных одного и того же объекта данных обрабатываются в одном и том же теле цикла, а не в случае разделенных циклов.

Существует несколько теоретических преимуществ разделения циклов, но они не применяются к вашему случаю, поэтому я предоставил их на всякий случай. Цикл расщепления разумно/выгодно, когда:

  • Существует более чем один цикл осуществляется зависимость или уменьшение в же цикле.
  • В случае, если цикл split помогает избавиться от некорректного выполнения зависимостей потока данных.
  • Если вам не хватает векторных регистров для выполнения всех вычислений (для сложных алгоритмов).

Intel Advisor (упомянутый вами в предыдущих запросах) помогает проанализировать многие из этих факторов и меры AI.

Это также верно, что хорошие компиляторы «не заботятся» всякий раз, когда у вас есть один такой цикл или цикл-сплит, потому что они могут легко преобразовать один случай в другой или наоборот «на лету». Однако применимость для такого рода преобразований очень ограничена в реальных кодах, потому что для этого вам нужно знать во время компиляции дополнительную информацию: когда указатели или динамические массивы перекрываются или нет, всякий раз, когда данные выравниваются или нет и т. д. Поэтому вам не следует полагаться на преобразования компилятора и конкретную небольшую версию компилятора, но просто напишите код, подготовленный HPC, насколько вы способны.

Смежные вопросы