#c #for-loop #openmp #nested-loops #intrinsics
#c #цикл for #openmp #вложенные циклы #встроенные функции
Вопрос:
Итак, у меня возникли небольшие проблемы с поиском наилучшего способа распараллеливания этих циклов for с использованием openmp. Я предполагаю, что наибольшая скорость была бы достигнута при распараллеливании среднего цикла, как я делаю здесь:
for(i = 0; i < m/16*16; i =16){
#pragma omp parallel for
for(j = 0; j < m; j ){
C_column_start = C i j*m;
c_1 = _mm_loadu_ps(C_column_start);
c_2 = _mm_loadu_ps(C_column_start 4);
c_3 = _mm_loadu_ps(C_column_start 8);
c_4 = _mm_loadu_ps(C_column_start 12);
for (k=0; k < n; k =2){
A_column_start = A k*m;
a_1 = _mm_loadu_ps(A_column_start i);
a_2 = _mm_loadu_ps(A_column_start i 4);
a_3 = _mm_loadu_ps(A_column_start i 8);
a_4 = _mm_loadu_ps(A_column_start i 12);
b_1 = _mm_load1_ps(A_column_start j);
mul_1 = _mm_mul_ps(a_1, b_1);
mul_2 = _mm_mul_ps(a_2, b_1);
mul_3 = _mm_mul_ps(a_3, b_1);
mul_4 = _mm_mul_ps(a_4, b_1);
c_4 = _mm_add_ps(c_4, mul_4);
c_3 = _mm_add_ps(c_3, mul_3);
c_2 = _mm_add_ps(c_2, mul_2);
c_1 = _mm_add_ps(c_1, mul_1);
A_column_start =m;
a_1 = _mm_loadu_ps(A_column_start i);
a_2 = _mm_loadu_ps(A_column_start i 4);
a_3 = _mm_loadu_ps(A_column_start i 8);
a_4 = _mm_loadu_ps(A_column_start i 12);
b_1 = _mm_load1_ps(A_column_start j);
mul_1 = _mm_mul_ps(a_1, b_1);
mul_2 = _mm_mul_ps(a_2, b_1);
mul_3 = _mm_mul_ps(a_3, b_1);
mul_4 = _mm_mul_ps(a_4, b_1);
c_4 = _mm_add_ps(c_4, mul_4);
c_3 = _mm_add_ps(c_3, mul_3);
c_2 = _mm_add_ps(c_2, mul_2);
c_1 = _mm_add_ps(c_1, mul_1);
}
_mm_storeu_ps(C_column_start, c_1);
_mm_storeu_ps(C_column_start 4, c_2);
_mm_storeu_ps(C_column_start 8, c_3);
_mm_storeu_ps(C_column_start 12, c_4);
}
}
Однако в настоящее время это почти не ускоряет меня. Любые советы были бы замечательными. Я застрял на довольно долгое время.
Комментарии:
1. Вы пытались распараллелить внешний цикл?
2. Я сделал. Это также не дает мне никакого ускорения.
Ответ №1:
Прежде всего, вы уверены, что циклы распараллеливаются? Каков диапазон значений m
?
Когда все три вложенных цикла распараллеливаются и m
достаточно велики (скажем, по крайней мере 16 или около того), тогда распараллеливание самого внешнего цикла будет наиболее выгодным. Распараллеливание внутренних циклов может привести к серьезным накладным расходам на разветвление omp parallel for
.
Для низкого ускорения, вот некоторый контрольный список:
- Вы уверены, что все ядра используются? Проверьте что-то вроде диспетчера задач. Поскольку синхронизация отсутствует, за исключением неявного барьера
omp parallel for
, должны использоваться все ядра. m
Это огромное число? И какова длина вычислений? Еслиm
объем вычислений огромен, а объем вычислений невелик, параллельные накладные расходы из-заomp parallel for
могут свести на нет преимущества распараллеливания. При распараллеливании внутреннего цикла количество отключений (например,m
) не должно быть огромным.- Причиной может бытьложный общий доступ. Если ваш код изменяет большой объем памяти, это может привести к ложному распределению и ускорению может быть нанесен ущерб.