【问题标题】:JOCL local memory access syntaxJOCL 本地内存访问语法
【发布时间】:2015-04-06 10:38:58
【问题描述】:

这是我的 OpenCl 内核函数

private static String programSource =


        "__kernel void "+
        "sampleKernel(__local float *a,"+
        "             __local float *b,"+
        "             __global float *c,"+
        "             __global float *d)"+

        "{"+
        "   int gid=get_local_id(0);"+
        "   c[gid]=a[gid]+b[gid];"+
        "   d[gid]=a[gid]-1;"+
        "}";

    clSetKernelArg(kernel, 0, Sizeof.cl_mem, Pointer.to(memObjects[0]));
    clSetKernelArg(kernel, 1, Sizeof.cl_mem, Pointer.to(memObjects[1]));
    clSetKernelArg(kernel, 2, Sizeof.cl_mem, Pointer.to(memObjects[2]));
    clSetKernelArg(kernel, 3, Sizeof.cl_mem, Pointer.to(memObjects[3]));

我已使用全局内存来存储数据。现在我尝试将存储位置转换为本地内存。所以我的代码如下所示:

private static String programSource =
            "__kernel void "+
            "sampleKernel(__local float *a,"+
            "             __local float *b,"+
            "             __global float *c,"+
            "             __global float *d)"+
            "{"+
            "   int gid=get_local_id(0);"+
            "   c[gid]=a[gid]+b[gid];"+
            "   d[gid]=a[gid]-1;"+
            "}";
        clSetKernelArg(kernel, 0, Sizeof.cl_mem, NULL);
        clSetKernelArg(kernel, 1, Sizeof.cl_mem, NULL);
        clSetKernelArg(kernel, 2, Sizeof.cl_mem, Pointer.to(memObjects[2]));
        clSetKernelArg(kernel, 3, Sizeof.cl_mem, Pointer.to(memObjects[3]));

当我执行上述代码时,出现以下语法错误:

NULL cannot be resolved to a variable. 

谁能指出我的错误?

提前致谢!

【问题讨论】:

    标签: parallel-processing opencl gpu amd-processor jocl


    【解决方案1】:

    试试看

    clSetKernelArg(kernel, 0, Sizeof.cl_mem, new Pointer());
    clSetKernelArg(kernel, 1, Sizeof.cl_mem, new Pointer());
    

    这应该会创建一个有效的 NULL 指针。

    【讨论】:

    • 我尝试使用'new Pointer()'和'null'。两者都有效。现在语法错误消失了。但我仍然没有得到预期的结果。 c[] 包含 0.0,d[] 包含 -1.0。正如 jprice 所说,我猜本地内存必须从内核内部初始化。为了将初始数组 a 和 b 存储在本地内存中,应在代码中进行哪些更改?
    • 您的预期结果是什么? ab 是未初始化的浮点值,因此“随机”将它们设置为 0.0
    • 我发现了错误。我放错了输入和输出数组。 a,b 应该是全局的,c,d 应该是本地的。
    【解决方案2】:

    看看other JOCL examples that use local memory,你做的没错,但最后一个参数应该是null而不是NULL(前者是Java关键字,后者通常用于C/C++)。

    也就是说,您在内核中实际使用本地内存的方式并不完全正确(尽管我很欣赏这可能只是让主机端工作的示例内核)。必须在内核内部显式管理将数据移入/移出本地内存 - 主机无法初始化本地内存(在您的示例中,本地内存缓冲区将包含垃圾值)。您的输入值需要在全局内存缓冲区中传递给内核。

    目前,您对 clSetKernelArg 的调用仅为每个本地内存缓冲区分配 4 或 8 个字节 (Sizeof.cl_mem),这可能不是您想要的。这对于全局内存参数来说很好,因为您只存储指针 - 实际的缓冲区分配是在您调用 clCreateBuffer 时执行的。对于本地内存参数,此大小是您希望为缓冲区分配的内存量,因此需要反映您希望存储在本地内存中的数据量(对于每个工作组)。

    【讨论】:

    • 是的,null 有效。我用小写。根据您的评论,我了解到主机将 a、b 传输到全局内存。然后使用内核我必须将数据从全局内存传输到本地内存。那正确吗?如果是这样,将数组 a 和 b 存储在本地内存中的正确方法是什么?我应该对 clSetKernelArg 和内核函数进行哪些更改?关于 clSetKernelArg 中的内存分配,它适用于全局数组 c 和 d。我只分配了 4 个字节。为什么这对于数组 a、b 也不够用?
    • @SadhanaRayan 我已经添加了一些注释,说明为什么clSetKernelArg 中的大小参数对于本地内存与全局内存不同。对于您的示例内核,您的 ab 数组需要在全局内存中,否则它们无法被主机初始化。然后,您可以根据需要手动将它们复制到本地内存(例如local_a[i] = global_a[i])。不过,这只会使内核变慢 - 您的示例内核确实没有本地内存的用例。
    • 我有更大的代码要在 GPU 中运行。现在我只是在练习访问不同的记忆。我从这个链接中读到了一篇文章:openclblog.com/2011/03/is-your-local-memory-really-local.html 正如他所说,我得到了 CL_GLOBAL。那么这是否意味着即使我将数组存储在本地内存中也不会有任何改进?
    • 是的,如果您的设备没有专用的物理本地内存,您不太可能看到任何改进。但是,本地内存对于在工作组内共享数据可能仍然有用,例如在实现并行归约时。
    • 我对 GPU 架构有点困惑。看起来所有卡都没有专用的物理本地存储器。那么在我的情况下,我的工作组将访问哪些物理内存用于本地存储?
    猜你喜欢
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 2018-09-08
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多