在#pragma omp parallel
开始时创建了一堆线程,然后当我们到达#pragma omp for
时,工作负载就会被分发。如果for循环中有for循环,我会在它前面放置一个#pragma omp for
会发生什么?每个线程都会创建新线程吗?如果没有,哪个线程被分配了这个任务?在这种情况下到底发生了什么?
答案 0 :(得分:3)
默认情况下,不会为内部循环生成任何线程。它是使用到达它的线程顺序完成的。
这是因为默认情况下禁用嵌套。但是,如果通过omp_set_nested()
启用嵌套,则会生成一组新线程。
但是,如果您不小心,这将导致p^2
个线程数(因为每个原始p
线程将产生另一个p
个线程。)因此默认情况下禁用嵌套。
答案 1 :(得分:1)
在以下情况中:
#pragma omp parallel
{
#pragma omp for
for(int ii = 0; ii < n; ii++) {
/* ... */
#pragma omp for
for(int jj = 0; jj < m; jj++) {
/* ... */
}
}
}
当您违反OpenMP标准时,会触发未定义的行为。更准确地说,您违反了第2.5节(工作共享结构)中出现的限制:
以下限制适用于工作共享结构:
- 团队中的所有线程都必须遇到每个工作共享区域,或者根本不会遇到任何工作共享区域。
- 对于团队中的每个线程,遇到的工作共享区域和障碍区域的顺序必须相同。
示例A.39.1c and A.40.1c中清楚地显示了这一点:
示例A.39.1c :以下循环构造嵌套的示例符合,因为内部和外部循环区域绑定到不同的并行 区域:
void work(int i, int j) {}
void good_nesting(int n)
{
int i, j;
#pragma omp parallel default(shared)
{
#pragma omp for
for (i=0; i<n; i++) {
#pragma omp parallel shared(i, n)
{
#pragma omp for
for (j=0; j < n; j++)
work(i, j);
}
}
}
}
示例A.40.1c :以下示例不符合,因为内部和外部循环区域紧密嵌套
void work(int i, int j) {}
void wrong1(int n)
{
#pragma omp parallel default(shared)
{
int i, j;
#pragma omp for
for (i=0; i<n; i++) {
/* incorrect nesting of loop regions */
#pragma omp for
for (j=0; j<n; j++)
work(i, j);
}
}
}
请注意,这与:
不同#pragma omp parallel for
for(int ii = 0; ii < n; ii++) {
/* ... */
#pragma omp parallel for
for(int jj = 0; jj < m; jj++) {
/* ... */
}
}
您尝试生成嵌套的并行区域。只有在这种情况下才会讨论Mysticial的答案。