gcc openmp线程重用

时间:2012-01-31 08:26:45

标签: gcc for-loop parallel-processing openmp

我正在使用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");
        }
    }
}

1 个答案:

答案 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");
            }
        }
    }
}