找到OpenMP和VS 2012意外的文件结尾

时间:2014-10-20 14:41:36

标签: c++ c visual-studio visual-studio-2012 openmp

我试图找到当我尝试使用openMP运行pi计算程序时出现错误的原因。 我正在使用的代码显示如下,使用vs2012并在项目中设置了openMP选项。我已成功运行hello world程序,但我不明白这里的问题是什么。

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 2

static long num_steps = 100000;
double step;
int main(void)
{
    // Shared variable, updated !
    int i;
    double pi, sum[NUM_THREADS]; 
    step = 1.0/(double) num_steps;

    omp_set_num_threads(NUM_THREADS);

    #pragma omp parallel 
    {   double x;
        int id; 
        id = omp_get_thread_num();
        sum[id]=0.0;
        for (i=id; i< num_steps; i=i+NUM_THREADS){ 
            x = (i+0.5)*step; 
            sum[id] += 4.0/(1.0+x*x); 
        } 
    }
    pi=0.0;
    for(i=0;i<NUM_THREADS;i++){
        pi += sum[i] * step; 
    }
    printf("pi = %f\n",pi);
    return 0;
}

所以我得到的唯一错误是 pi.cpp(35): fatal error C1004: unexpected end-of-file found 这里发生了什么?这是Visual Studio的错误吗? 提前致谢

不介意代码效率低下,这里的问题不是关于这里的代码,而是VS2012和openMP ...

2 个答案:

答案 0 :(得分:1)

默认情况下,预编译的标题功能处于启用状态。当它在每个cpp文件上时必须有第一个包含的行,如

#include "stdafx.h"

编译器正在扫描您的源文件以查找该行,并且在找到之前忽略其他所有内容。您可以在项目属性中关闭预编译的标题。

答案 1 :(得分:0)

您的问题基本上与另一个I answered recently重复。即使您获得编译代码后,您也会发现竞争条件和错误共享。我没有给出相同的答案,而是添加了新内容。

在您的代码中,您尝试为for循环手册定义块,另外还保存每个线程的部分和,然后在并行部分之后合并结果。对于你正在做的事情,没有充分的理由去做这些事情。但是,让我举两个你需要做的例子。我可以想到手动定义块的唯一原因是在执行induction to reduce the number of computations per iteration时。

在您的情况下,您可以将功能更改为使用感应,如下所示:

double pi = 0.0;
for(double x=0.5*step; x<max; x+=step) {
    pi += 1.0/(1.0+x*x);
}
pi *= 4*step

要使用OpenMP执行此操作,需要定义for循环的开始和结束范围:

double pi = 0.0;
#pragma omp parallel reduction(+:pi)
{
    int ithread = omp_get_thread_num();
    int nthreads = omp_get_num_threads();
    int start = ithread*n/nthreads;
    int finish = (ithread+1)*n/nthreads;
    double startx = (start+0.5)*step;
    double finishx = (finish+0.5)*step;
    for(double x=startx; x<finishx; x+=step) {
        pi += 1.0/(1.0+x*x);        
    }       
}
pi *= 4*step;

正如我已经说过的那样,感应是我能想到的唯一一个你需要做的事情。

您的代码还会保存每个线程减少的结果。我能想到这样做的唯一原因是你正在做的操作不是commutative。矩阵乘法不是可交换的,因为A*B通常不等于B*A。但是你的操作是可交换的,但我们假设它不是。在这种情况下,你可以像这样做

double pi = 0.0;
int nthreads;
double *ppi;
#pragma omp parallel
{
    double pi_private = 0.0;
    int ithread = omp_get_thread_num();
    #pragma single
    {
        nthreads = omp_get_num_threads();
        ppi = new double[nthreads];
    } 
    #pragma omp for
    for(int i=0; i<n; i++) {
        double x = (i+0.5)*step;
        pi_private += 1.0/(1.0+x*x);
    }
    ppi[ithread] = pi_private;
}
for(int i=0; i<nthreads; i++) {
    pi += ppi[i];
}
pi *= 4*step;
delete[] ppi;

顺便说一句,为了进行减少,操作需要是关联的。但浮点运算不是严格关联的。使用浮点运算进行简化时,必须接受结果可能无法再现。

无论如何,在你的情况下做的简单事情是:

double pi = 0.0;
#pragma omp parallel for reduction(+:pi)
for(int i=0; i<n; i++) {
    double x = (i+0.5)*step;
    pi += 1.0/(1.0+x*x);
}
pi *= 4*step;

这是完整的代码

include <stdio.h>
#include <omp.h>

void foo(int n) {
    double step = 1.0/n;
    double max = (0.5+n)*step;
    double pi = 0.0;
    for(double x=0.5*step; x<max; x+=step) {
        pi += 1.0/(1.0+x*x);
    }
    pi *= 4*step;
    printf("pi %f\n", pi);
}

void foo2(int n) {
    double step = 1.0/n;
    double pi = 0.0;
    #pragma omp parallel reduction(+:pi)
        {
        int ithread = omp_get_thread_num();
        int nthreads = omp_get_num_threads();
            int start = ithread*n/nthreads;
            int finish = (ithread+1)*n/nthreads;
        double startx = (start+0.5)*step;
        double finishx = (finish+0.5)*step;
        for(double x=startx; x<finishx; x+=step) {
            pi += 1.0/(1.0+x*x);
            //printf("%d %f\n", ithread, x);    
        }
    }
    pi *= 4*step;
    printf("pi %f\n", pi);
}

void foo3(int n) {
    double step = 1.0/n;
        double pi = 0.0;
    int nthreads;
    double *ppi;
    #pragma omp parallel
    {
        double pi_private = 0.0;
        int ithread = omp_get_thread_num();
        #pragma single
        {
            nthreads = omp_get_num_threads();
            ppi = new double[nthreads];
        }   
        #pragma omp for
            for(int i=0; i<n; i++) {
            double x = (i+0.5)*step;
            pi_private += 1.0/(1.0+x*x);
        }
        ppi[ithread] = pi_private;
    }
    for(int i=0; i<nthreads; i++) {
        pi += ppi[i];
    }
    pi *= 4*step;
    printf("pi %f\n", pi);
}

void foo4(int n) {
    double step = 1.0/n;
        double pi = 0.0;
    #pragma omp parallel for reduction(+:pi)
        for(int i=0; i<n; i++) {
        double x = (i+0.5)*step;
        pi += 1.0/(1.0+x*x);
    }
    pi *= 4*step;
    printf("pi %f\n", pi);
}

int main() {
    foo(1<<20);
    foo2(1<<20);
    foo3(1<<20);
    foo4(1<<20);
}