OpenMP set_num_threads() 不起作用。

48

我正在使用C++中的OpenMP编写并行程序。

我想使用omp_set_num_threads()控制程序中线程的数量,但它不起作用。

#include <iostream>
#include <omp.h>
#include "mpi.h"

using namespace std;

int myrank;
int groupsize;
double sum;
double t1,t2;
int n = 10000000;

int main(int argc, char *argv[])
{
    MPI_Init( &argc, &argv);
    MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
    MPI_Comm_size(MPI_COMM_WORLD,&groupsize);

    omp_set_num_threads(4);

    sum = 0;
    #pragma omp for  reduction(+:sum)
    for (int i = 0; i < n; i++)
        sum+= i/(n/10);

    cout<<"sum="<<sum<<endl;
    cout<<"threads="<<omp_get_num_threads()<<endl;

    MPI_Finalize();
    return 0;
}
程序输出:
sum = 4.5e+007
threads=1

如何控制线程的数量?

4个回答

117
除了在并行区域外调用omp_get_num_threads()之外,在您的情况下调用omp_set_num_threads()仍然不能保证OpenMP运行时将确切指定数量的线程。 omp_set_num_threads()用于覆盖环境变量OMP_NUM_THREADS的值,它们都控制OpenMP为所有并行区域生成的线程团队的大小上限(对于OMP_NUM_THREADS)或任何后续并行区域的大小上限(在调用omp_set_num_threads()之后)。 还有一种称为动态团队的东西,如果运行时系统认为更合适,仍然可以选择较少数量的线程。 您可以通过调用omp_set_dynamic(0)或将环境变量OMP_DYNAMIC设置为false来禁用动态团队。
为强制执行给定数量的线程,应禁用动态团队,并使用omp_set_num_threads()指定所需的线程数:
omp_set_dynamic(0);     // Explicitly disable dynamic teams
omp_set_num_threads(4); // Use 4 threads for all consecutive parallel regions
#pragma omp parallel ...
{
    ... 4 threads used here ...
}

或使用 num_threads OpenMP 子句:

omp_set_dynamic(0);     // Explicitly disable dynamic teams
// Spawn 4 threads for this parallel region only
#pragma omp parallel ... num_threads(4)
{
    ... 4 threads used here ...
}

但是通过更改线程数量和设置omp_set_dynamic(0),我无法获得任何加速。 - Nurlan
10
首先,串行版本在我的CPU上需要50毫秒。由于OpenMP的开销,您不能指望这样快速的代码有加速效果。将循环中的迭代次数增加100倍。其次,您原始代码中缺少并行区域。您编写了“#pragma omp for ...”,但应该是“#pragma omp parallel for ...”。第三,您正在混合使用MPI和OpenMP。您确定自己明确知道自己在做什么吗? - Hristo Iliev
@HristoIliev 用户是否可以动态控制线程数?即使用变量而不是硬编码的“4”。 - manatttta
@manatttta,是的。每次程序执行时遇到并行区域时,该值都会传递给OpenMP运行库,因此使用变量可以按预期工作。 - Hristo Iliev
使用 num_threads OpenMP 子句选项,是否可以使用变量而不是硬编码数字?例如:int n = 4; #pragma omp parallel ... num_threads(n) - Omar Haque
2
@OmarHaque,是的,num_threads子句也接受变量,因此可以在运行时控制线程数。 - Hristo Iliev

30

omp_get_num_threads()函数返回当前执行并行区域的团队中的线程数。由于您在并行区域之外调用它,因此它返回1


我可以确认这一点。GNU实现的omp文档也有记录。https://gcc.gnu.org/onlinedocs/libgomp/omp_005fget_005fnum_005fthreads.html - Guibao Wang

8
根据GCC手册中关于omp_get_num_threads的说明

在程序的串行部分,omp_get_num_threads返回1。

因此,这段代码:
cout<<"sum="<<sum<<endl;
cout<<"threads="<<omp_get_num_threads()<<endl;

应该改成像这样的内容:
#pragma omp parallel
{
    cout<<"sum="<<sum<<endl;
    cout<<"threads="<<omp_get_num_threads()<<endl;
}

我使用的代码也遵循了Hristo的建议,禁用了动态团队。

4

我曾面临同样的问题。解决方法如下:

右键点击源程序 > 属性 > 配置属性 > C/C++ > 语言 > 现在将Open MP支持标志更改为“是”...

你会得到所需的结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接