Существуют ли какие-либо директивы препроцессора, управляющие развертыванием цикла?

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

6

Решение

Для MSVC есть только подсказка о независимости вектора: http://msdn.microsoft.com/en-us/library/hh923901.aspx

#pragma loop( ivdep )

Для многих других компиляторов, таких как Intel/IBM, Есть несколько практических советов по оптимизации цикла:

#pragma unroll
#pragma loop count N
#pragma ivdep

Существует ветка с людьми из MSVC ++ о эвристическом развертывании: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/d0b225c2-f5b0-4bb9-ac6a-4d4f61f7cb17/

VC пытается сбалансировать скорость выполнения и размер кода. Вы можете изменить баланс, используя флаги / O1 или / O2, но даже при оптимизации скорости VC также пытается сохранить размер кода.

По сути, развертывание увеличит размер кода, поэтому он может быть ограничен в режимах Os и O1 (таблица режимов)

PS: Pragma выглядит как директива препроцессора, но это не так. Это директива для компилятора, и она игнорируется препроцессором.

6

Другие решения

В случае Intel Compiler:

#pragma loop count N помогает компилятору использовать лучшую стратегию для векторизации цикла. Это экономит время. Таким образом, мы можем сказать, что это помогает развернуть цикл.
Примеры:

#pragma loop_count min(n),max(n),avg(n)

#pragma unroll (n) работает только при использовании с флагом -O3, вы можете использовать следующую стратегию, чтобы развернуть цикл в соответствии с целевым процессором.

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

В случаях, когда развертывание влияет на производительность, например: цикл с 20 итерациями с длиной вектора 16, приводит к 1 циклу, который выполняет 16 операций одновременно, и к циклу остатка, который выполняет 4 последовательно.
Чтобы избежать цикла остатка, сгенерированного компилятором, мы можем использовать перед циклом:

#pragma vector novecremainder //or -mP2OPT_hpo_vec_peel = F to disable peel and remainder loops (compiler internal option)

или же

#pragma nounroll //where unrolling is not worth at all

Просто чтобы уточнить #pragma ivdep :

  • Он дает конкретные советы по изменению эвристики компилятора относительно зависимостей и должен использоваться только тогда, когда мы знаем, что предполагаемые зависимости безопасны для игнорирования.
  • Самое главное, он переопределяет потенциальные зависимости, но компилятор все еще выполняет анализ зависимостей, попробуйте #pragma simd для векторизации независимо от любого анализа.

Надеюсь это поможет.

2

По вопросам рекламы [email protected]