这个最小的 OpenMP 程序
#include <omp.h>
int main()
{
#pragma omp parallel sections
{
#pragma omp section
{
while(1) {}
}
#pragma omp section
{
while(1) {}
}
}
}
使用gcc test.c -fopenmp
编译和运行时会产生这个错误:
Illegal instruction (core dumped)
当我用
改变其中一个循环时 int i=1;
while(i++) {}
或它编译和运行时没有错误的任何其他条件。看起来,1
作为不同线程中的循环条件会导致一些奇怪的行为。为什么?
编辑:我使用的是 gcc 4.6.3
编辑:这是 gcc 中的错误,提交为 Bug 54017给 gcc 开发人员。
最佳答案
这显然是 GCC 中的错误。 GCC 使用 libgomp
中的 GOMP_sections_start()
例程实现 OpenMP 部分,该例程返回调用线程应执行的基于 1
的部分 ID 或 0
如果所有工作项都已分发。基本上转换后的代码应该是这样的:
main._omp_fn.0 (void * .omp_data_i)
{
unsigned int .section.1;
.section.1 = GOMP_sections_start(2);
L0:
switch (.section.1)
{
case 0:
// No more sections to run, exit
goto L2;
case 1:
// Do section 1
while (1) {}
goto L1;
case 2:
// Do section 2
while (1) {}
goto L1;
default:
// Impossible section value, possible error in libgomp
__builtin_trap();
}
L1:
.section.1 = GOMP_sections_next();
goto L0;
L2:
GOMP_sections_end_nowait();
return;
}
在您的情况下,default
和 0
情况都会导致 __builtin_trap()
。 __builtin_trap()
是一个 GCC 内置函数,应该会异常终止您的程序,在 x86 上它会发出 ud2
指令,使 CPU 发出非法操作码异常.它通常放在代码永远不会执行的地方,例如GOMP_sections_start()
和 GOMP_sections_next()
的所有可能的正确返回值 应该 被开关中的 case 覆盖,如果达到默认值 (在 libgomp
中发出可能的错误信号)它应该会失败,你会向开发人员投诉 :)
编辑:这绝对不是预期的 OpenMP 行为,icc
或 suncc
也不会发生。我提交了Bug 54017到 GCC Bugzilla。
编辑 2:我更新了文本以更准确地反射(reflect) GCC 应该产生的内容。看起来 GCC 对并行区域中的控制流产生了错误的印象,并进行了一些进一步破坏代码生成的“优化”。
关于c - 运行最小 OpenMP 程序时的非法指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11542692/