基础问题,简单的图像内存读取出错,clSetKernelArg,-38 CL_INVALID_MEM_OBJECT

2016-09-08 20:37
#define _CRT_SECURE_NO_WARNINGS

#define PROGRAM_FILE "matdot.cl"
#define KERNEL_FUNC "matdoc_mult"

#include "stdio.h"
#include "stdlib.h"
#include "sys/types.h"
#include <CL/cl.h>
#include <math.h>

//BMP utilities
#include "bmpfuncs.h"

cl_int err;

cl_int openCL_init( cl_platform_id &platform,
cl_device_id &device,
cl_context &context
)
{
//cl_platform_id platform;
err = clGetPlatformIDs( 1, &platform, NULL);
if(err < 0) 
{
perror("Couldn't find any platforms! ");
printf("Error code : %d \n press Enter to exit", err);
getchar();
exit(1);
}
//cl_device_id device;
err = clGetDeviceIDs( platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
if(err < 0) 
{
perror("Couldn't find any device! ");
printf("Error code : %d \n press Enter to exit", err);
getchar();
exit(1);
}
//cl_context context;
context = clCreateContext( NULL, 1, &device, NULL, NULL, &err);
if(err < 0) 
{
perror("Couldn't create a Context! ");
printf("Error code : %d \n press Enter to exit", err);
getchar();
exit(1);
}

return 0;
}

// This function reads in a text file and stores it as a char pointer
char* readSource(char* kernelPath) {

cl_int status;
FILE *fp;
char *source;
long int size;

printf("Program file is: %s\n", kernelPath);

fp = fopen(kernelPath, "rb");
if(!fp) {
printf("Could not open kernel file\n");
exit(-1);
}
status = fseek(fp, 0, SEEK_END);
if(status != 0) {
printf("Error seeking to end of file\n");
exit(-1);
}
size = ftell(fp);
if(size < 0) {
printf("Error getting file position\n");
exit(-1);
}

rewind(fp);

source = (char *)malloc(size + 1);

int i;
for (i = 0; i < size+1; i++) {
source[i]='\0';
}

if(source == NULL) {
printf("Error allocating space for the kernel source\n");
exit(-1);
}

fread(source, 1, size, fp);
source[size] = '\0';

return source;
}

int main()
{
cl_platform_id platform;
cl_device_id device;
cl_context context;
cl_program program; 
cl_kernel kernel;
cl_command_queue queue;
err = openCL_init(platform, device, context);

cl_context_properties props[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)(platform), 0};
context = clCreateContext(props, 1, &device, NULL, NULL, &err);
queue = clCreateCommandQueue(context, device, 0, &err);

const char* source = readSource("rotation.cl");
program = clCreateProgramWithSource(context, 1, &source, NULL, NULL);
err = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
kernel = clCreateKernel(program, "img_rotate", &err);





int imageHeight;
int imageWidth;
const char* inputFile = "input.bmp";
const char* outputFile = "output706.bmp";
// Homegrown function to read a BMP from file
float* inputImage = readImage(inputFile, &imageWidth, &imageHeight);


// The image format describes how the data will be stored in memory
cl_image_format format;
format.image_channel_order = CL_R; // single channel
format.image_channel_data_type = CL_FLOAT; // float data type
cl_mem d_inputImage = clCreateImage2D(context, 0, &format, imageWidth, imageHeight, 0, NULL, &err);
// Create space for the output image on the device
cl_mem d_outputImage= clCreateImage2D(context, 0, &format, imageWidth, imageHeight, 0, NULL, &err);
// Copy the source image to the device
size_t origin[3] = {0, 0, 0}; // Offset within the image to copy from
size_t region[3] = {imageWidth, imageHeight, 1}; // Elements to per dimension
err = clEnqueueWriteImage(queue, d_inputImage, CL_FALSE, origin, region, 
0, 0, inputImage, 0, NULL, NULL);

float theta = 3.14159/6;
float cos_theta = cos(theta);
float sin_theta = sin(theta);

err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &d_outputImage);//【此次出了问题】错误代码 -38 CL_INVALID_MEM_OBJECT 
//err = 9;
err = clSetKernelArg(kernel, 1, sizeof(cl_mem), &d_inputImage);//【此次出了同样的问题】错误代码 -38 CL_INVALID_MEM_OBJECT 
err = clSetKernelArg(kernel, 2, sizeof(int), &imageWidth);
err = clSetKernelArg(kernel, 3, sizeof(int), &imageHeight);
err = clSetKernelArg(kernel, 4, sizeof(float), &sin_theta);
err = clSetKernelArg(kernel, 5, sizeof(float), &cos_theta);

size_t globalSize[2] = {imageWidth, imageHeight};
err = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, globalSize, NULL, 0, NULL, NULL);


// Size of the input and output images on the host
int dataSize = imageHeight*imageWidth*sizeof(float);
// Output image on the host
float* outputImage = NULL;
outputImage = (float*)malloc(dataSize);
err = clEnqueueReadImage(queue, d_outputImage, CL_TRUE, origin, 
region, 0, 0, outputImage, 0, NULL, NULL);
// Write the output image to file
storeImage(outputImage, outputFile, imageHeight, imageWidth, inputFile);

return 0;
}

问题在【147 149】行,请大家看看纠结是怎么回事,十分感谢……(前面的语句都正确,err=0)

回复讨论(解决方案)

这儿(http://elvisjeng.blogspot.com/2011/07/opencl-clcreateimage2d-sample.html)的例子:
ciErr1 = clSetKernelArg( ckKernel, 0, sizeof(cl_mem), (void*)&myClImageInBuffer);
ciErr1 = clSetKernelArg( ckKernel, 1, sizeof(cl_mem), (void*)&myClImageOutBuffer);
这儿(http://elvisjeng.blogspot.com/2011/07/opencl-clcreateimage2d-sample.html)的例子:
ciErr1 = clSetKernelArg( ckKernel, 0, sizeof(cl_mem), (void*)&myClImageInBuffer);
ciErr1 = clSetKernelArg( ckKernel, 1, sizeof(cl_mem), (void*)&myClImageOutBuffer);

改了没用,那个网站打不开……搜索到了相关语句的网页,但是内容也与这个无关……
楼主先确认一下:
cl_mem d_inputImage = clCreateImage2D(context, 0, &format, imageWidth, imageHeight, 0, NULL, &err);
// Create space for the output image on the device
cl_mem d_outputImage= clCreateImage2D(context, 0, &format, imageWidth, imageHeight, 0, NULL, &err);

这两句返回的d_inputImage和d_outputImage不空~
楼主先确认一下:
cl_mem d_inputImage = clCreateImage2D(context, 0, &format, imageWidth, imageHeight, 0, NULL, &err);
// Create space for the output image on the device
cl_mem d_outputImage= clCreateImage2D(context, 0, &format, imageWidth, imageHeight, 0, NULL, &err);

这两句返回的d_inputImage和d_outputImage不空~

唉,似乎是显卡的问题,在GT620跑不起来,但在GTX970能运行起来,真是很奇怪,难道搞OpenCL必须用A卡吗……
唉,似乎是显卡的问题,在GT620跑不起来,但在GTX970能运行起来,真是很奇怪,难道搞OpenCL必须用A卡吗……


呵呵,您说对了。如果您的系统不是OS X的话,还是请使用A卡或Intel的核心GPU来玩OpenCL……不过Intel在Linux上对OpenCL的支持也不太友好~所以,玩OpenCL最佳的系统是OS X,如果是其它操作系统,还是认准A卡,哈哈~