#c #c #multithreading #parallel-processing #openmp
#c #c #многопоточность #параллельная обработка #openmp
Вопрос:
Я новичок в параллельном программировании OpenMP, и мне трудно оптимизировать мою функцию, которая должна возвращать -1 в случае, если столбец пуст.
Вот моя функция. Исходная матрица имеет некоторые значения и norm_matrix
строится как диагональная матрица, где каждый столбец содержит максимальное значение из соответствующего столбца исходной матрицы.
Я выполняю это для матрицы размером 1000, например, если моя исходная матрица
3 2 3 3
2 4 5 5
1 4 91 8
32 12 9 63
тогда вычисленное norm_matrix
значение будет
32 0 0 0
0 12 0 0
0 0 91 0
0 0 0 63
Если какой-либо столбец содержит все нули, то функция должна возвращать значение -1.
Вот моя функция, которую я пытаюсь оптимизировать в OpenMP:
int statistic_norm_matrix(double* source_matrix, double* norm_matrix, int size) {
int col, row;
for (col = 0; col < size; col ) {
norm_matrix[col * size col] = source_matrix[col];
for (row = 0; row < size; row ) {
norm_matrix[col * size col] = fmax(norm_matrix[col * size col], source_matrix[row * size col]);
}
if (norm_matrix[col * size col] == 0) {
printf("can't process a matrix where the max col value is 0");
return -1;
}
norm_matrix[col * size col] = (1 / norm_matrix[col * size col]);
if (col == size - 1) {
print_matrix("matrix-norm", norm_matrix, size);
}
}
return 0;
Это попытка распараллеливания с OpenMP, но я не вижу разницы в производительности:
int statistic_norm_matrix(double* source_matrix, double* norm_matrix, int size) {
int col, row;
int flag=0;
#pragma omp parallel for shared(source_matrix,norm_matrix) private(col,row)
for (col = 0; col < size; col ) {
norm_matrix[col * size col] = source_matrix[col];
for (row = 0; row < size; row ) {
norm_matrix[col * size col] = fmax(norm_matrix[col * size col], source_matrix[row * size col]);
}
if (norm_matrix[col * size col] == 0) {
printf("can't process a matrix where the max col value is 0");
flag=-1;
}
norm_matrix[col * size col] = (1 / norm_matrix[col * size col]);
}
print_matrix("matrix-norm", norm_matrix, size);
return flag;
}
Комментарии:
1. Приятно знать, что Bosch — удивительная компания 🙂
Ответ №1:
Когда norm_matrix[col * size col] == 0
вы получите ошибку деления на ноль в инструкции (1 / norm_matrix[col * size col]);
. Предполагая, что когда flag = -1
вы должны полностью выйти из параллельной области, вам следует использовать #pragma omp cancel для
int statistic_norm_matrix(double* source_matrix, double* norm_matrix, int size) {
int flag = 0;
#pragma omp parallel for shared(source_matrix,norm_matrix)
for (int col = 0; col < size; col ) {
norm_matrix[col * size col] = source_matrix[col];
for (int row = 0; row < size; row ) {
norm_matrix[col * size col] = fmax(norm_matrix[col * size col], source_matrix[row * size col]);
}
if (norm_matrix[col * size col] == 0) {
flag = -1;
#pragma omp cancel for
}
norm_matrix[col * size col] = (1 / norm_matrix[col * size col]);
}
print_matrix("matrix-norm", norm_matrix, size);
return flag;
}
Я провел быстрый тест на своей машине (т. Е. С 4 ядрами), измеряя время statistic_norm_matrix
одного, без подсчета print_matrix
, и для матрицы 1000x1000
:
1 Поток: затраченное время составляет 0,010852 (с)
Время, затрачиваемое на 2 потока, составляет 0,005325 (с)
Время, затрачиваемое на 4 потока, составляет 0,002891 (с)
для матрицы 10000x10000
:
Время, затрачиваемое на 1 поток, составляет 1.937415 (с)
Время, затрачиваемое на 2 потока, составляет 1.052908 (с)
Время, затрачиваемое на 4 потока, составляет 0,807185 (с)
Тесты с 1 потоком были выполнены без каких-либо openmp
директив. Таким образом, либо что-то не так с способом компиляции / запуска, и ваш код фактически не выполняется параллельно, либо что-то не так с тем, как вы измеряете время.
Комментарии:
1. Отмена была введена еще в OpenMP 4.0. Старые компиляторы должны ее поддерживать.