OpenMP:将所有线程分为不同的组 [英] OpenMP: Divide all the threads into different groups

查看:79
本文介绍了OpenMP:将所有线程分为不同的组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I will like to divide all the threads into 2 different groups, since I have two parallel tasks to run asynchronously. For example, if totally 8 threads are available, I will like 6 threads dedicated to task1, and the other 2 dedicated to task2.

如何使用OpenMP做到这一点?

How can I achieve this with OpenMP?

推荐答案

这是

This is a job for OpenMP nested parallelism, as of OpenMP 3: you can use OpenMP tasks to start two independent tasks and then within those tasks, have parallel sections which use the appropriate number of threads.

作为一个简单的例子:

#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个硬件线程)节点上运行此

Running this on an 8 core (16 hardware threads) node,

$ 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"-在这里我还打印了祖先(例如,"5个1的子代中的线程1"与"0的11个子代中的线程1"").

Updated: I've changed the above to include the thread ancestor; there was come confusion because there were (for instance) two "thread 1"s printed - here I've also printed the ancestor (e.g., "thread 1 of the 5 children of 1" vs "thread 1 of the 11 children of 0").

来自 OpenMP标准,S.3.2.4,"; omp_get_thread_num 例程返回调用线程的线程号,在当前团队中.&rdquo ;,从第2.5节起,当线程遇到并行构造时",将创建一个线程组以执行并行区域[...]遇到并行结构的线程成为新团队的主线程,的线程号为零新的平行区域的持续时间.

From the OpenMP standard, S.3.2.4, “The omp_get_thread_num routine returns the thread number, within the current team, of the calling thread.”, and from section 2.5, “When a thread encounters a parallel construct, a team of threads is created to execute the parallel region [...] The thread that encountered the parallel construct becomes the master thread of the new team, with a thread number of zero for the duration of the new parallel region.

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

That is, within each of those (nested) parallel regions, teams of threads are created which have thread ids starting at zero; but just because those ids overlap within the team doesn't mean they're the same threads. Here I've emphasized that by printing their ancestor number as well, but if the threads were doing CPU-intensive work you'd also see with monitoring tools that there were indeed 16 active threads, not just 11.

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

The reason why they are team-local thread numbers and not globally-unique thread numbers is pretty straightforward; it would be almost impossible to keep track of globally-unique thread numbers in an environment where nested and dynamic parallelism can happen. Say there are three teams of threads, numbered [0..5], [6,..10], and [11..15], and the middle team completes. Do we leave gaps in the thread numbering? do we interrupt all threads to change their global numbers? What if a new team is started, with 7 threads? Do we start them at 6 and have overlapping thread ids, or do we start them at 16 and leave gaps in the numbering?

这篇关于OpenMP:将所有线程分为不同的组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆