我已经创建了内核函数,该内核函数从某些范围中计算积分,并将结果添加到变量(每个gpu一个变量),在主机中,我将它们全部添加,我都有积分的结果(在此为此情况x^2dx),对于0-8,我的结果是170,666 ...是真的。我使用的是全球工作尺寸1、2、4、8、16、32,它适用于所有工作,但是由于某种原因,当我将GWS更改为64时,我会有细分故障。我有1个平台(包含8张GPU卡)每个设备都有自己的队列,上下文,内核。
这是我的代码中的几行:
im创建3个缓冲区,我以后将其传递给内核(第三个用于阅读结果)。
cl_mem bufferA[deviceNumber];
cl_mem bufferB[deviceNumber];
cl_mem bufferC[deviceNumber];
for(int i = 0; i< deviceNumber; i++){
bufferA[i] = clCreateBuffer(context[i], CL_MEM_READ_WRITE , sizeof(float) * global_size, NULL, &error);
bufferB[i] = clCreateBuffer(context[i], CL_MEM_READ_ONLY , sizeof(float) * global_size, NULL, &error);
bufferC[i] = clCreateBuffer(context[i], CL_MEM_WRITE_ONLY, sizeof(float) * global_size, NULL, &error);
}
稍后创建和构建程序后,我设置了内核。
for(int i = 0; i< deviceNumber; i++){
error = clSetKernelArg(kernel[i], 0, sizeof(cl_mem), (void*)&bufferA[i]);
error = clSetKernelArg(kernel[i], 1, sizeof(cl_mem), (void*)&bufferB[i]);
error = clSetKernelArg(kernel[i], 2, sizeof(cl_mem), (void*)&bufferC[i]);
error = clSetKernelArg(kernel[i], 3, sizeof(cl_int), (void*)&global_size);
}
和起重点的写作
for(int i = 0; i< deviceNumber; i++){
error = clEnqueueWriteBuffer(commandQueue[i], bufferA[i], CL_FALSE, 0, sizeof(float) * global_size, a, 0, NULL, NULL);
error = clEnqueueWriteBuffer(commandQueue[i], bufferB[i], CL_FALSE, 0, sizeof(float) * global_size, &b[i], 0, NULL, NULL);
}
启动内核来完成他们的工作。
for(int i = 0; i< deviceNumber; i++){
error = clEnqueueNDRangeKernel(commandQueue[i], kernel[i], 1, NULL, &global_size, &localWorkSize, 0, NULL, NULL);
}
最后放置了发生segfault的地方:
for(int i = 0; i< deviceNumber; i++){
std::cout<<"clEnqueueReadBuffer: "<<error<<std::endl;
error = clEnqueueReadBuffer(commandQueue[i], bufferC[i], CL_TRUE, 0, sizeof(float) * global_size, &c[i], 0, NULL, NULL);
}
我到处都在打印错误代码,并且有全部0我在输出中看到的最后一件事是,在clenqueereadbuffer之前的那个字符串,因此在第一次迭代中崩溃了。
有人知道我在这里错过了什么吗?
找到了故障!
sizeof(float) * global_size
可以读取矢量的大小等于global_size,但是在将代码重新编写为积分之后,我完全忘记了这一点,如果您读取每个设备的一个变量,则仅需要SizeOf(键入)。希望它能帮助某人