我正在尝试并行化一个简单的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;
}
答案 0 :(得分:2)
由于您无法从GPU访问文件,因此您需要将结果捕获到数组,将它们复制回主机,然后将结果输出到文件。
此外,“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;
}
答案 1 :(得分:0)
使用OpenACC时,并行区域会卸载到设备(如GPU)。 GPU设备通常无法访问整个系统或IO,并且实现了标准库的缩减子集。 在您的情况下, fwrite 函数调用无法卸载到设备,因为您无法从加速器访问磁盘。 您可以在OpenMP中执行此操作,其中并行区域在CPU或MIC线程上执行,这些线程通常可以访问整个系统库。 PGC建议的 acc例程指令允许您注释任何函数以创建它的设备版本。