我的电脑配有AMD处理器和ATI 3200 GPU,不支持OpenCL。其余的代码都是通过“回退到CPU本身”来运行的。
我正在将其中一个代码从CUDA转换为OpenCL,但卡在某个特定部分,而OpenCL中没有确切的转换代码。由于我在OpenCL方面的经验不足,我无法弄明白,如果你们认为有用的话,请建议我一些解决方案,
CUDA代码是,
size_t pitch = 0;
cudaError error = cudaMallocPitch((void**)&gpu_data, (size_t*)&pitch,
instances->cols * sizeof(float), instances->rows);
for( int i = 0; i < instances->rows; i++ ){
error = cudaMemcpy((void*)(gpu_data + (pitch/sizeof(float))*i),
(void*)(instances->data + (instances->cols*i)),
instances->cols * sizeof(float) ,cudaMemcpyHostToDevice);
如果我从上面删除音高值,我最终会遇到一个不能写入设备存储器“gpu_data”的问题。
有人请将此代码转换为OpenCL并回复。我已将其转换为OpenCL,但它无法正常工作且数据未写入“gpu_data”。我转换的OpenCL代码是
gpu_data = clCreateBuffer(context, CL_MEM_READ_WRITE, ((instances->cols)*(instances->rows))*sizeof(float), NULL, &ret);
for( int i = 0; i < instances->rows; i++ ){
ret = clEnqueueWriteBuffer(command_queue, gpu_data, CL_TRUE, 0, ((instances->cols)*(instances->rows))*sizeof(float),(void*)(instances->data + (instances->cols*i)) , 0, NULL, NULL);
有时它对这段代码运行良好并且卡在阅读部分,即
ret = clEnqueueReadBuffer(command_queue, gpu_data, CL_TRUE, 0,sizeof( float ) * instances->cols* 1 , instances->data, 0, NULL, NULL);
overhere。它会给出错误,如
CL_kmeans.exe中0x10001098处的未处理异常:0xC000001D:非法指令。
按下休息时,它会给出:
调试时没有为任何调用堆栈帧加载符号。无法显示源代码。
在调用堆栈中,它显示:
OCL8CA9.tmp.dll!10001098()
[下面的框架可能不正确和/或缺失,没有为OCL8CA9.tmp.dll加载符号]
amdocl.dll!5c39de16()
我真的不知道这意味着什么。有人请帮我摆脱这个问题。
答案 0 :(得分:3)
首先,在CUDA代码中,你正在做一个非常低效的复制数据。 CUDA运行时具有函数cudaMemcpy2D
,它通过循环遍历不同的行来完成您正在尝试执行的操作。
cudaMallocPitch
做的是计算最佳音高(= 2D数组中行之间的字节距离),这样每个新行都从一个最适合合并的地址开始,然后分配一个内存区域作为大小作为音高乘以指定的行数。您可以通过首先计算最佳音高然后分配正确的音量来模拟OpenCL中的相同内容。
最佳音高的计算方法是:(1)获取卡的基地址对齐首选项(CL_DEVICE_MEM_BASE_ADDR_ALIGN属性与clGetDeviceInfo:注意返回的值是以位为单位,所以你必须除以8才能得到字节数);让我们称之为base
(2)找到base
的最大倍数,它不小于你的自然数据间距(sizeof(type)乘以列数);这将是您的pitch
。
然后分配pitch
次行数字节,并将pitch
信息传递给内核。
此外,在将数据从主机复制到设备时,您需要使用专门用于复制2D数据的clEnqueue{Read,Write}BufferRect
(它们是cudaMemcpy2D
的对应物)。