【问题标题】:OpenCL clCreateContextFromType function results in memory leaksOpenCL clCreateContextFromType 函数导致内存泄漏
【发布时间】:2020-04-12 04:11:20
【问题描述】:

我对我的一个开源 OpenCL 代码 (https://github.com/fangq/mmc) 运行了 valgrind,它在 OpenCL host code 中检测到大量内存泄漏。大多数人都指向the line,我在其中使用clCreateContextFromType 创建了上下文对象。

我仔细检查了我所有的 OpenCL 变量、命令队列、内核和程序,并确保它们 are all properly released,但是,在对示例程序进行测试时,每次调用 mmc_run_cl() function 都会增加 300MB-400MB 的内存并且不会在返回时释放。

您可以通过在终端中运行以下命令来重现 valgrind 报告:

git clone https://github.com/fangq/mmc.git
cd mmc/src
make clean
make all
cd ../examples/validation
valgrind --show-leak-kinds=all --leak-check=full ../../src/bin/mmc -f cube2.inp -G 1 -s cube2 -n 1e4 -b 0 -D TP -M G -F bin

假设您的系统安装了 gcc/git/libOpenCL 和 valgrind。如果您想在其他 OpenCL 设备上运行 -G 1 输入,请将其更改为不同的数字(将 -L 添加到列表中)。

在下表中,我列出了使用最新驱动程序+cuda 9 在 Linux 机器 (Ubuntu 16.04) 上的 NVIDIA GPU (TitanV) 上检测到的每个 valgrind 泄漏的重复计数。

同样,大多数泄漏与 clCreateContextFromType 行相关,我假设一些 GPU 内存没有释放,但我确实在主机代码末尾释放了所有 GPU 资源。

您是否注意到我在主机代码中遗漏的任何内容?非常感谢您的意见

counts |        error message
------------------------------------------------------------------------------------
    380 ==27828==    by 0x402C77: main (mmc.c:67)
Code: entry point to the below errors

     64 ==27828==    by 0x41CF02: mcx_list_gpu (mmc_cl_utils.c:135)
Code: OCL_ASSERT((clGetPlatformIDs(0, NULL, &numPlatforms)));

      4 ==27828==    by 0x41D032: mcx_list_gpu (mmc_cl_utils.c:154)
Code: context=clCreateContextFromType(cps,devtype[j],NULL,NULL,&status);

     58 ==27828==    by 0x41DF8A: mmc_run_cl (mmc_cl_host.c:111)
Code: entry point to the below errors

    438 ==27828==    by 0x41E006: mmc_run_cl (mmc_cl_host.c:124)
Code: OCL_ASSERT(((mcxcontext=clCreateContextFromType(cprops,CL_DEVICE_TYPE_ALL,...));

     13 ==27828==    by 0x41E238: mmc_run_cl (mmc_cl_host.c:144)
Code: OCL_ASSERT(((mcxqueue[i]=clCreateCommandQueue(mcxcontext,devices[i],prop,&status),status)));

      1 ==27828==    by 0x41E7A6: mmc_run_cl (mmc_cl_host.c:224)
Code:  OCL_ASSERT(((gprogress[0]=clCreateBufferNV(mcxcontext,CL_MEM_READ_WRITE, NV_PIN, ...);

      1 ==27828==    by 0x41E7F9: mmc_run_cl (mmc_cl_host.c:225)
Code: progress = (cl_uint *)clEnqueueMapBuffer(mcxqueue[0], gprogress[0], CL_TRUE, ...);

     10 ==27828==    by 0x41EDFA: mmc_run_cl (mmc_cl_host.c:290)
Code: status=clBuildProgram(mcxprogram, 0, NULL, opt, NULL, NULL);

      7 ==27828==    by 0x41F95C: mmc_run_cl (mmc_cl_host.c:417)
Code: OCL_ASSERT((clEnqueueReadBuffer(mcxqueue[devid],greporter[devid],CL_TRUE,0,...));

更新 [04/11/2020]:

阅读 @doqtor 的评论后,我在 5 个不同的设备、2 个 NVIDIA GPU、2 个 AMD GPU 和 1 个 Intel CPU 上进行了以下测试。他说的是正确的——英特尔 OpenCL 库不会发生内存泄漏,我还发现 AMD OpenCL 驱动程序也很好。唯一的问题是 NVIDIA OpenCL 库似乎在我测试的两个 GPU(Titan V 和 RTX2080)上都有泄漏。

我的测试结果如下。使用 psrecord 进行内存/CPU 分析已引入 in this post

我将就如何使用 NVIDIA OpenCL 减少这种内存泄漏提出一个新问题和赏金。如果你有这方面的经验,请分享。将在下面发布链接。谢谢

【问题讨论】:

  • 您是否尝试过使用minimal reproducible example 重现您的问题?
  • 你试过我上面的 6 命令示例了吗?
  • 这不是我可以编译的东西......另外问题是您是否首先使用最小可重现示例重现了您的问题?
  • 我认为我的 6 命令示例代码是最小可重现示例 - 因为此报告的行为发生在当前代码库中,您可以使用我的命令重现它。如果无法编译,可以从mcx.space/nightly/linux64/mcxcl-linux-x86_64-nightlybuild.zip下载预编译的nightly build
  • 我认为@doqtor 的意思可能是:您是否尝试过删除代码片段以缩小问题发生与未发生时的范围?也许这个网站上的某个人有时间阅读并完全理解您的 500LOC 函数,但如果您发布一段简化得多且更易于理解的代码,并显示出相同的问题,您更有可能获得帮助。

标签: performance debugging memory-leaks opencl valgrind


【解决方案1】:

我仔细检查了所有的 OpenCL 变量、命令队列、内核和 程序,并确保它们都已正确发布...

嗯,我仍然在 mmc 代码中发现了一个(微小的)内存泄漏:

==15320== 8 bytes in 1 blocks are definitely lost in loss record 14 of 1,905
==15320==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15320==    by 0x128D48: mmc_run_cl (mmc_cl_host.c:137)
==15320==    by 0x11E71E: main (mmc.c:67)

greporter 分配的内存未被释放。所以这要由你来解决。

其余的是 OpenCL 库中的潜在内存泄漏。它们可能是也可能不是内存泄漏,例如库可能使用valgrind 无法识别的自定义内存分配器或执行其他一些技巧。有很多关于此的主题:

一般来说,除非您想深入了解库代码并为此做点什么,否则您对此无能为力。 我建议仔细压制那些来自图书馆的报道。可以按照 valgrind 手册中的说明生成抑制文件:https://valgrind.org/docs/manual/manual-core.html#manual-core.suppress

...但是,在对示例程序进行测试时,每次调用 mmc_run_cl() 函数将内存增加 300MB-400MB 并且不会释放 返回时

你是怎么检查的?我还没有看到内存可疑地增长。我设置了-n 1000e4,它让它运行了大约 2 分钟,其中分配的内存一直保持在我 RAM 大小的 ~0.6% 处。请注意,我没有在 Intel GPU 和 CPU 上使用 nvidia CUDA,而是在 POCL 上使用,并与从 Ubuntu 18.04 上的 ocl-icd-libopencl1:amd64 软件包安装的 libOpenCL 链接。所以你可以尝试一下,看看是否有任何改变。

======== 更新=================================

我已按照您在评论中的描述重新运行它,第一次迭代后内存使用率为 0.6%,然后在第二次迭代后增加到 0.9%,之后下一次迭代没有增加内存使用率。除了我之前观察到的之外,Valgrind 也没有报告任何更新的内容。所以我建议链接不同于 nvidia-cuda libOpenCL 并重新测试。

【讨论】:

  • 感谢 @doqtor 的 cmets。关于greporter,是的,你是对的。我在调试方面发现了它:见github.com/fangq/mmc/commit/…。多次运行模拟时,我观察到 matlab mex 文件中的内存泄漏。要在二进制文件中重现此内容,您可以打开mmc.c,在mmc_init_from_cmd 之前插入for(int i=0;i<5;i++){,并在底部的return 0 之前插入getchar(); }。当您使用它再次运行我的基准测试时,您可以看到每次迭代的内存增加了 300MB。
  • 谢谢。我更新了我原来的问题并确认 Intel 和 AMD OpenCL 中没有内存泄漏,但它确实出现在 NVIDIA GPU 上。我将开一个新的赏金/问题,专门讨论如何减少nvidia内存泄漏,如果您有经验,欢迎分享!再次感谢
  • 在这里发布了我的后续问题:stackoverflow.com/questions/61163373/…
猜你喜欢
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
  • 1970-01-01
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
  • 2015-07-06
  • 2014-06-07
相关资源
最近更新 更多