【问题标题】:What is openCL equivalent for this cuda "cudaMallocPitch "code.?这个 cuda“cudaMallocPitch”代码的 openCL 等效项是什么?
【发布时间】:2014-11-20 08:30:01
【问题描述】:

我的电脑有一个 AMD 处理器和一个不支持 OpenCL 的 ATI 3200 GPU。其余代码全部通过“回退到 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);

这里。它给出了类似的错误

CL_kmeans.exe 中 0x10001098 处的未处理异常:0xC000001D:非法指令。

当按下 break 时,它给出:

没有为任何调用堆栈帧加载符号。无法显示源代码。

调试时。在调用堆栈中显示:

OCL8CA9.tmp.dll!10001098()
[以下帧可能不正确和/或丢失,没有为 OCL8CA9.tmp.dll 加载符号]
amdocl.dll!5c39de16()

我真的不知道这是什么意思。有人请帮我解决这个问题。

【问题讨论】:

    标签: visual-c++ opencl gpu amd-processor


    【解决方案1】:

    首先,在 CUDA 代码中,复制数据的效率极低。 CUDA 运行时有函数cudaMemcpy2D,它通过循环遍历不同的行来完成你想要做的事情。

    cudaMallocPitch 所做的是计算最佳间距(= 二维数组中的行之间的字节距离),以便每个新行从最适合合并的地址开始,然后分配一个内存区域,其大小为pitch 乘以您指定的行数。您可以在 OpenCL 中模拟同样的事情,首先计算最佳音高,然后分配正确的尺寸。

    最佳间距是通过 (1) 获取卡的基地址对齐首选项来计算的(使用 clGetDeviceInfo 的 CL_DEVICE_MEM_BASE_ADDR_ALIGN 属性:注意返回值以位为单位,因此您必须除以 8 才能以字节为单位);让我们称之为base (2) 找到不小于自然数据间距的base 的最大倍数(sizeof(type) 乘以列数);这将是你的pitch

    然后分配pitch 乘以行数字节,并将pitch 信息传递给内核。

    另外,当从主机复制数据到设备时,你想使用clEnqueue{Read,Write}BufferRect,它专门用于复制二维数据(它们是cudaMemcpy2D的对应物)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-20
      • 1970-01-01
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多