gcc openmp线程重用

Jam*_*ter 3 parallel-processing gcc for-loop openmp

我正在使用gcc的openmp实现来尝试并行化程序.基本上,赋值是添加omp pragma以获得找到友好数字的程序的加速.

给出了原始的串行程序(如下所示,除了我最后添加注释的3行).我们必须首先只是外部循环,然后只是内部循环.外环非常简单,对于给定数量的处理器,我接近理想的加速.对于内循环,我的性能比原始的串行程序差得多.基本上我要做的是减少sum变量.

看看cpu的使用情况,我每个核心只使用了~30%.可能是什么导致了这个?程序是否在每次遇到omp parallel for子句时不断创建新线程?在减少障碍方面,还有更多的开销吗?或者它可能是内存访问问题(例如缓存抖动)?从我读到的大多数openmp线程的实现得到加速重用(例如汇集),所以我不太确定第一个问题是什么是错的.

#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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

seh*_*ehe 7

thread teams在进入并行部分时实例化OpenMP .实际上,这意味着每次内循环开始时都会重复创建线程.

要启用线程重用,请使用更大的并行部分(以控制团队的生命周期)并特别控制外部/内部循环的并行,如下所示:

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");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)