使用copyin和copyout的OpenAcc错误
一般资料 注意:我对C、OpenAcc也是相当陌生的 您好,我正在尝试开发一个图像模糊程序,但首先我想看看是否可以并行化for循环和copyin/copyout我的值 我目前面临的问题是,当我尝试复制输入和复制输出我的数据和输出变量时。这个错误看起来是缓冲区溢出(我也用谷歌搜索了一下,人们都这么说),但我不确定该如何解决这个问题。我想我的指针有问题,但我不确定 提前非常感谢,如果您认为我遗漏了一些信息,请让我知道,我可以提供 问题:使用copyin和copyout的OpenAcc错误,c,pointers,gpu,buffer-overflow,openacc,C,Pointers,Gpu,Buffer Overflow,Openacc,一般资料 注意:我对C、OpenAcc也是相当陌生的 您好,我正在尝试开发一个图像模糊程序,但首先我想看看是否可以并行化for循环和copyin/copyout我的值 我目前面临的问题是,当我尝试复制输入和复制输出我的数据和输出变量时。这个错误看起来是缓冲区溢出(我也用谷歌搜索了一下,人们都这么说),但我不确定该如何解决这个问题。我想我的指针有问题,但我不确定 提前非常感谢,如果您认为我遗漏了一些信息,请让我知道,我可以提供 问题: 我想确认错误到底是什么 我应该如何着手解决这个问题 任何我应该
#包括
#包括
#包括
#包括
// ================================================
//ppmFile.h
// ================================================
#包括
typedef结构图像
{
整数宽度;
内部高度;
无符号字符*数据;
}形象;
图像*图像创建(整数宽度,
内部高度);
图像*图像读取(字符*文件名);
无效图像写入(图像*图像,
字符*文件名);
int ImageWidth(图像*图像);
int ImageHeight(图像*图像);
无效图像清除(图像*图像,
未签名的字符红色,
无符号字符绿色,
无符号字符(蓝色);
无效图像设置像素(图像*图像,
int x,
INTY,
陈英杰,
无符号字符(val);
无符号字符ImageGetPixel(图像*图像,
int x,
INTY,
陈国强),;
模糊滤波函数
//================================================
//模糊过滤器
// ================================================
void ProcessImageACC(图像**数据,整型过滤器,图像**输出){
int行=(*数据)->高度;
整数列=(*数据)->宽度;
#pragma acc data copyin(行、列、筛选器列、(*data)->数据[0:row*col])copyout((*output)->数据[0:row*col])
#pragma-acc核
{
#pragma acc环路独立
对于(int j=0;j数据[j*行+i]=(*数据)->数据[j*行+i];
}
}
}
}
主要功能
//================================================
//主程序
// ================================================
int main(int argc,char*argv[]){
//用于处理的变量:
图像*数据,*结果;
int-dataSize;
int filteradius=atoi(argv[1]);
//==读取数据===
数据=图像读取(argv[2]);
//==向节点发送数据===
//发送数据大小(字节)
dataSize=sizeof(无符号字符)*数据->宽度*数据->高度*3;
//==处理图像===
//分配空间来存储结果
结果=(图像*)malloc(sizeof(图像));
结果->数据=(无符号字符*)malloc(数据大小);
结果->宽度=数据->宽度;
结果->高度=数据->高度;
//将全部初始化为0
对于(int i=0;i<(结果->宽度*结果->高度*3);i++){
结果->数据[i]=0;
}
//应用过滤器
ProcessImageACC(数据、过滤器和结果);
//==保存回数据===
ImageWrite(结果,argv[3]);
返回0;
}
这里的问题是,除了数据数组之外,还需要复制输出和数据指针。从编译器的反馈消息中,您可以看到编译器隐式地将它们复制过来
% pgcc -c image.c -ta=tesla:cc70 -Minfo=accel
ProcessImageACC:
46, Generating copyout(output->->data[:col*row])
Generating copyin(data->->data[:col*row],col,filterRad,row)
47, Generating implicit copyout(output[:1])
Generating implicit copyin(data[:1])
50, Loop is parallelizable
52, Loop is parallelizable
Accelerator kernel generated
Generating Tesla code
50, #pragma acc loop gang, vector(4) /* blockIdx.y threadIdx.y */
52, #pragma acc loop gang, vector(32) /* blockIdx.x threadIdx.x */
现在,您可以通过使用非结构化数据区域来创建数据和指针,然后将指针“附加”到数组(即,将设备指针的值填充到设备数据数组的地址)来实现这一点
尽管更简单的选择是创建指向数据的临时数组,然后将数据复制到设备。这还将提高代码的性能(在GPU和CPU上),因为它消除了额外的间接寻址级别
void ProcessImageACC(Image **data, int filterRad, Image **output) {
int row = (*data)->height;
int col = (*data)->width;
unsigned char * ddata, * odata;
odata = (*output)->data;
ddata = (*data)->data;
#pragma acc data copyin(ddata[0:row * col]) copyout(odata[0:row * col])
#pragma acc kernels
{
#pragma acc loop independent
for (int j = 0; j < row; j++) {
#pragma acc loop independent
for (int i = 0; i < col; i++) {
odata[j * row + i] = ddata[j * row + i];
}
}
}
}
void ProcessImageACC(图像**数据、整型过滤器、图像**输出){
int行=(*数据)->高度;
整数列=(*数据)->宽度;
无符号字符*ddata,*odata;
odata=(*输出)->数据;
ddata=(*数据)->数据;
#pragma acc数据复制输入(ddata[0:row*col])复制输出(odata[0:row*col])
#pragma-acc核
{
#pragma acc环路独立
对于(int j=0;j|
请注意,标量在默认情况下是firstprivate的,因此无需在data子句中添加row、col和filterRad变量
// ================================================
// The Blur Filter
// ================================================
void ProcessImageACC(Image **data, int filterRad, Image **output) {
int row = (*data)->height;
int col = (*data)->width;
#pragma acc data copyin(row, col, filterRad, (*data)->data[0:row * col]) copyout((*output)->data[0:row * col])
#pragma acc kernels
{
#pragma acc loop independent
for (int j = 0; j < row; j++) {
#pragma acc loop independent
for (int i = 0; i < col; i++) {
(*output)->data[j * row + i] = (*data)->data[j * row + i];
}
}
}
}
// ================================================
// Main Program
// ================================================
int main(int argc, char *argv[]) {
// vars used for processing:
Image *data, *result;
int dataSize;
int filterRadius = atoi(argv[1]);
// ===read the data===
data = ImageRead(argv[2]);
// ===send data to nodes===
// send data size in bytes
dataSize = sizeof(unsigned char) * data->width * data->height * 3;
// ===process the image===
// allocate space to store result
result = (Image *)malloc(sizeof(Image));
result->data = (unsigned char *)malloc(dataSize);
result->width = data->width;
result->height = data->height;
// initialize all to 0
for (int i = 0; i < (result->width * result->height * 3); i++) {
result->data[i] = 0;
}
// apply the filter
ProcessImageACC(&data, filterRadius, &result);
// ===save the data back===
ImageWrite(result, argv[3]);
return 0;
}
% pgcc -c image.c -ta=tesla:cc70 -Minfo=accel
ProcessImageACC:
46, Generating copyout(output->->data[:col*row])
Generating copyin(data->->data[:col*row],col,filterRad,row)
47, Generating implicit copyout(output[:1])
Generating implicit copyin(data[:1])
50, Loop is parallelizable
52, Loop is parallelizable
Accelerator kernel generated
Generating Tesla code
50, #pragma acc loop gang, vector(4) /* blockIdx.y threadIdx.y */
52, #pragma acc loop gang, vector(32) /* blockIdx.x threadIdx.x */
void ProcessImageACC(Image **data, int filterRad, Image **output) {
int row = (*data)->height;
int col = (*data)->width;
unsigned char * ddata, * odata;
odata = (*output)->data;
ddata = (*data)->data;
#pragma acc data copyin(ddata[0:row * col]) copyout(odata[0:row * col])
#pragma acc kernels
{
#pragma acc loop independent
for (int j = 0; j < row; j++) {
#pragma acc loop independent
for (int i = 0; i < col; i++) {
odata[j * row + i] = ddata[j * row + i];
}
}
}
}