我正在尝试使用 Opencl 制作卷积图像。
__kernel void convolution_read4(__global uchar *in1, __global uchar* in2,
__constant float* mask, int height, int width, int kernelSize,
__local float* lMem, int localHeight, int localWidth)
{
convolution(in1, in2, mask, height, width, kernelSize, lMem, localHeight, localWidth);
convolution(in2, in1, mask, height, width, kernelSize, lMem, localHeight, localWidth);
convolution(in1, in2, mask, height, width, kernelSize, lMem, localHeight, localWidth);
}
上层代码执行同一个函数3次。
err = kernel.setArg(0, d_inputImage);
err |= kernel.setArg(1, d_outputImage);
err |= kernel.setArg(2, d_filter);
err |= kernel.setArg(3, Height);
err |= kernel.setArg(4, Width);
err |= kernel.setArg(5, kernelSize);
err |= kernel.setArg(6, localSize, NULL);
err |= kernel.setArg(7, localHeight);
err |= kernel.setArg(8, localWidth);
int totalWorkItemX = roundUp(Width - paddingPixels, wgWidth);
int totalWorkItemY = roundUp(Height - paddingPixels , wgHeight);
cl::NDRange globalws(totalWorkItemX, totalWorkItemY);
cl::NDRange localws(wgWidth, wgHeight);
err = queue.enqueueNDRangeKernel(kernel, cl::NullRange,
globalws, localws, NULL, NULL);
err = kernel.setArg(1, d_inputImage);
err |= kernel.setArg(0, d_outputImage);
err = queue.enqueueNDRangeKernel(kernel, cl::NullRange,
globalws, localws, NULL, NULL);
err = kernel.setArg(0, d_inputImage);
err |= kernel.setArg(1, d_outputImage);
err = queue.enqueueNDRangeKernel(kernel, cl::NullRange,
globalws, localws, NULL, NULL);
queue.finish();
此代码也执行相同的函数“Convolution”,但内核代码已更改为那样。
__kernel void convolution_read4(__global uchar *in1, __global uchar* in2,
__constant float* mask, int height, int width, int kernelSize,
__local float* lMem, int localHeight, int localWidth)
{
convolution(in1, in2, mask, height, width, kernelSize, lMem, localHeight, localWidth);
}
我认为这两个代码是相同的代码。但是第一个代码得出了错误的输出。 我不知道这两者有什么区别。
最佳答案
您的卷积
函数可能会从全局内存中获取整个输入图像,并在全局内存中生成整个输出图像。在单个内核调用中调用此函数三次与从三个单独的内核调用中调用一次之间的区别在于,一个工作项对全局内存的写入对于同一内核调用中的其他工作项是不可见的。这意味着在您的第一个示例中第二次调用 convolution
期间,工作项将读取陈旧值,并且看不到第一次调用此函数的输出。
OpenCL 不提供任何方式来同步整个内核调用中的全局内存。您可以使用 barrier
函数同步工作组内的内存,这可能允许您在单个内核调用中实现您的算法,并进行一些修改。
关于c++ - 设置主机和执行功能有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26237678/