使用clEnqueueWriteBuffer的内存损坏-OpenCL

Memory corruption using clEnqueueWriteBuffer - OpenCL

本文关键字:损坏 -OpenCL 内存 clEnqueueWriteBuffer 使用      更新时间:2023-10-16

我正在处理一些代码,这些代码将大量数据从主机发送到设备,并且它的行为不稳定。

在下面的代码中,我试图将一个数组从主机发送到设备。阵列大小在每次迭代中都在增加,逐渐增加发送到设备的内存量。数组中的第一个元素填充了一个非零值,然后从内核内部读取并打印到控制台。当从主机和设备读取时,该值应该是相同的,但在某些迭代中却不是。

这是代码:


    int SizeArray = 0;
    for(int j=1; j<100 ;j++){ 
        //Array memory allocation, starting with 4MB in first iteration to 400MB in last one
        SizeArray = j * 1000000 * sizeof(float);
        Array = (float*)malloc(SizeArray);
        memset(Array, 0, SizeArray);
        //Give the array's first element some nonzero value
        //This is the value that is expected to be printed by the kernel execution
        Array[0] = j;
        memArray = clCreateBuffer(context, CL_MEM_READ_WRITE, SizeArray, NULL, &ret);
        //Write the array contents into the buffer inside the device
        ret = clEnqueueWriteBuffer(command_queue, memArray, CL_TRUE, 0, SizeArray, Array, 0, NULL, NULL);
        ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memArray);
        getchar();
        //Execute the kernel where the content of the first element of the array will be printed
        ret = clEnqueueNDRangeKernel(command_queue, kernel, 3, NULL, mGlobalWorkSizePtr, mLocalWorkSizePtr, 0, NULL,NULL);
        ret = clFinish(command_queue);
        /****** FAIL! Kernel prints correct value of Array's first element ONLY IN 
        SOME ITERATIONS (when it fails zero values are printed)! Depending on SizeArray :?? ******/
        free(Array);
        ret = clReleaseMemObject(memArray);
    }

测试该代码的设备具有以下功能:

    -名称:Intel(R)HD Graphics 4000-设备版本:OpenCL 1.1-驱动程序版本:8.15.10.2696-最大内存分配大小:425721856-全局内存缓存大小:2097152-全局内存大小:1702887424-MaxConstantBufferSize:65536-本地内存大小:65536

内核是否打印错误的值,取决于发送到设备的缓冲区大小。

这是输出:


Array GPU: 1.000000
Array GPU: 2.000000
Array GPU: 3.000000
Array GPU: 4.000000
Array GPU: 5.000000
Array GPU: 6.000000
Array GPU: 7.000000
Array GPU: 8.000000
Array GPU: 9.000000
Array GPU: 10.000000
Array GPU: 11.000000
Array GPU: 12.000000
Array GPU: 13.000000
Array GPU: 14.000000
Array GPU: 15.000000
Array GPU: 16.000000
Array GPU: 17.000000
Array GPU: 18.000000
Array GPU: 19.000000
Array GPU: 20.000000
Array GPU: 21.000000
Array GPU: 22.000000
Array GPU: 23.000000
Array GPU: 24.000000
Array GPU: 25.000000
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 34.000000
Array GPU: 35.000000
Array GPU: 36.000000
Array GPU: 37.000000
Array GPU: 38.000000
Array GPU: 39.000000
Array GPU: 40.000000
Array GPU: 41.000000
Array GPU: 42.000000
Array GPU: 43.000000
Array GPU: 44.000000
Array GPU: 45.000000
Array GPU: 46.000000
Array GPU: 47.000000
Array GPU: 48.000000
Array GPU: 49.000000
Array GPU: 50.000000
Array GPU: 51.000000
Array GPU: 52.000000
Array GPU: 53.000000
Array GPU: 54.000000
Array GPU: 55.000000
Array GPU: 56.000000
Array GPU: 57.000000
Array GPU: 58.000000
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     <-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 68.000000
Array GPU: 69.000000
...

正如您所看到的,设备接收到的值不正确,没有明显的模式,clEnqueueWriteBuffer函数也没有返回错误代码。

总结一下:一个内存块被发送到内核,但内核接收到的内存为零,这取决于发送的总块大小。

在不同的计算机上测试的相同代码表现不同(不同迭代中的值不正确)。

如何避免内存损坏?我是不是错过了什么?

提前谢谢。


以下是完整的工作代码:


编辑:经过一些测试后,需要澄清问题不在printf中。问题似乎是在内核执行之前向设备传输数据。

这是没有执行内核的代码。结果仍然是错误的。

你试过吗

   CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR

因为你的gpu和CPU共享相同的内存?

设备也位于iGPU主机的同一位置。

创建一些缓冲区,对它们进行压力测试,如果所有的缓冲区都得到了无效的值,那么安装另一个驱动程序版本,可能是一个新的版本,如果这不能解决,请重新授权您的卡。

如果只有一个缓冲区是错误的,那么这就是简单的vram错误,将该缓冲区标记为不可用,并根据需要创建新的缓冲区,并避免该缓冲区,但我不确定驱动程序是否在后台交换缓冲区。如果每个内核都出现故障,那么内核也可能损坏。