Я использую функцию ступенчатого разностного разностного разрыва 8-го порядка (для двумерного акустического волнового уравнения), показанного ниже.Местоположение процессора Intel __assume влияет на производительность
Я наблюдаю существенное (до 25%) увеличение производительности от размещения инструкции Intel __assume
во внутреннем цикле, по сравнению с размещением ее в начале тела функции. (Это происходит независимо от количества потоков OpenMP).
Код компилируется компилятором Intel 2016-update1, Linux, с опцией оптимизации -O3 и для архитектуры с поддержкой AVX (Xeon E5-2695 v2).
Это проблема с компилятором?
/* Finite difference, 8-th order scheme for acoustic 2D equation.
p - current pressure
q - previous and next pressure
c - velocity
n0 x n1 - problem size
p1 - stride
*/
void fdtd_2d(float const* const __restrict__ p,
float * const __restrict__ q,
float const* const __restrict__ c,
int const n0,
int const n1,
int const p1)
{
// Stencil coefficients.
static const float C[5] = { -5.6944444e+0f, 1.6000000e+0f, -2.0000000e-1f, 2.5396825e-2f, -1.7857143e-3f };
// INTEL OPTIMIZER PROBLEM?
// PLACING THE FOLLOWING LINE INSIDE THE LOOP BELOW
// INSTEAD OF HERE SPEEDS UP THE CODE!
// __assume(p1 % 16 == 0);
#pragma omp parallel for default(none)
for (int i1 = 0; i1 < n1; ++i1)
{
float const* const __restrict__ ps = p + i1 * p1;
float * const __restrict__ qs = q + i1 * p1;
float const* const __restrict__ cs = c + i1 * p1;
#pragma omp simd aligned(ps, qs, cs : 64)
for (int i0 = 0; i0 < n0; ++i0)
{
// INTEL OPTIMIZER PROBLEM?
// PLACING THE FOLLOWING LINE HERE
// INSTEAD OF THE ABOVE SPEEDS UP THE CODE!
__assume(p1 % 16 == 0);
// Laplacian cross stencil:
// center and 4 points up, down, left and right from the center
auto lap = C[0] * ps[i0];
for (int r = 1; r <= 4; ++r)
lap += C[r] * (ps[i0 + r] + ps[i0 - r] + ps[i0 + r * p1] + ps[i0 - r * p1]);
qs[i0] = 2.0f * ps[i0] - qs[i0] + cs[i0] * lap;
}
}
}
Является ли первый комментарий строго точным? Если вы раскомментировали '__assume' вне цикла, он бы замедлялся, даже если вы оставили' __assume' внутри цикла активным? И с тем, что в цикле прокомментировал, будет ли ранний '__assume' делать ваш код медленнее, чем без' __assume' вообще? Из текста это звучит не так, поэтому я думаю, что ваши комментарии «все-шапки», возможно, говорят «не помогают здесь», а «только помогает здесь, а не за пределами цикла», или что-то в этом роде. –
@PeterCordes Да, я попытался разместить '__assume' либо сверху, либо внутри цикла, но не в обоих местах одновременно. – user2052436
Работает ли этот код, и этот вопрос все еще случается с ICC13? Если это так, вы можете поместить свой код [на godbolt] (http://goo.gl/3nrETr). Я пробовал, но он не компилируется; может быть, есть компиляция, которую мне не хватает? В противном случае просто отредактируйте разборку для обеих версий в вопросе, чтобы мы могли видеть, какая разница в автообвещении. Конечно, это не скажет нам * почему * он не может оптимизировать, когда '__assume' выходит за рамки OpenMP-прагм, просто * как *. Более медленный случай, вероятно, просто испускает больше кода для обработки несоосности для 'r * p1'. –