0
package parallelencode;

import org.jocl.*;
import static org.jocl.CL.*;

public class ParallelEncode {
    /**
     * The source code of the OpenCL program to execute
     */
    private static String programSource =
        "__kernel void "+
        "sampleKernel(__global const float *a,"+
        "             __global const float *b,"+
        "             __global uchar16 *c,"+
        "             __global char *d)"+
        "{"+
        "    int gid = get_global_id(0);"+
        "    c[gid] = 'q';"+
        "    "+
        "    d[gid] = 'm';"+
        "}";


    /**
     * The entry point of this sample
     * 
     * @param args Not used
     */
    public static void main(String args[])
    {
        // Create input- and output data 
        int n = 17;
        float srcArrayA[] = new float[n];
        float srcArrayB[] = new float[n];
        char dstArray[] = new char[n];
        char charArray[] = new char[n];
        for (int i=0; i<n; i++)
        {
            srcArrayA[i] = i;
            srcArrayB[i] = i;
        }
        Pointer srcA = Pointer.to(srcArrayA);
        Pointer srcB = Pointer.to(srcArrayB); 
        Pointer dst = Pointer.to(dstArray);
        Pointer cArr = Pointer.to(charArray);

        // The platform, device type and device number
        // that will be used
        final int platformIndex = 0;
        final long deviceType = CL_DEVICE_TYPE_ALL;
        final int deviceIndex = 0;

        // Enable exceptions and subsequently omit error checks in this sample
        CL.setExceptionsEnabled(true);

        // Obtain the number of platforms
        int numPlatformsArray[] = new int[1];
        clGetPlatformIDs(0, null, numPlatformsArray);
        int numPlatforms = numPlatformsArray[0];

        // Obtain a platform ID
        cl_platform_id platforms[] = new cl_platform_id[numPlatforms];
        clGetPlatformIDs(platforms.length, platforms, null);
        cl_platform_id platform = platforms[platformIndex];

        // Initialize the context properties
        cl_context_properties contextProperties = new cl_context_properties();
        contextProperties.addProperty(CL_CONTEXT_PLATFORM, platform);

        // Obtain the number of devices for the platform
        int numDevicesArray[] = new int[1];
        clGetDeviceIDs(platform, deviceType, 0, null, numDevicesArray);
        int numDevices = numDevicesArray[0];

        // Obtain a device ID 
        cl_device_id devices[] = new cl_device_id[numDevices];
        clGetDeviceIDs(platform, deviceType, numDevices, devices, null);
        cl_device_id device = devices[deviceIndex];

        // Create a context for the selected device
        cl_context context = clCreateContext(
            contextProperties, 1, new cl_device_id[]{device}, 
            null, null, null);

        // Create a command-queue for the selected device
        cl_command_queue commandQueue = 
            clCreateCommandQueue(context, device, 0, null);

        // Allocate the memory objects for the input- and output data
        cl_mem memObjects[] = new cl_mem[4];
        memObjects[0] = clCreateBuffer(context, 
            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
            Sizeof.cl_float * n, srcA, null);
        memObjects[1] = clCreateBuffer(context, 
            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
            Sizeof.cl_float * n, srcB, null);
        memObjects[2] = clCreateBuffer(context, 
            CL_MEM_READ_WRITE, 
            Sizeof.cl_char * n, null, null);
        memObjects[3] = clCreateBuffer(context, CL_MEM_READ_WRITE, Sizeof.cl_char * n, null, null);

        //char *h_rp = (char*)malloc(length);
        //cl_mem d_rp = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, length, h_rp, &err);
        //err = clSetKernelArg(ckKernel, 0, sizeof(cl_mem), &d_rp)

        // Create the program from the source code
        cl_program program = clCreateProgramWithSource(context,
            1, new String[]{ programSource }, null, null);

        // Build the program
        clBuildProgram(program, 0, null, null, null, null);

        // Create the kernel
        cl_kernel kernel = clCreateKernel(program, "sampleKernel", null);

        // Set the arguments for the kernel
        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]));

        // Set the work-item dimensions
        long global_work_size[] = new long[]{n};
        long local_work_size[] = new long[]{1};

        // Execute the kernel
        clEnqueueNDRangeKernel(commandQueue, kernel, 1, null,
            global_work_size, local_work_size, 0, null, null);

        // Read the output data
        clEnqueueReadBuffer(commandQueue, memObjects[2], CL_TRUE, 0,
            n * Sizeof.cl_char, dst, 0, null, null);

        clEnqueueReadBuffer(commandQueue, memObjects[3], CL_TRUE, 0,
                n * Sizeof.cl_char, cArr, 0, null, null);

        // Release kernel, program, and memory objects
        clReleaseMemObject(memObjects[0]);
        clReleaseMemObject(memObjects[1]);
        clReleaseMemObject(memObjects[2]);
        clReleaseMemObject(memObjects[3]);
        clReleaseKernel(kernel);
        clReleaseProgram(program);
        clReleaseCommandQueue(commandQueue);
        clReleaseContext(context);

        System.out.println(java.util.Arrays.toString(dstArray));
        System.out.println(java.util.Arrays.toString(charArray));
    }
}

结果:

[?, ?, ?, ?, ?, ?, ?, ?, q,  ,  ,  ,  ,  ,  ,  ,  ]
[?, ?, ?, ?, ?, ?, ?, ?, m,  ,  ,  ,  ,  ,  ,  ,  ]

为什么它不为数组中的每个生成 aq,问号是什么?我尝试改变一些东西,比如int gid = get_global_id(0);to int gid = get_global_id(1);,最终结果是[q, , , ...][m, , , ...]。有人可以解释一下,以及如何将多个chars 作为输入传递给 OpenCL 内核吗?

4

2 回答 2

2
 int n = 17;

这没关系,除了缓冲区副本。

clEnqueueReadBuffer(commandQueue, memObjects[3], CL_TRUE, 0,
            n * Sizeof.cl_char, cArr, 0, null, null);

这读取 8 个半char值或 17 个字节。java char(2 个字节)和设备端 char(1 个字节)不匹配。

这就是为什么您q在第 17 个字节或第 9 个元素处看到正确的原因。

java bool 数组也会出现类似的错误。

uchar16 也表示 16 个字节。

    clEnqueueReadBuffer(commandQueue, memObjects[2], CL_TRUE, 0,
        n * Sizeof.cl_char, dst, 0, null, null);

这需要乘以 16,除非每个元素都适用于所有 16 个元素。如果您的意思是每个 16 字节的 17 个元素,那么 n*16 应该在那里并且主机端(java)应该提供字节数组。

于 2017-06-23T13:48:50.800 回答
1

huseyin tugrul buyukisik 的回答中已经提到了最重要的一点:

javachar两个字节(16 位)组成。在 C 和 OpenCL 中,achar一个字节(8 位)。

尚不完全清楚您的程序最终应该做什么,但正如 huseyin 所说:我很确定您打算使用 achar2而不是char16(假设这将是一些与 UTF16 相关的程序 - 否则,主机代码没有意义)。此外,您似乎以某种方式混合了输入和输出数组。


笔记:

如果您现在将其更改为使用uchar2,您可能还会遇到OpenCL 的限制:根据Khronos 网站上提到的限制

小于 32 位的内置类型,即 char、uchar、char2、uchar2、short、ushort 和 half 具有以下限制:

不支持写入char、uchar、char2、uchar2、short、ushort 和 half ...类型的指针(或数组)。


如果您更清楚地描述程序应该做什么(并在此处给我留言,作为评论),我将尝试添加一个小示例来演示如何处理此问题。

于 2017-06-27T19:01:54.293 回答