我正在使用gcc的openmp实现来尝试并行化程序。基本上,赋值是添加omp pragma以获得找到amicable numbers的程序的加速。
给出了原始的连续程序(如下所示,除了我最后添加注释的3行)。我们必须首先只是外部循环,然后只是内部循环。外环非常简单,对于给定数量的处理器,我接近理想的加速。对于内循环,我的性能比原始的串行程序差得多。基本上我要做的是减少sum变量。
看看cpu的使用情况,我每个核心只使用了~30%。可能是什么导致了这个?程序是否在每次遇到omp parallel for子句时不断创建新线程?在减少障碍方面,还有更多的开销吗?或者它可能是内存访问问题(例如缓存抖动)?从我阅读的内容来看,大多数openmp线程的实现都会被超时重用(例如pooled),所以我不太确定第一个问题是什么问题。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <omp.h>
#define numThread 2
int main(int argc, char* argv[]) {
int ser[29], end, i, j, a, limit, als;
als = atoi(argv[1]);
limit = atoi(argv[2]);
for (i = 2; i < limit; i++) {
ser[0] = i;
for (a = 1; a <= als; a++) {
ser[a] = 1;
int prev = ser[a-1];
if ((prev > i) || (a == 1)) {
end = sqrt(prev);
int sum = 0;//added this
#pragma omp parallel for reduction(+:sum) num_threads(numThread)//added this
for (j = 2; j <= end; j++) {
if (prev % j == 0) {
sum += j;
sum += prev / j;
}
}
ser[a] = sum + 1;//added this
}
}
if (ser[als] == i) {
printf("%d", i);
for (j = 1; j < als; j++) {
printf(", %d", ser[j]);
}
printf("\n");
}
}
}
答案 0 :(得分:7)
OpenMP thread teams
在进入并行部分时被实例化。实际上,这意味着每次内循环开始时都会重复创建线程。
要启用线程重用,请使用更大的并行部分(以控制团队的生命周期)并特别控制外部/内部循环的并行,如下所示:
使用此修复程序test.exe 1 1000000
的执行时间从43秒降至22秒(并且线程数反映了numThreads定义的值+ 1
PS 或许说明显而易见的是,内部循环的并行化似乎不是一个合理的性能指标。但这可能是这项工作的重点,我不会批评这个问题。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <omp.h>
#define numThread 2
int main(int argc, char* argv[]) {
int ser[29], end, i, j, a, limit, als;
als = atoi(argv[1]);
limit = atoi(argv[2]);
#pragma omp parallel num_threads(numThread)
{
#pragma omp single
for (i = 2; i < limit; i++) {
ser[0] = i;
for (a = 1; a <= als; a++) {
ser[a] = 1;
int prev = ser[a-1];
if ((prev > i) || (a == 1)) {
end = sqrt(prev);
int sum = 0;//added this
#pragma omp parallel for reduction(+:sum) //added this
for (j = 2; j <= end; j++) {
if (prev % j == 0) {
sum += j;
sum += prev / j;
}
}
ser[a] = sum + 1;//added this
}
}
if (ser[als] == i) {
printf("%d", i);
for (j = 1; j < als; j++) {
printf(", %d", ser[j]);
}
printf("\n");
}
}
}
}