0

我正在尝试并行化一个简单的 mandelbrot c 程序,但我得到了这个错误,它与不包括 acc 例程信息有关。另外,我不确定是否应该将数据复制进和复制出并行部分。PS我对并行编程比较陌生,所以任何关于学习它的建议都将不胜感激。

(编译时警告)

PGC-S-0155-Procedures called in a compute region must have acc routine information: fwrite (mandelbrot.c: 88)
PGC-S-0155-Accelerator region ignored; see -Minfo messages  (mandelbrot.c: 51)
main:
     51, Accelerator region ignored
     88, Accelerator restriction: call to 'fwrite' with no acc routine information
PGC/x86-64 Linux 16.10-0: compilation completed with severe errors

这是我的代码:

#include <stdio.h>
#include <math.h>
int main()
{
    /* screen ( integer) coordinate */
    int iX,iY;
    const int iXmax = 800;
    const int iYmax = 800;
    /* world ( double) coordinate = parameter plane*/
    double Cx,Cy;
    const double CxMin=-2.5;
    const double CxMax=1.5;
    const double CyMin=-2.0;
    const double CyMax=2.0;
    /* */
    double PixelWidth=(CxMax-CxMin)/iXmax;
    double PixelHeight=(CyMax-CyMin)/iYmax;
    /* color component ( R or G or B) is coded from 0 to 255 */
    /* it is 24 bit color RGB file */
    const int MaxColorComponentValue=255;
    FILE * fp;
    char *filename="new1.ppm";
    char *comment="# ";/* comment should start with # */
    static unsigned char color[3];
    /* Z=Zx+Zy*i  ;   Z0 = 0 */
    double Zx, Zy;
    double Zx2, Zy2; /* Zx2=Zx*Zx;  Zy2=Zy*Zy  */
    /*  */
    int Iteration;
    const int IterationMax=200;
    /* bail-out value , radius of circle ;  */
    const double EscapeRadius=2;
    double ER2=EscapeRadius*EscapeRadius;
    /*create new file,give it a name and open it in binary mode  */
    fp= fopen(filename,"wb"); /* b -  binary mode */
    /*write ASCII header to the file*/
    fprintf(fp,"P6\n %s\n %d\n %d\n %d\n",comment,iXmax,iYmax,MaxColorComponentValue);
    /* compute and write image data bytes to the file*/
    #pragma acc parallel loop present(CyMin, iY, PixelHeight, iX, iXmax, CxMin, PixelWidth, Zx, Zy, Zx2, Zy2, Iteration, IterationMax)
    for(iY=0;iY<iYmax;iY++)
    {
        Cy=CyMin + iY*PixelHeight;
        if (fabs(Cy)< PixelHeight/2) Cy=0.0; /* Main antenna */
        #pragma acc loop
        for(iX=0;iX<iXmax;iX++)
        {
            Cx=CxMin + iX*PixelWidth;
            /* initial value of orbit = critical point Z= 0 */
            Zx=0.0;
            Zy=0.0;
            Zx2=Zx*Zx;
            Zy2=Zy*Zy;
            /* */
            #pragma acc loop
            for (Iteration=0;Iteration<IterationMax && ((Zx2+Zy2)<ER2);Iteration++)
            {
                Zy=2*Zx*Zy + Cy;
                Zx=Zx2-Zy2 +Cx;
                Zx2=Zx*Zx;
                Zy2=Zy*Zy;
            };
            /* compute  pixel color (24 bit = 3 bytes) */
            if (Iteration==IterationMax)
            { /*  interior of Mandelbrot set = black */
                color[0]=0;
                color[1]=0;
                color[2]=0;
            }
            else
            { /* exterior of Mandelbrot set = white */
                color[0]=255; /* Red*/
                color[1]=255;  /* Green */
                color[2]=255;/* Blue */
            };
            /*write color to the file*/
            fwrite(color,1,3,fp);
        }
    }
    fclose(fp);
    return 0;
}
4

2 回答 2

2

由于您无法从 GPU 访问文件,因此您需要将结果捕获到数组中,将它们复制回主机,然后将结果输出到文件中。

此外,“present”子句表示您已经将数据复制到设备上,如果不存在,程序将中止。鉴于用法,我认为您的意思是使用“私有”,这表明该变量应该是执行级别的私有变量。然而,标量在 OpenACC 中默认是私有的,所以不需要手动私有化这些变量。如果您手动将变量私有化,请确保将其置于正确的循环级别。例如,如果您在外循环上将“Zx”私有化,它只会对该循环级别私有化。它将被内循环的所有向量共享!同样,在这里,最好让编译器处理私有化标量,但请注意在必须手动私有化变量的少数情况下将事物私有化的位置。

这是您的代码的更正版本。

#include <stdio.h>
#include <math.h>

int main()
{
    /* screen ( integer) coordinate */
    int iX,iY;
    const int iXmax = 800;
    const int iYmax = 800;
    /* world ( double) coordinate = parameter plane*/
    double Cx,Cy;
    const double CxMin=-2.5;
    const double CxMax=1.5;
    const double CyMin=-2.0;
    const double CyMax=2.0;
    /* */
    double PixelWidth=(CxMax-CxMin)/iXmax;
    double PixelHeight=(CyMax-CyMin)/iYmax;
    /* color component ( R or G or B) is coded from 0 to 255 */
    /* it is 24 bit color RGB file */
    const int MaxColorComponentValue=255;
    FILE * fp;
    char *filename="new1.ppm";
    char *comment="# ";/* comment should start with # */
    static unsigned char color[3];
    unsigned char red[iXmax][iYmax];
    unsigned char blue[iXmax][iYmax];
    unsigned char green[iXmax][iYmax];
    /* Z=Zx+Zy*i  ;   Z0 = 0 */
    double Zx, Zy;
    double Zx2, Zy2; /* Zx2=Zx*Zx;  Zy2=Zy*Zy  */
    /*  */
    int Iteration;
    const int IterationMax=200;
    /* bail-out value , radius of circle ;  */
    const double EscapeRadius=2;
    double ER2=EscapeRadius*EscapeRadius;
    /*create new file,give it a name and open it in binary mode  */
    fp= fopen(filename,"wb"); /* b -  binary mode */
    /*write ASCII header to the file*/
    fprintf(fp,"P6\n %s\n %d\n %d\n %d\n",comment,iXmax,iYmax,MaxColorComponentValue);
    /* compute and write image data bytes to the file*/
    #pragma acc parallel loop copyout(red,blue,green)
    for(iY=0;iY<iYmax;iY++)
    {
        Cy=CyMin + iY*PixelHeight;
        if (fabs(Cy)< PixelHeight/2) Cy=0.0; /* Main antenna */
        #pragma acc loop
        for(iX=0;iX<iXmax;iX++)
        {
            Cx=CxMin + iX*PixelWidth;
            /* initial value of orbit = critical point Z= 0 */
            Zx=0.0;
            Zy=0.0;
            Zx2=Zx*Zx;
            Zy2=Zy*Zy;
            /* */
            #pragma acc loop
            for (Iteration=0;Iteration<IterationMax && ((Zx2+Zy2)<ER2);Iteration++)
            {
                Zy=2*Zx*Zy + Cy;
                Zx=Zx2-Zy2 +Cx;
                Zx2=Zx*Zx;
                Zy2=Zy*Zy;
            };
            /* compute  pixel color (24 bit = 3 bytes) */
            if (Iteration==IterationMax)
            { /*  interior of Mandelbrot set = black */
                red[iX][iY]=0;
                blue[iX][iY]=0;
                green[iX][iY]=0;
            }
            else
            { /* exterior of Mandelbrot set = white */
                red[iX][iY]=255;
                blue[iX][iY]=255;
                green[iX][iY]=255;
            };            }
    }


    /*write color to the file*/
    for(iY=0;iY<iYmax;iY++) {
        for(iX=0;iX<iXmax;iX++) {
            color[0] = red[iX][iY];
            color[1] = blue[iX][iY];
            color[2] = green[iX][iY];
            fwrite(color,1,3,fp);
        }
    }
    fclose(fp);
    return 0;
}
于 2017-05-31T17:14:04.650 回答
0

使用 OpenACC 时,并行区域被卸载到一个设备上,比如 GPU。GPU 设备通常无法访问整个系统或 IO,并且实现了标准库的缩减子集。在您的情况下,fwrite函数调用无法卸载到设备,因为您无法从加速器访问磁盘。您可以在 OpenMP 中执行此操作,其中并行区域在 CPU 或 MIC 线程上执行,这些线程通常可以访问整个系统库。PGC 建议的acc 例程指令将允许您注释任何函数以创建它的设备版本。

于 2017-05-31T08:30:16.893 回答