我有这个C ++代码。
循环遍历矩阵,在每一行中找到min元素并从相应行的每个元素中减去它。 变量myr是所有最小元素的总和
尝试并行:
int min = 0;
int myr = 0;
int temp[SIZE][SIZE];
int size = 0;
...//some initialization
omp_set_num_threads(1);
start_time = omp_get_wtime();
#ifdef _OPENMP
#pragma omp parallel for firstprivate(min, size) reduction(+:myr)
#endif
for(int i = 0; i < size; i++){
min = INFINITY;
for(int j = 0; j < size; j++){
if (temp[i][j] < min)
min = temp[i][j];
}
myr+=min;
for(int j = 0; j < size; j++)
temp[i][j]-=min;
}
end_time = omp_get_wtime();
如果我设置omp_set_num_threads(2);
这部分代码开始工作较慢。
我的proc有2个核心
为什么2个线程的代码运行速度较慢?
答案 0 :(得分:3)
必须有一些别名或正在发生的事情。使OpenMP更简单:
int const size0 = size;
#ifdef _OPENMP
#pragma omp parallel for reduction(+:myr)
#endif
for(int i = 0; i < size0; i++){
int min = INFINITY;
int * tmp = temp[i];
for(int j = 0; j < size0; j++){
if (tmp[j] < min)
min = tmp[j];
}
for(int j = 0; j < size0; j++)
tmp[j]-=min;
myr+=min;
}
也就是说,如果可能的话,将大部分变量置于本地,const
。
答案 1 :(得分:0)
并行部分可以重新解释如下(我使用@ jens-gustedt的片段,但根据我的经验,它并没有太大的区别):
#pragma omp parallel private(myr_private) shared(myr)
{
myr_private = 0;
#pragma omp for
for(int i = 0; i < size; i++){
int min = INFINITY;
int * tmp = temp[i];
for(int j = 0; j < size; j++){
if (tmp[j] < min)
min = tmp[j];
}
for(int j = 0; j < size; j++)
tmp[j]-=min;
myr_private+=min;
}
#pragma omp critical
{
myr+=myr_private;
}
}
(这种解释直接来自http://www.openmp.org/mp-documents/OpenMP3.1.pdf例A.36.2c)。
如果线程数是n> 1,则#pragma omp parallel
创建其他线程时会有开销,然后是临界区,所有线程都应该等待。
我已经尝试了不同的矩阵尺寸,在我的有限测试中,两个线程的尺寸大于1000,速度要快得多,并且开始落后于500以下的尺寸。