OpenMP 导致内部编译器错误

Posted

技术标签:

【中文标题】OpenMP 导致内部编译器错误【英文标题】:OpenMP causes internal compiler error 【发布时间】:2017-08-09 16:40:34 【问题描述】:

我编写了一个小程序来测试 OpenMP 的性能提升。 我使用 Microsoft Visual Studio 进行编译。

void findAllPrimesUntilX() 
    for (int i = 2; i <= upToXthPrimes; i++) 
        if (i % 500 == 0) std::cout << "First " << i * 500 << "primes have been checked\n";
        if (checkPrime(i)) primes.push_back(i);
    
    std::cout << "All primes have been calculated!\n";

这是调用“checkPrime(i)”的函数,如下所示:

bool checkPrime(int n) 
    if (n == 2) return true;
    if (n < 2 || n % 2 == 0) return false;      
#pragma omp parallel for
        for (int i = 3; i <= static_cast<int>(sqrt(n)); i += 2) 
            if (n % i == 0) return false;
        
        return true;        

我现在收到“C1001 错误:编译器发生内部错误。”

删除#pragma omp parallel for 解决了这个问题。那么有什么关系呢?

提前致谢

以下

【问题讨论】:

OpenMP 规范禁止线程拥有除并行区域末端之外的任何其他退出代码路径。换句话说,return 语句或goto 到并行区域之外的标签是不允许的。编译器应该会发出错误,但 Microsoft 的 OpenMP 实现非常旧且不受支持,而且显然非常损坏。 在外循环而不是内循环上共享工作。不过要小心std::vector。要么提前保留一块包含所有素数的内存,要么为每个线程填充私有std::vector,然后再加入它们。 【参考方案1】:

OpenMP 旨在生成大量线程,这些线程可以同时执行多个独立操作。在您的情况下,我认为该错误是由于产生了许多线程,但只有其中一些线程被 return false; 语句提前终止。不要立即返回false,而是尝试设置一个布尔变量:

bool checkPrime(int n) 
    if (n == 2) return true;
    if (n < 2 || n % 2 == 0) return false;
    bool prime = true;

    #pragma omp parallel for
    for (int i = 3; i <= static_cast<int>(sqrt(n)); i += 2) 
        if (n % i == 0) prime = false;
    

    return prime;        

另外,请注意,使用 OpenMP 需要使用附加标志进行编译。如果遇到编译器错误,您可能已经正确执行此操作。

【讨论】:

以上是关于OpenMP 导致内部编译器错误的主要内容,如果未能解决你的问题,请参考以下文章

GCC 8.1.0/MinGW64 编译的 OpenMP 程序崩溃寻找 cygwin.s?

在 Oracle 11g2 XE 中编译 PL/SQL 函数有时会导致 ORA-00600:内部错误

BFD:矮人错误:使用 GNU 4.7.2 使用 HPCToolKit 分析 openmp 程序时

OpenMP 并行等待

Helgrind (Valgrind) 和 OpenMP (C):避免误报?

用 ISPC 编译器编译 OpenMP 程序