【问题标题】:Memory corruption using clEnqueueWriteBuffer - OpenCL使用 clEnqueueWriteBuffer 的内存损坏 - OpenCL
【发布时间】:2014-11-11 18:01:07
【问题描述】:

我正在编写一些从主机向设备发送大量数据的代码,但它的行为不规律。

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

代码如下:


    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 - MaxMemoryAllocationSize:425721856 - GlobalMemoryCacheSize: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     &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函数也没有返回错误代码。

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

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

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

提前致谢。


Here的完整工作代码:


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

Here 是没有执行内核的代码。结果还是错的。

【问题讨论】:

  • 所有这些看起来都像 C 代码,您可能需要取消标记 C++,除非您想收到大量“不要使用 malloc,或者新的,使用向量”cmets/answers。
  • 您是否在检查各种 OpenCL API 调用的返回值?您正在获取返回值 (ret = ...),但随后忽略了返回的值。了解其中一个功能是否失败会很有用。
  • 每个 openCL 函数的返回值都打印在完整的工作代码中,该代码链接在帖子末尾。我删除了帖子内代码段中的这些行,只是为了简化它。但是,我检查了每个函数的返回值,在内核返回零(错误值)的情况下,它们都没有返回错误代码。感谢您的回答。
  • GPU 上的 0 值通常是越界内存访问。在 CPU 上运行它,看看是否出现堆栈溢出?检查这个答案:stackoverflow.com/questions/25536033/…
  • 让我猜猜,“AMD printf”...以错误地打印变量值而闻名。尝试将第二个地址设置为第一个地址的值,然后从 CPU 读取它。你会发现操作没问题。看到这个问题:stackoverflow.com/questions/24450831/…

标签: c++ c arrays opencl memory-corruption


【解决方案1】:

你试过了吗

   CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR

因为您的 gpu 与 CPU 共享相同的内存?

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

创建一些缓冲区,对它们进行压力测试,如果它们都得到无效值,则安装另一个驱动程序版本,可能是较新的驱动程序版本,如果这不能解决,RMA 你的卡。

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

【讨论】:

  • 我只是尝试创建添加标志 CL_MEM_ALLOC_HOST_PTR 的缓冲区,但结果是相同的。此外,我在两台具有与我最初发布的相同硬件和驱动程序的计算机上运行代码,它们也返回错误的结果。该计算机是具有专有驱动程序的Dell Vostro,最新更新是在 2012 年。当我安装此最新更新时,计算机开始识别除 GPU 之外的 CPU,并在 CPU 中运行 OpenCL 代码结果是正确的。 GPU 仍然返回错误和不稳定的结果。感谢您的回答。
猜你喜欢
  • 2014-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多