使用clEnqueueWriteBuffer引起的内存损坏问题 - OpenCL

5
我正在编写发送大量数据从主机到设备的代码,但其行为不稳定。
在以下这段代码中,我试图从主机向设备发送一个数组。数组大小在每次迭代中递增,逐渐增加发送到设备的内存量。数组的第一个元素填充了非零值,并且从内核中读取并打印到控制台。当从主机和设备中读取该值时,它应该是相同的,但在某些迭代中不是。
以下是代码:

    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 - 最大常量缓冲区大小: 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     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- 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     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 0.000000     &lt-------- INCORRECT VALUE, kernel is receiving corrupted memory
Array GPU: 68.000000
Array GPU: 69.000000
...

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

总结一下:一个内存块被发送到内核,但是内核根据发送的总块大小接收到了零值内存。

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

如何避免内存损坏?我有什么遗漏吗?

提前致谢。


这里是完整的可工作代码:


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

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


2
所有这些看起来都像C代码,除非你想收到大量“不要使用malloc或new,使用vector”的评论/答案,否则你可能需要取消标记C++。 - Borgleader
1
你是否检查各种OpenCL API调用的返回值?你获取了返回值(ret = ...),但是忽略了返回的值。如果其中一个函数失败,知道这一点将非常有用。 - dsharlet
通常情况下,GPU上的0值是越界内存访问。在CPU上运行并查看是否出现堆栈溢出?请参考此答案:http://stackoverflow.com/questions/25536033/wavelet-transform-written-in-opencl-seeing-artifacts-in-image/25556191#25556191 - Austin
@Austin:这是我在这台电脑上运行代码时发现的另一个问题。它无法识别多个设备,包括GPU(_Intel(R) HD Graphics 4000_)。CPU型号为_i5-3230M CPU @ 2.6GHZ_,支持OpenCL,但即使使用_GPU Caps Viewer_等工具,也只能识别一个平台和一个设备,即GPU。也许这两个问题有关。非常感谢您的回答。 - Backgroung
在写入缓冲区后,尝试使用clEnqueueReadBuffer将其读回到另一个分配的CPU内存块中。这些值是否为0?如果正确,那么问题可能出在内核或printf上,而不是写入缓冲区。 - Dithermaster
显示剩余10条评论
1个回答

0

你试过了吗?

   CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR

由于您的GPU与CPU共享同一内存?

设备也位于主机的相同位置,适用于您的iGPU。

创建一些缓冲区,在它们上面进行压力测试,如果所有缓冲区都得到无效值,则安装另一个驱动程序版本,可能是更新版本,如果这样做不能解决问题,则需要RMA您的卡。

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


我尝试使用_CL_MEM_ALLOC_HOST_PTR_标志创建缓冲区,但结果仍然相同。此外,我在两台与我最初发布的计算机具有相同硬件和驱动程序的计算机上运行代码,它们也返回错误的结果。该计算机是带有专有驱动程序的Dell Vostro,最新更新是在2012年。当我安装了这个最新的更新后,计算机开始识别CPU,并在CPU中运行OpenCL代码可以得到正确的结果。GPU仍然返回错误和不稳定的结果。谢谢回答。 - Backgroung

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接