(1) Вложенный параллелизм в OpenMP: http://docs.oracle.com/cd/E19205-01/819-5270/aewbc/index.html
Вам необходимо включить вложенный параллелизм, установив OMP_NESTED
или omp_set_nested
, потому что многие реализации отключают эту функцию по умолчанию, даже некоторые реализации этого не сделали.Не поддерживает вложенный параллелизм полностью.Если этот параметр включен, то при каждом достижении parallel for
OpenMP будет создавать количество потоков, как определено в OMP_NUM_THREADS
.Таким образом, если двухуровневый параллелизм, общее количество потоков будет N ^ 2, где N = OMP_NUM_THREADS
.
Такой вложенный параллелизм приведет к переподписке (т. Е. Число занятых потоков больше, чемядра), что может ухудшить ускорение.В крайнем случае, когда вложенный параллелизм вызывается рекурсивно, потоки могут быть раздутыми (например, создавать потоки 1000 с), и компьютер просто тратит время на переключение контекста.В этом случае вы можете динамически контролировать количество потоков, задав omp_set_dynamic
.
(2) Пример умножения матрицы на вектор: код будет выглядеть так:
// Input: A(N by M), B(M by 1)
// Output: C(N by 1)
for (int i = 0; i < N; ++i)
for (int j = 0; j < M; ++j)
C[i] += A[i][j] * B[j];
В общем, распараллеливание внутренних циклов, когда возможны внешние циклы, является плохим из-за разветвления / объединения потоков.(хотя во многих реализациях OpenMP предварительно создаются потоки, все же требуется, чтобы некоторые из них отправляли задачи в потоки и вызывали неявный барьер в конце параллельного потока)
Вас беспокоит случай, когда N <# ЦП,Да, верно, в этом случае ускорение будет ограничено N, и использование вложенного параллелизма определенно принесет пользу.</p>
Однако тогда код вызовет переподписку, если N достаточно велико.Я просто думаю о следующих решениях:
- Изменение структуры цикла так, чтобы существовал только одноуровневый цикл.(Это выглядит выполнимо)
- Специализация кода: если N маленькое, тогда делайте вложенный параллелизм, иначе не делайте этого.
- Вложенный параллелизм с
omp_set_dynamic
.Но, пожалуйста, убедитесь, что omp_set_dynamic
контролирует количество потоков и их активность.Реализации могут отличаться.