【发布时间】:2015-06-25 07:19:38
【问题描述】:
我刚刚发现虽然这个 C 代码给出了一个有序的整数列表(如预期的那样):
#include <stdio.h>
#include <unistd.h>
#include <omp.h>
int main() {
#pragma omp parallel for ordered schedule(dynamic)
for (int i=0; i<10; i++) {
#pragma omp ordered
{
printf("%i (tid=%i)\n",i,omp_get_thread_num(); fflush(stdout);
}
}
}
同时使用 gcc 和 icc,以下会产生不良行为:
#include <stdio.h>
#include <unistd.h>
#include <omp.h>
int main() {
#pragma omp parallel for ordered schedule(dynamic)
for (int i=0; i<10; i++) {
#pragma omp ordered
{
printf("%i (tid=%i)\n",i,omp_get_thread_num()); fflush(stdout);
}
usleep(100*omp_get_thread_num());
printf("WORK IS DONE (tid=%i)\n",omp_get_thread_num()); fflush(stdout);
usleep(100*omp_get_thread_num());
#pragma omp ordered
{
printf(" %i (tid=%i)\n",i,omp_get_thread_num()); fflush(stdout);
}
}
}
我希望看到的是:
0
1
2
3
4
5
6
7
8
9
工作完成
工作完成
工作完成
工作完成
工作完成
工作完成
工作完成
工作完成
工作完成
工作完成
0
1
2
3
4
5
6
7
8
9
但是用 gcc 是 get:
0 (tid=5)
工作完成 (tid=5)
0 (tid=5)
1 (tid=2)
工作已完成 (tid=2)
1 (tid=2)
2 (tid=0)
工作已完成 (tid=0)
2 (tid=0)
3 (tid=6)
工作已完成 (tid=6)
3 (tid=6)
4 (tid=7)
工作完成 (tid=7)
4 (tid=7)
5 (tid=3)
工作完成 (tid=3)
5 (tid=3)
6 (tid=4)
工作完成 (tid=4)
6 (tid=4)
7 (tid=1)
工作已完成 (tid=1)
7 (tid=1)
8 (tid=5)
工作完成 (tid=5)
8 (tid=5)
9 (tid=2)
工作已完成 (tid=2)
9 (tid=2)
(所以一切都井井有条——即使是可并行化的工作部分)
还有 icc:
1 (tid=0)
2 (tid=5)
3 (tid=1)
4 (tid=2)
工作已完成 (tid=1)
工作完成 (tid=3)
3 (tid=1)
6 (tid=4)
7 (tid=7)
8 (tid=1)
工作已完成 (tid=0)
5 (tid=6)
工作已完成 (tid=2)
1 (tid=0)
9 (tid=0)
工作已完成 (tid=0)
工作完成 (tid=5)
工作已完成 (tid=1)
9 (tid=0)
0 (tid=3)
8 (tid=1)
工作完成 (tid=4)
工作已完成 (tid=6)
2 (tid=5)
工作完成 (tid=7)
6 (tid=4)
5 (tid=6)
4 (tid=2)
7 (tid=7)
(所以即使是有序的子句也没有得到任何命令)
在一个有序循环中使用多个有序子句未定义行为还是这里发生了什么?在我能找到的任何 OpenMP 文档中,我都找不到任何不允许每个循环使用多个子句的内容。
我知道在这个简单的例子中我可以像
int main() {
for (int i=0; i<10; i++) {
printf("%i (tid=%i)\n",i,omp_get_thread_num()); fflush(stdout);
}
#pragma omp parallel for schedule(dynamic)
for (int i=0; i<10; i++) {
usleep(100*omp_get_thread_num());
printf("WORK IS DONE (tid=%i)\n",omp_get_thread_num()); fflush(stdout);
usleep(100*omp_get_thread_num());
}
for (int i=0; i<10; i++) {
printf(" %i (tid=%i)\n",i,omp_get_thread_num()); fflush(stdout);
}
}
所以我不是在寻找解决方法。我真的很想了解这里发生了什么,这样我就可以处理真实情况而不会遇到任何破坏性/意外情况。
我真的希望你能帮助我。
【问题讨论】:
标签: c gcc openmp undefined-behavior icc