【问题标题】:Opencl kernel buffers leaking after 12k float elementsOpencl 内核缓冲区在 12k 浮点元素后泄漏
【发布时间】:2013-07-31 21:29:42
【问题描述】:

我在 C++ 中为 opencl 编写了一个点积内核,它适用于向量长度 4096(也尝试了 12k 个元素并且工作完美)但是当我将向量长度增加到 16k 个元素时,结果变为无穷大 虽然它不应该超过一个小的浮点数。显然有泄漏或类似的东西,但它适用于 n

这是从 C# 通过 DLL 调用传递给 C++ 的内核(Ln= 本地工作大小,n= 全局工作大小):

"__kernel void SkalarCarpim(__global float * v1, __global float * v2, __global float * v3)" +
            "{" +
            "    int i = get_global_id(0);" +
            "    int j = get_local_id(0);" +
            "    __local float biriktirici [" + Ln.ToString() + "];" +
            "    barrier(CLK_LOCAL_MEM_FENCE);" +
            "    biriktirici[j]=v1[i]*v2[i];" +
            "    barrier(CLK_LOCAL_MEM_FENCE);" +
            "    barrier(CLK_GLOBAL_MEM_FENCE);" +
            "    float toplam=0.0f;" +
            "    if(j==0)" +
            "    {" +
            "        for(int k=0;k<"+Ln.ToString()+";k++)"+ // reduction
            "        {"+
            "             toplam+=biriktirici[k];"+
            "        }"+
            "    }" +
            "    barrier(CLK_GLOBAL_MEM_FENCE);" +
            "    v3[i]=toplam;" +
            "    barrier(CLK_GLOBAL_MEM_FENCE);" +
            "    toplam=0.0f;" +
            "    for(int k=0;k<"+(n/Ln).ToString()+";k++)" + 
            "    {" +
            "         toplam+=v3[k*"+Ln.ToString()+"];       " + // sum of temporary sums
            "    }" +
            "    v3[i]=toplam;"+
            "}";

这里是 C++ Opencl 缓冲区:

buf1=cl::Buffer(altYapi,CL_MEM_READ_WRITE,sizeof(cl_float) * N);
buf2=cl::Buffer(altYapi,CL_MEM_READ_WRITE,sizeof(cl_float) * N);
buf3=cl::Buffer(altYapi,CL_MEM_READ_WRITE,sizeof(cl_float) * N);
//CL_MEM_READ_ONLY makes same error, tried some other too, no solution :(

以下是缓冲区的发送方式:

komutSirasi.enqueueWriteBuffer(buf1,CL_TRUE,0,sizeof(cl_float)*N,v1);
komutSirasi.enqueueWriteBuffer(buf2,CL_TRUE,0,sizeof(cl_float)*N,v2);
//CL_TRUE makes a blocking action so waits until finished

执行:

 komutSirasi.enqueueNDRangeKernel(kernel,0,Global,Local);
 //I got this from an example and I dont know if it is blocking or not.

这是结果缓冲区的获取方式(所有元素都是结果,我知道它未完成):

komutSirasi.enqueueReadBuffer(buf3,CL_TRUE,0,sizeof(cl_float) * N,v3);
//CL_TRUE makes a blocking action so waits until finished

问题:在深入研究 C++ Opencl 之前,我必须做一些配置吗?这在 Java/Aparapi/Jocl 中不是问题。

使用来自 Khronos 网站的 Opencl 1.2 头文件和 AMD Opencl.lib + Opencl.dll 来解决这个问题(目标设备是 HD7870)。

【问题讨论】:

    标签: c# c++ buffer opencl dot-product


    【解决方案1】:

    您的第二次缩减,即 v3[k*N] 的总和,假设 v3 中的所有值都已计算完毕。这将需要不同工作组之间的同步,这在一般情况下是不可能的。当只有一个工作组时,可能会意外发生。

    第一次缩减后,您应该将 toplam 存储在 v3[get_group_id(0)] 中,然后运行第二个内核进行第二次缩减。

    【讨论】:

    • 但它已经在处理 64 个组,每个组有 64 个元素,全局大小 = 4096。
    • 是的,它也可能在这种情况下意外工作,因为所有工作组将意外地同时安排在所有计算单元上。这仍然是一个意外。全局同步在一般情况下不起作用。
    • 这是无穷大的原因吗?因为缓冲区在发送之前都设置为小浮点数。甚至所有元素的 v3 向量都初始化为 1。
    • 我们正在告诉您。这是。即使你设置 100 万个全球障碍,它也行不通。因为障碍在工作组之外不起作用。对于特定的硬件和组大小,它“可能”起作用。但这只是一种错觉。
    • 你是对的。刚刚尝试了蛮力,它奏效了。谢谢你。我将使它成为多级内核执行(稍后我将使它成为矩阵乘法)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 2016-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多