Влияние неделимых размеров цикла во время выполнения на openMP SIMD - PullRequest
0 голосов
/ 25 февраля 2019

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

У меня есть фрагмент кода, который можно сократить до серии циклов, похожих на следующие:

#pragma omp parallel for simd
for(int i = 0; i < a*b*c; i++)
{
    array1[i] += array2[i] * array3[i];
}

Теперь большинство примеров использования SIMD, с которыми я столкнулся, имеют,b и c исправлены во время компиляции, что позволяет провести оптимизацию.Однако мой код требует, чтобы значения ab и c определялись во время выполнения.

Допустим, что для случая компьютера, который я использую, регистр может соответствовать 4 значениям, и что значение b c равно 127. Я понимаю, что время компиляции для этогочто компилятор будет векторизовать все, что полностью делится на 4, а затем сериализовать все остальное (пожалуйста, исправьте это, если я ошибаюсь).Однако это когда компилятор полностью знает проблему.Если бы я теперь разрешил выбор времени выполнения a, b и c и достиг значения 127, как бы происходила векторизация?Наивно я предположил бы, что закулисный код достаточно умен, чтобы понять, что это может произойти, имеет как последовательный, так и векторный код и вызывает наиболее подходящий.Тем не менее, поскольку это предположение, я был бы признателен кому-то более знающему по этому вопросу, чтобы просветить меня дальше, поскольку я не хочу случайных переполнений или отсутствия обработки данных из-за недопонимания.

На случай, если это важно, я использую OpenMP 4.0 с компилятором C gcc, хотя я надеюсь, что это не изменит ваш ответ, так как я всегда буду пытаться использовать последнюю версию OpenMP и, к сожалению, возможно, потребуетсярегулярно меняйте компилятор.

1 Ответ

0 голосов
/ 25 февраля 2019

Обычно компилятор разворачивается за пределы длины simd.Для получения оптимальных результатов, особенно с gcc, вы должны указать этот коэффициент развертывания, например --param max-unroll-times = 2 (если вы не ожидаете гораздо более длинных циклов).при длине simd 4 цикл будет потреблять 8 итераций за раз, оставляя остаток.gcc построил бы остаточный цикл, похожий на устройство Даффа, который мог бы иметь 15 итераций, и вычислил бы, куда переходить во время выполнения.Компилятор Intel по-другому обрабатывает векторизованный цикл остатков.Предположим, что у вас есть 2 доступные ширины simd, остаток цикла будет использовать более короткую ширину без развертывания, так что серийная часть будет как можно короче.При компиляции для общего случая невыровненных данных на обоих концах имеется цикл остатка, причем в начале цикл ограничен длиной, необходимой для выравнивания сохраненных значений.С комбинацией omp параллельно simd ситуация становится более сложной;как правило, куски петли должны различаться по размеру, и можно утверждать, что внутренние куски могут быть настроены для выравнивания, причем концевые куски меньше (обычно это не делается).

...