首页 > 解决方案 > openMP 无效控制谓词

问题描述

在这段代码中,我正在尝试使用 OpenMP 并行执行 Sieve of Eratosthenes 算法,当程序是串行的时它工作正常

for (int i = p * p; i <= n; i += p) 素数[i] = false;

但是当我使用

#pragma omp for

它给出了这个错误

错误:无效的控制谓词 17 | for (int p = 2; p * p <= n; p++)

这是代码

#include <bits/stdc++.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
using namespace std;
 
void SieveOfEratosthenes(int n)
{
    #pragma omp parallel
    {
    bool prime[n + 1];
    memset(prime, true, sizeof(prime));
    #pragma omp for 
    for (int p = 2; p * p <= n; p++)
    {
        
        if (prime[p] == true)
        {
            for (int i = p * p; i <= n; i += p)
                prime[i] = false;
        }
    }
    
    #pragma omp critical
    for (int p = 2; p <= n; p++)
        if (prime[p])
            printf("%d  ", p);
    }
}
 
int main()
{
    printf("Enter the siza: ");
    int n ;
    scanf("%d", &n);
    printf("Following are the prime numbers from 1 to %f \n", sqrt(n));
    SieveOfEratosthenes(sqrt(n));
    printf("\n");
    return 0;
}

标签: c++copenmp

解决方案


正如@Daniel Langr 所指出的,您的循环测试形式不受支持。它必须是规范的循环形式。有关更多详细信息,请参阅OpenMP 规范的2.9.1 规范循环形式。取比较两边的平方根,您可以将其更改为支持的形式:

const int end_p=sqrt(n);
#pragma omp for 
for (int p = 2; p <= end_p; p++)

请注意,您的代码也有其他错误:每个线程将创建一个私有prime数组并处理其私有副本,因此您会获得不正确的结果。您可以通过使用共享prime数组和原子读写操作来纠正它:

void SieveOfEratosthenes(int n)
{    
    bool prime[n + 1];
    memset(prime, true, sizeof(prime));
    
    const int end_p=sqrt(n);
    #pragma omp parallel for 
    for (int p = 2; p <= end_p; p++)
    {
        bool prime_p;
        #pragma omp atomic read
        prime_p=prime[p];
        if (prime_p == true)
        {
            for (int i = p * p; i <= n; i += p)
            {
                #pragma omp atomic write
                prime[i] = false;
            }
        }
    }
    
    for (int p = 2; p <= n; p++)
        if (prime[p])
            printf("%d  ", p);
    
}

推荐阅读