gpt4 book ai didi

c++ - OMP部分中的线程数

转载 作者:可可西里 更新时间:2023-11-01 18:35:37 25 4
gpt4 key购买 nike

我的电脑有四个核心。我正在运行Ubuntu 15.10,并使用g++ -fopenmp进行编译...

我有两种不同类型的工作,并且两者是相互独立的:Work1和Work2。特别是,Work1应该在单个处理器上运行,但是Work2应该并行化。我尝试使用omp_set_num_threads():

#pragma omp parallel sections
{
#pragma omp section
{
// Should run on one processor.
omp_set_num_threads(1);
Work1();
}

#pragma omp section
{
// Should run on as many processors as possible.
omp_set_num_threads(3);
Work2();
}
}

说Work2是这样的:
void Work2(...){
#pragma omp parallel for
for (...) ...

return;
}

运行该程序时,仅使用两个处理器。显然,omp_set_num_threads()无法正常工作。使用OpenMP可以解决此问题吗?

谢谢大家,

罗德里戈

最佳答案

首先,OpenMP标准不保证这两个部分将由不同的线程执行(第2.7.2节“sections构造”):

The method of scheduling the structured blocks among the threads in the team is implementation defined.



同时执行两个工作例程的唯一可靠方法是使用基于线程ID的显式流控制:
#pragma omp parallel num_threads(2)
{
if (omp_get_thread_num() == 0)
{
omp_set_num_threads(1);
Work1();
}
else
{
omp_set_num_threads(3);
Work2();
}
}

此外, Work2()中的嵌套并行区域是否将使用多个线程,取决于多种因素的组合。这些因素包括几个内部控制变量(ICV)的值:
  • nest-var控制是否启用嵌套并行性;从OMP_NESTED的值初始化,并在运行时通过调用omp_set_nested()进行设置;
  • thread-limit-var(自OpenMP 3.0起)设置所有事件并行区域中所有OpenMP线程总数的最高限制。从OMP_THREAD_LIMIT的值初始化,并在运行时通过thread_limit子句的设置进行设置;
  • max-active-levels(自OpenMP 3.0起)限制了事件并行区域的数量深度;从OMP_MAX_ACTIVE_LEVELS的值初始化,并通过调用omp_set_max_active_levels()进行设置。

  • 如果nest-var为false,则其他ICV的值无关紧要-嵌套并行性被禁用。这是标准规定的默认值,因此必须显式启用嵌套并行性。

    如果启用了嵌套并行机制,则它只能在最高事件级别上工作,最外部的并行区域为1级,第一个嵌套并行区域为2级,依此类推。该ICV的默认值为实现支持的嵌套并行性级别。更深层次的并行区域将被禁用,即仅使用其主线程来串行执行。

    如果启用了嵌套并行性,并且特定并行区域的嵌套深度不超过max-active-levels,则它是否将并行执行取决于thread-limit-var的值。在您的情况下,任何小于4的值都将导致 Work2()无法使用三个线程执行。

    以下测试程序可用于检查这些ICV之间的相互作用:
    #include <stdio.h>
    #include <omp.h>

    void Work1(void)
    {
    printf("Work1 started by tid %d/%d\n",
    omp_get_thread_num(), omp_get_num_threads());
    }

    void Work2(void)
    {
    printf("Work2 started by tid %d/%d\n",
    omp_get_thread_num(), omp_get_num_threads());

    #pragma omp parallel for schedule(static)
    for (int i = 0; i < 3; i++)
    {
    printf("Work2 nested loop: %d by tid %d/%d\n", i,
    omp_get_thread_num(), omp_get_num_threads());
    }
    }

    int main(void)
    {
    #pragma omp parallel num_threads(2)
    {
    if (omp_get_thread_num() == 0)
    {
    omp_set_num_threads(1);
    Work1();
    }
    else
    {
    omp_set_num_threads(3);
    Work2();
    }
    }
    return 0;
    }

    样本输出:
    $ ./nested
    Work1: started by tid 0/2
    Work2: started by tid 1/2
    Work2 nested loop: 0 by tid 0/1
    Work2 nested loop: 1 by tid 0/1
    Work2 nested loop: 2 by tid 0/1

    最外面的平行区域是事件的。 Work2()中的嵌套嵌套无效,因为默认情况下禁用嵌套并行性。
    $ OMP_NESTED=TRUE ./nested
    Work1: started by tid 0/2
    Work2: started by tid 1/2
    Work2 nested loop: 0 by tid 0/3
    Work2 nested loop: 1 by tid 1/3
    Work2 nested loop: 2 by tid 2/3

    所有并行区域均处于事件状态并并行执行。
    $ OMP_NESTED=TRUE OMP_MAX_ACTIVE_LEVELS=1 ./nested
    Work1: started by tid 0/2
    Work2: started by tid 1/2
    Work2 nested loop: 0 by tid 0/1
    Work2 nested loop: 1 by tid 0/1
    Work2 nested loop: 2 by tid 0/1

    尽管启用了嵌套并行性,但只能激活一个级别的并行性,因此嵌套区域将串行执行。使用OpenMP 3.0之前的编译器,例如在GCC 4.4中,设置 OMP_MAX_ACTIVE_LEVELS无效。
    $ OMP_NESTED=TRUE OMP_THREAD_LIMIT=3 ./nested
    Work1: started by tid 0/2
    Work2: started by tid 1/2
    Work2 nested loop: 0 by tid 0/2
    Work2 nested loop: 2 by tid 1/2
    Work2 nested loop: 1 by tid 0/2

    嵌套区域是事件的,但仅由于设置 OMP_THREAD_LIMIT施加了全局线程限制,才用两个线程执行。

    如果您启用了嵌套并行性,则事件级别的数量没有限制,并且线程限制足够高,因此您的程序应该没有理由不同时使用四个CPU内核...

    ...除非进程和/或线程绑定(bind)有效。绑定(bind)控制不同OpenMP线程与可用CPU的关联性。在大多数OpenMP运行时中,默认情况下禁用线程绑定(bind),并且OS调度程序可以在认为合适的情况下自由在可用内核之间移动线程。但是,运行时通常会遵循适用于整个过程的亲和力掩码。如果您使用 taskset之类的东西来将进程固定/绑定(bind)到两个逻辑CPU,则无论产生了多少线程,它们都将在两个逻辑CPU和分时运行。在GCC中,线程绑定(bind)是通过设置 GOMP_CPU_AFFINITY和/或 OMP_PROC_BIND来控制的,而对于支持OpenMP 4.0的最新版本,则是通过设置 OMP_PLACES来控制的。

    如果未绑定(bind)可执行文件(通过检查 Cpus_allowed中的 /proc/$PID/status的值进行验证,其中 $PID是正在运行的OpenMP进程的PID),则既未设置 GOMP_CPU_AFFINITY/ OMP_PROC_BIND,也未设置 OMP_PLACES,未启用嵌套并行性,对事件并行度没有限制或强加了线程号,并且 tophtop之类的程序仍然显示仅使用了两个逻辑CPU,那么程序的逻辑有问题,而不是OpenMP环境有问题。

    关于c++ - OMP部分中的线程数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33632071/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com