我正在尝试使用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);
}
我认为这两个代码是相同的代码。但第一个代码输出错误。 我不知道这两者有什么区别。
答案 0 :(得分:2)
您的convolution
函数可能会从全局内存中获取整个输入图像,并在全局内存中生成整个输出图像。在单个内核调用中调用此函数三次与在三个单独的内核调用中调用一次之间的区别在于,一个工作项对全局内存的写入对于同一内核调用中的其他工作项是不可见的。这意味着在第一个示例中第二次调用convolution
期间,工作项将读取失效值,而不会看到第一次调用此函数的输出。
OpenCL没有提供任何在整个内核调用中同步全局内存的方法。您可以使用barrier
函数同步工作组中的内存,这可能允许您在单个内核调用中实现算法,并进行一些修改。