如何解决OpenCL.clSetKernelArg 返回 -51
我尝试在 openCL 中创建并行 bfs,但我对 C++ 没有足够的经验。 所以这可能是内存错误,但我真的不知道如何修复它。 我也找不到错误值 -51 是什么意思。 结果,我在我的 project.exe 中的 0x00007FFCFB06A549 (amdocl64.dll) 处出现了“未处理的异常:0xC0000005:访问冲突读取位置 0xFFFFFFFFFFFFFFFF”。
主要
Graph G(AdjacencyList,Directed);
int startVertex;
vector<int> distance;
vector<bool> visited;
distance = vector<int>(G.numVertices);
visited = vector<bool>(G.numVertices);
bool done = false;
const bool true_value = true;
int level = 0;
// Allocation on device
const int size = G.numVertices * sizeof(int);
const int adjacencySize = G.adjacencyList.size() * sizeof(int);
//OpenCL
cl_int status;
cl_int ret;
cl_platform_id platform_id;
clGetPlatformIDs(1,&platform_id,NULL);
cl_device_id device_id;
ret = clGetDeviceIDs(platform_id,CL_DEVICE_TYPE_GPU,1,&device_id,NULL);
cl_context context = clCreateContext(NULL,NULL,&status);
cl_command_queue command_queue = clCreateCommandQueueWithProperties(context,device_id,&status);
cl_mem d_adjacencyList = clCreateBuffer(context,CL_MEM_READ_WRITE,adjacencySize,&status);
cl_mem d_edgesOffset = clCreateBuffer(context,size,&status);
cl_mem d_edgesSize = clCreateBuffer(context,&status);
cl_mem d_distance = clCreateBuffer(context,&status);
cl_mem d_done = clCreateBuffer(context,sizeof(bool),&status);
status = clEnqueueWriteBuffer(command_queue,d_adjacencyList,CL_TRUE,&G.adjacencyList[0],NULL);
status = clEnqueueWriteBuffer(command_queue,d_edgesOffset,&G.edgesOffset[0],d_edgesSize,&G.edgesSize[0],NULL);
distance = vector<int>(G.numVertices,INT_MAX);
distance[start] = 0;
status = clEnqueueWriteBuffer(command_queue,d_distance,distance.data(),NULL);
char* source_str = NULL;
size_t source_size;
FILE* fp;
fp = fopen("bfs.cl","r");
if (!fp)
{
cout << "Failed to load Kernel\n";
exit(1);
}
source_str = (char*)malloc(MAX_SOURCE_SIZE);
source_size = fread(source_str,MAX_SOURCE_SIZE,fp);
cl_program program = clCreateProgramWithSource(context,(const char**)&source_str,(const size_t*)&source_size,&status);
status = clBuildProgram(program,NULL);
cl_kernel kernel = clCreateKernel(program,"bfs",&status);
status = clSetKernelArg(kernel,sizeof(int),(void*)&G.numVertices);
status = clSetKernelArg(kernel,sizeof(cl_mem),(void*)&d_adjacencyList);
status = clSetKernelArg(kernel,2,(void*)&d_edgesOffset);
status = clSetKernelArg(kernel,3,4,(void*)&d_edgesSize);
status = clSetKernelArg(kernel,5,(void*)&d_distance); //here retirns -51
status = clSetKernelArg(kernel,6,(void*)&level);
status = clSetKernelArg(kernel,7,(void*)&d_done);
内核
__kernel void bfs(int n,__global int *adjacencyList,__global int *edgesOffset,__global int *edgesSize,__global int *distance,int level,__global bool *done) {
int tid = get_global_id(0);
if (tid < n) {
if (distance[tid] == level) {
for (int i = edgesOffset[tid]; i < edgesOffset[tid] + edgesSize[tid]; ++i) {
int v = adjacencyList[i];
if (distance[v] == INT_MAX) {
*done = false;
distance[v] = level + 1;
}
}
}
}
}
解决方法
嗨@Parrison 欢迎来到 StackOverflow!
所有 OpenCL
错误代码都在 cl.h
中定义。在最新的(版本 3)cl.h
中,您会发现在第 194 行和第 270 行之间定义的错误代码,在第 241 行您会发现:
#define CL_INVALID_ARG_SIZE -51
因此 OpenCL ICD 认为您为 distance
传递了错误的变量大小。
但是,在此之前,我可以看到许多其他错误。例如,您需要根据 OpenCL 变量而不是本机变量的大小来设置 OpenCL 缓冲区的大小,例如:
-
cl_int
而不是int
-
cl_float
而不是float
- 特别是
cl_bool
而不是bool
。
无法保证 OpenCL cl_int
与主机 int
的大小相同,并且 OpenCL cl_bool
被定义为 unsigned int
,这极不可能是与 bool
大小相同!
确保所有 OpenCL 内核的参数定义正确,并且
您正在 buffers
程序中为它们创建正确的 variables
和 main
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。