【问题标题】:OpenMP - Manage multiple calls to block with parallel forOpenMP - 管理多个调用以并行阻止
【发布时间】:2017-11-08 22:53:19
【问题描述】:

假设我有一个程序,其函数名为run(),该函数将执行for loop 并在其中做一些工作。

因为我想利用我所有的 CPU 内核,我使用 OpenMP#pragma omp parallel for 来并行化它。

现在,问题是这个run()函数是从多个线程调用的,当有大量线程同时调用run()时,我会有巨大的性能损失,因为会有很多OpenMP threads 来自每个 parallel for pragma 调用。

为了说明,我有线程 A 和线程 B,我的 CPU 有 4 个内核,线程 A 调用函数 run(),它将创建 4 个 OpenMP 线程来运行 for loop

现在,同时线程B也调用了run(),这样会产生更多的4个OpenMP线程,总共有8个OpenMP线程。

我的问题是,是否有某种方法可以平衡 OpenMP,在上面的示例中,OpenMP 可以对 A 使用半线程,而对于 B 使用一半线程。 另一种策略是 OpenMP 创建一个线程队列,因此它永远不会使用超过 4 个 OpenMP 线程。

这样的事情可能吗?

PS。请注意,我的示例中的 2 个线程只是为了说明这一点,在我的程序中,不清楚有多少线程将调用 run(),因为线程数是在运行时根据需要创建的。

PS 2. 请注意,每当我谈论 OpenMP 创建的线程时,我将其称为 OpenMP 线程,而当我谈论通过其他方式创建的线程(例如 std::thread)时,我将其称为它只是线程。

【问题讨论】:

    标签: c++ multithreading openmp


    【解决方案1】:

    如果您仅使用 OpenMP 进行并行处理,并且启用了 nested parallelism,您可以使用 pragma omp parallelnum_threads 参数来指定使用一半线程:

    int const currentNumThreads = omp_get_num_threads();
    int const maxNumThreads = omp_get_max_num_threads();
    #pragma omp parallel for num_threads(maxNumThreads/currentNumThreads)
    for ( ... ) {
       ...
    }
    

    即使您使用的是混合线程技术(这似乎是您的情况),您仍然可以通过使用不同的方法设置currentNumThreadsmaxNumThreads 来完成相同的操作。

    请注意。对于 OpenMP,使用嵌套并行性通常是不可取的,因为它使代码相当 fragile and rigid。对run() 函数的任何更改都需要知道从哪里调用它,并且将来对run() 的任何调用都需要知道其中的内容。在性能和维护方面,尝试遵循 data parallel 方法来使用 OpenMP 是最好的。也就是说,在每个线程中执行一组类似的操作,但在不同的数据块上。

    例外情况是,如果您使用的是 OpenMP 任务,您可以生成这些任务,并让调度程序来处理它。由于缺少data locality,在并行for循环中使用任务并行性往往会导致性能不佳,并且如果任务很小,开销也会很高。

    【讨论】:

    • 我的问题是你所说的混合线程技术,但我不认为我手动更改 currentNumThreadsmaxNumThreads 会起作用,因为不能保证我会在同时。我的意思是我可以让一个线程做另一件与run() 无关的事情,它仍然会计入num_threads() 计算中。
    猜你喜欢
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2013-01-06
    • 1970-01-01
    相关资源
    最近更新 更多