c-如何在没有主线程的情况下运行静态并行for循环



我想用多线程执行一个函数,而不使用主线程。这就是我想要的:

# pragma omp parallel num_threads(9)
{
// do something
# pragma omp for schedule(static,1)
for(int i = 0; i < 10; i++)
func(i); // random stuff
}

所以我希望func((只由8个线程执行,没有主线程。这有可能吗?

所以我希望func((只由8个线程执行,而不包含main线这有可能吗?

是的,你可以做到。但是,你必须实现的功能

#pragma omp for schedule(static,1) 

因为,显式使用前面提到的子句将使编译器自动在团队中的线程之间划分循环的迭代,包括该团队的master线程,在您的代码示例中,它也是main螺纹。代码可能如下所示:

# pragma omp parallel num_threads(9) 
{
// do something
int thread_id = omp_get_thread_num();
int total_threads = omp_get_num_threads();
if(thread_id != 0) // all threads but the master thread
{
thread_id--; // shift all the ids
total_threads = total_threads - 1;
for(int i = thread_id ; i < 10; i += total_threads)
func(i); // random stuff
}
#pragma omp barrier
} 

首先,我们确保除了master之外的所有线程都执行了要并行化的循环(if(thread_id != 0)(,然后我们将循环的迭代划分在其余线程中(for(int i = thread_id ; i < 10; i += total_threads)(,最后我们确保所有线程在并行区域的末尾相互等待(1即2#pragma omp barrier(。

如果哪个线程不执行循环并不重要,那么另一种选择是将sections与循环结合起来。这意味着嵌套并行性,应该非常小心,但它应该起作用:

#pragma omp parallel sections num_threads(2)
{
#pragma omp section
{ /* work for one thread */ }
#pragma omp section
{
#pragma omp parallel for num_threads(8) schedule(static, 1)
for (int i = 0; i < N; ++i) { /* ... */ }
}
}

这里的主要问题是,这些部分中的一个很可能会比另一个花费更长的时间,这意味着在最坏的情况下(循环速度比第一个部分快(,除了一个线程之外,其他线程大部分时间都不做任何事。

如果你真的需要主线程在并行区域之外,这可能会起作用(未测试(:

#pragma omp parallel num_threads(2)
{
#pragma omp master
{ /* work for master thread, other thread is NOT waiting */ }
#pragma omp single
{
#pragma omp parallel for num_threads(8) schedule(static, 1)
for (int i = 0; i < N; ++i) { /* ... */ }
}
}

不能保证master线程也不会计算single区域,但如果您的核心没有被过度占用,至少应该不太可能。甚至有人可能会说,如果来自外部平行区域的第二个线程没有及时到达单个区域,那么主线程最好也有机会进入其中,即使这意味着第二个螺纹没有任何事情可做

由于single区域的末端应该只有一个隐式势垒,而master区域不包含任何隐式势垒。因此,只要master区域在single区域的前面,它们就可能并行执行。这是假设single区域实现得很好,这样每个线程都有机会计算它。我认为标准并不能保证这一点。

编辑:这些解决方案需要嵌套并行性才能工作,而在大多数实现中默认情况下都会禁用嵌套并行性。它可以通过环境变量OMP_NESTED或通过调用omp_set_nested()来激活。

相关内容

最新更新