设置主机和执行功能有什么区别

What is difference between setting host and executing function?

本文关键字:什么 区别 功能 执行 主机 设置      更新时间:2023-10-16

我正在尝试使用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();

这段代码也执行相同的函数"卷积",但内核代码是这样更改的。

__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函数可能从全局内存中获取整个输入图像,并在全局内存中生成整个输出图像。在单个内核调用中调用此函数三次与在三个单独的内核调用中一次的区别在于,一个工作项对全局内存的写入对同一内核调用中的其他工作项不可见。这意味着,在第一个示例中对convolution的第二次调用期间,工作项将读取过时的值,而看不到此函数的第一次调用的输出。

OpenCL没有提供任何方法来在整个内核调用中同步全局内存。您可以使用barrier函数来同步工作组中的内存,这可能允许您在单个内核调用中实现算法,但需要进行一些修改。