gpt4 book ai didi

multithreading - OpenMP:将所有线程分成不同的组

转载 作者:行者123 更新时间:2023-12-03 13:15:04 25 4
gpt4 key购买 nike

我想将所有线程分成两个不同的组,因为我有两个并行任务要异步运行。例如,如果总共有 8 个线程可用,我希望 6 个线程专用于 task1,另外 2 个专用于 task2。

如何使用 OpenMP 实现这一点?

最佳答案

这是 OpenMP nested parallelism 的工作,从 OpenMP 3 开始:您可以使用 OpenMP tasks启动两个独立的任务,然后在这些任务中,有使用适当线程数的并行部分。

举个简单的例子:

#include <stdio.h>
#include <omp.h>

int main(int argc, char **argv) {

omp_set_nested(1); /* make sure nested parallism is on */
int nprocs = omp_get_num_procs();
int nthreads1 = nprocs/3;
int nthreads2 = nprocs - nthreads1;

#pragma omp parallel default(none) shared(nthreads1, nthreads2) num_threads(2)
#pragma omp single
{
#pragma omp task
#pragma omp parallel for num_threads(nthreads1)
for (int i=0; i<16; i++)
printf("Task 1: thread %d of the %d children of %d: handling iter %d\n",
omp_get_thread_num(), omp_get_team_size(2),
omp_get_ancestor_thread_num(1), i);
#pragma omp task
#pragma omp parallel for num_threads(nthreads2)
for (int j=0; j<16; j++)
printf("Task 2: thread %d of the %d children of %d: handling iter %d\n",
omp_get_thread_num(), omp_get_team_size(2),
omp_get_ancestor_thread_num(1), j);
}

return 0;
}

在 8 核(16 个硬件线程)节点上运行,

$ gcc -fopenmp nested.c -o nested -std=c99
$ ./nested
Task 2: thread 3 of the 11 children of 0: handling iter 6
Task 2: thread 3 of the 11 children of 0: handling iter 7
Task 2: thread 1 of the 11 children of 0: handling iter 2
Task 2: thread 1 of the 11 children of 0: handling iter 3
Task 1: thread 2 of the 5 children of 1: handling iter 8
Task 1: thread 2 of the 5 children of 1: handling iter 9
Task 1: thread 2 of the 5 children of 1: handling iter 10
Task 1: thread 2 of the 5 children of 1: handling iter 11
Task 2: thread 6 of the 11 children of 0: handling iter 12
Task 2: thread 6 of the 11 children of 0: handling iter 13
Task 1: thread 0 of the 5 children of 1: handling iter 0
Task 1: thread 0 of the 5 children of 1: handling iter 1
Task 1: thread 0 of the 5 children of 1: handling iter 2
Task 1: thread 0 of the 5 children of 1: handling iter 3
Task 2: thread 5 of the 11 children of 0: handling iter 10
Task 2: thread 5 of the 11 children of 0: handling iter 11
Task 2: thread 0 of the 11 children of 0: handling iter 0
Task 2: thread 0 of the 11 children of 0: handling iter 1
Task 2: thread 2 of the 11 children of 0: handling iter 4
Task 2: thread 2 of the 11 children of 0: handling iter 5
Task 1: thread 1 of the 5 children of 1: handling iter 4
Task 2: thread 4 of the 11 children of 0: handling iter 8
Task 2: thread 4 of the 11 children of 0: handling iter 9
Task 1: thread 3 of the 5 children of 1: handling iter 12
Task 1: thread 3 of the 5 children of 1: handling iter 13
Task 1: thread 3 of the 5 children of 1: handling iter 14
Task 2: thread 7 of the 11 children of 0: handling iter 14
Task 2: thread 7 of the 11 children of 0: handling iter 15
Task 1: thread 1 of the 5 children of 1: handling iter 5
Task 1: thread 1 of the 5 children of 1: handling iter 6
Task 1: thread 1 of the 5 children of 1: handling iter 7
Task 1: thread 3 of the 5 children of 1: handling iter 15

已更新:我更改了上面的内容以包含线程祖先;出现了混淆,因为(例如)打印了两个“线程 1”——这里我还打印了祖先(例如,“1 的 5 个子线程中的线程 1”与“0 的 11 个子线程中的线程 1” ”)。

来自OpenMP standard ,S.3.2.4,“omp_get_thread_num 例程返回线程号,在当前团队中,调用线程。”,以及来自第 2.5 节的“当一个线程遇到并行构造,创建一组线程以执行并行区域 [...] 遇到并行构造的线程成为新团队的主线程,线程号为零新平行区域的持续时间。

也就是说,在每个(嵌套的)并行区域中,创建线程组,线程 ID 从零开始;但仅仅因为这些 ID 在团队中重叠并不意味着它们是相同的线程。在这里,我强调了通过打印它们的祖先编号,但是如果线程正在执行 CPU 密集型工作,您还会通过监视工具看到确实有 16 个事件线程,而不仅仅是 11 个。

它们是团队本地线程编号而不是全局唯一线程编号的原因很简单;在可能发生嵌套和动态并行性的环境中,几乎不可能跟踪全局唯一的线程数。假设有三组线程,编号为 [0..5]、[6,..10] 和 [11..15],中间组完成。我们是否在线程编号中留有空隙?我们是否中断所有线程以更改它们的全局编号?如果启动了一个新团队,有 7 个线程怎么办?我们是从 6 开始并具有重叠的线程 ID,还是从 16 开始并在编号中留有间隙?

关于multithreading - OpenMP:将所有线程分成不同的组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25556748/

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