1

赫鲁乌,

我有一个相当大的程序,我正在尝试线程化。到目前为止,这已经成功,并且基础都按预期工作。

我现在想在嵌套模式下用级联线程做一些花哨的工作。本质上,我希望主并行区域使用较低并行区域中的任何空闲线程。

详细介绍当前系统,主并行区域启动 10 个线程。我有 12 个内核,所以我可以再使用 2 个线程。第二个并行区域发生了一些繁重的计算,我希望前两个线程达到这一点,以便在那里建立一个新团队,每个有 2 个线程。在此之后对较低并行区域的每个新条目都将继续串行。

所以,这应该如下所示。
主要区域:10 个线程启动。
下部区域:2 个新线程已启动。

线程 1:下部区域有 2 个线程。
线程 2:下部区域有 2 个线程。
线程 3-10:下部区域有 1 个线程。

请记住,这些数字是为了清楚地提供对我的情况的具体描述,而不是程序运行的绝对和唯一情况。

编码:

main() {
    ...
    ...
    omp_set_num_threads(n);
    omp_set_dynamic(x);

    #pragma omp parallel
    {
        #pragma omp for
        for (int i = 0; i < iterations; i++) {
            ...
            Compute();
            ...
        }
    }
}    

在计算中

bool Compute() {
    ...
    float nThreads = omp_get_thread_limit() - omp_get_num_threads();
    nThreads = ceil(nThreads / omp_get_num_threads());
    omp_set_num_threads((int)nThreads);
    #pragma omp parallel
    {
        ...
        #pragma omp for
        for (int i = 0; i < nReductSize; i++) {
            ...
        }
    }
}

现在,我的问题是为整个程序设置最高限制(即 OMP_THREAD_LIMIT)只能在程序外部工作。使用

export OMP_THREAD_LIMIT=5  

从 bash 命令行效果很好。但我想在内部做。到目前为止,我已经尝试过

putenv("OMP_THREAD_LIMIT=12");
setenv("OMP_THREAD_LIMIT", "12", 1);

但是当我调用 omp_get_thread_limit() 或 getenv("OMP_THREAD_LIMIT") 时,我会得到古怪的返回值。即使我使用导出设置变量,调用 getenv("OMP_THREAD_LIMIT"); 返回 0。
所以,我想请你帮忙:如何在运行时正确设置 OMP_THREAD_LIMIT?

这是我设置线程默认值的主要功能。它在任何线程发生之前很好地执行:

#ifdef _OPENMP
    const char *name = "OMP_THREAD_LIMIT";
    const char *value = "5";
    int overwrite = 1;
    int success = setenv(name, value, overwrite);
    cout << "Var set (0 is success): " << success << endl;
#endif

哦,setenv 报告设置变量成功。

编译器说
gcc44 (GCC) 4.4.7 20120313 (Red Hat 4.4.7-1)

标志
CCFLAGS = -c -O0 -fopenmp -g -msse -msse2 -msse3 -mfpmath=sse -std=c++0x

OpenMP 版本是 3.0。

4

3 回答 3

2

这是 OpenMP 的正确实现,它忽略了程序内部的环境变化。如 OpenMP 3.1 标准第 159 页所述:

程序启动后对环境变量的修改,即使由程序本身修改,也会被 OpenMP 实现忽略。

您正在按照本段中所说的进行操作。

OpenMP 仅允许通过omp_set_*函数更改此类参数,但 thread-limit-var ICV 没有此类函数:

但是,可以在执行 OpenMP 程序期间通过使用适当的指令子句或 OpenMP API 例程来修改某些 ICV 的设置。

我认为,您可以使用num_threads子句 of#pragma omp parallel来实现您想要的。

于 2013-09-06T12:53:24.510 回答
2

程序启动后,无法使用OMP_THREAD_LIMIT(或任何其他环境变量)更改 OpenMP 的行为;OMP_*这些是供用户使用的。OMP_THREAD_LIMIT您可以让用户通过设置然后调用您的程序的脚本来调用您的程序,但这可能不是您在这种情况下需要做的。

OMP_NUM_THREADS, omp_set_num_threads, 和num_threads子句通常用于设置在一个区域中运行的线程数。

于 2013-09-07T01:58:46.507 回答
0

这可能是题外话,但您可能想尝试 openmp collapse 而不是在这里手工制作。

于 2013-09-07T13:00:43.813 回答