Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Автоматический параллелизатор и автоматический векторизатор обеспечивают автоматическое повышение производительности циклов в коде.
Автоматический параллелизатор
Параметр компилятора /Qpar активирует автоматическую параллелизацию циклов в вашем коде. Если установить этот флажок без изменения существующего кода, компилятор проанализирует код, чтобы выявить циклы, выполнение которых можно ускорить благодаря параллелизации. Компилятор может обнаруживать циклы, которые выполняют мало работы и не принесут заметного выигрыша от параллелизации. Каждая ненужная параллелизация может вызвать создание пула потоков, дополнительную синхронизацию или другую обработку, что может замедлить производительность, вместо ее повышения. Поэтому компилятор осторожно подходит к выбору циклов для параллелизации. Например, рассмотрим случай, в котором верхняя граница цикла неизвестна во время компиляции.
void loop_test(int u) {
for (int i=0; i<u; ++i)
A[i] = B[i] * C[i];
}
Так как u может быть небольшим значением, компилятор не будет автоматически параллелизировать этот цикл. Тем не менее, вы все же можете захотеть его параллелизовать, потому что знаете, что значение u всегда будет большим. Чтобы включить автоматическую параллелизацию, укажите #pragma loop(hint_parallel(n)), где n представляет количество потоков для параллелизации. В приведенном ниже примере компилятор попытается выполнить параллелизацию цикла по 8 потокам.
void loop_test(int u) {
#pragma loop(hint_parallel(8))
for (int i=0; i<u; ++i)
A[i] = B[i] * C[i];
}
Как и для всех директив pragma, поддерживается также альтернативный синтаксис __pragma(loop(hint_parallel(n))) pragma.
Существует несколько циклов, которые компилятор не может параллелизировать, даже если требуется. Приведем пример:
#pragma loop(hint_parallel(8))
for (int i=0; i<upper_bound(); ++i)
A[i] = B[i] * C[i];
Функция upper_bound() может меняться при каждом вызове. Так как верхняя граница не может быть известна, компилятор может выпустить диагностическое сообщение, объясняющее, почему он не может параллелизировать этот цикл. В приведенном ниже примере демонстрируется цикл, в котором может выполняться параллелизация, цикл, в котором не может выполняться параллелизация, синтаксис компилятора для командной строки и выходные данные компилятора для каждого параметра командной строки:
int A[1000];
void test() {
#pragma loop(hint_parallel(0))
for (int i=0; i<1000; ++i) {
A[i] = A[i] + 1;
}
for (int i=1000; i<2000; ++i) {
A[i] = A[i] + 1;
}
}
При компиляции с помощью этой команды:
cl d:\myproject\mylooptest.cpp /O2 /Qpar /Qpar-report:1
получаются следующие выходные данные:
--- Analyzing function: void __cdecl test(void)
d:\myproject\mytest.cpp(4) : loop parallelized
Компиляция с помощью этой команды:
cl d:\myproject\mylooptest.cpp /O2 /Qpar /Qpar-report:2
получаются следующие выходные данные:
--- Analyzing function: void __cdecl test(void)
d:\myproject\mytest.cpp(4) : loop parallelized
d:\myproject\mytest.cpp(4) : loop not parallelized due to reason '1008'
Обратите внимание на разницу в результатах между двумя параметрами /Qpar-report (уровень отчетности Auto-Parallelizer).
/Qpar-report:1 выводит сообщения параллелизатора только для тех циклов, параллелизация которых успешно выполнена.
/Qpar-report:2 выводит сообщения параллелизатора как для успешных, так и для неуспешных параллелизаций цикла.
Дополнительные сведения о кодах причин и сообщениях см. в разделе Vectorizer и Parallelizer Messages.
Автоматический векторизатор
Автоматический векторизатор анализирует циклы в коде и использует векторные регистры и инструкции на целевом компьютере для их выполнения, если это возможно. Это может повысить производительность кода. Компилятор предназначен для инструкций SSE2, AVX и AVX2 в процессорах Intel или AMD, а также инструкции NEON для процессоров ARM в соответствии с параметром /arch .
Автоматический векторизатор может создавать инструкции, отличные от указанных в переключателе /arch. Эти инструкции защищены проверкой среды выполнения, гарантирующей, что код все еще работает правильно. Например, при компиляции /arch:SSE2 могут быть выданы инструкции SSE4.2. При проверке среды выполнения проверяется, что инструкция SSE4.2 доступна на целевом процессоре, и осуществляется переход к версии цикла, отличной от SSE4.2, если процессор не поддерживает эти инструкции.
По умолчанию автоматический векторизатор включен. Если вы хотите сравнить производительность кода под векторизацией, можно использовать цикл #pragma (no_vector) для отключения векторизации любого заданного цикла.
#pragma loop(no_vector)
for (int i = 0; i < 1000; ++i)
A[i] = B[i] + C[i];
Как и во всех директивах pragma, также поддерживается альтернативный синтаксис __pragma(loop(no_vector)).
Как и при автоматическом параллелизаторе, можно указать параметр командной строки /Qvec-report (уровень отчетов автовекторизатора), чтобы сообщить только о векторизованных циклах (/Qvec-report:1или как успешно, так и неудачно векторизованных циклах)./Qvec-report:2
Дополнительные сведения о кодах причин и сообщениях см. в разделе Vectorizer и Parallelizer Messages.
Пример, демонстрирующий, как работает векторизатор на практике, можно найти в Project Austin: часть 2 из 6: Заворачивание страницы.
См. также
цикл
Параллельное программирование в машинном коде
/Qpar (автоматический параллелизатор)
/Qpar/report (уровень отчетности автоматического параллелизатора)
/Qvec-report (уровень отчетов автоматического векторизатора)
Сообщения векторизатора и параллелизатора