OpenACC должен иметь стандартную информационную ошибку

Я пытаюсь распараллелить простую программу mandelbrot c, но я получаю эту ошибку, которая не связана с обычной информацией. Кроме того, я не уверен, должен ли я копировать данные в параллельный раздел и из него. 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;
}

2 ответа

Поскольку вы не можете получить доступ к файлу из графического процессора, вам нужно захватить результаты в массивы, скопировать их обратно на хост и затем вывести результаты в файл.

Кроме того, предложение "present" указывает, что вы уже скопировали данные на устройство, и программа прервет работу, если ее там нет. Учитывая использование, я думаю, вы имели в виду использовать "private", что означает, что переменная должна быть приватной для уровня выполнения. Однако скаляры по умолчанию являются закрытыми в 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;
}

При использовании OpenACC параллельные области выгружаются на устройство, например, графический процессор. Устройства с графическим процессором обычно не имеют доступа ко всей системе или вводу-выводу и имеют уменьшенное подмножество реализованной стандартной библиотеки. В вашем случае вызов функции fwrite не может быть выгружен на устройство, так как вы не можете получить доступ к диску из ускорителя. Это можно сделать в OpenMP, где параллельные области выполняются в потоках ЦП или MIC, которые обычно имеют доступ ко всей системной библиотеке. Директива acc рутина, которую предлагает PGC, позволит вам аннотировать любую функцию для создания ее версии для устройства.

Другие вопросы по тегам