OpenCL clCreateContextFromType 函数导致内存泄漏

OpenCL clCreateContextFromType function results in memory leaks

我 运行 valgrind 我的一个开源 OpenCL 代码(https://github.com/fangq/mmc), and it detected a lot of memory leaks in the OpenCL host code. Most of those pointed back to the line 我在其中使用 clCreateContextFromType.

创建了上下文对象

我仔细检查了我所有的 OpenCL 变量、命令队列、内核和程序,并确保它们 are all properly released, but still, when testing on sample programs, every call to the mmc_run_cl() function 将内存增加 300MB-400MB,并且不会在 return 时释放。

您可以通过 运行在终端中执行以下命令来重现 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 到列表)。

在下面的 table 中,我在 Linux 框 (Ubuntu 16.04) 上列出了 NVIDIA GPU (TitanV) 上每个 valgrind 检测到的泄漏的重复计数,其中包含最新的驱动+cuda 9.

同样,大多数泄漏都与 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 个英特尔 CPU 上进行了以下测试。他说的是对的——英特尔 OpenCL 库不会发生内存泄漏,我还发现 AMD OpenCL 驱动程序也很好。唯一的问题是 NVIDIA OpenCL 库似乎在我测试的两个 GPU(Titan V 和 RTX2080)上都有泄漏。

我的测试结果如下。 Memory/CPU 介绍了使用 psrecord 进行分析 in this post

我将提出一个关于如何使用 NVIDIA OpenCL 减少内存泄漏的新问题和赏金。如果您有这方面的经验,请分享。将 post 下面的 link。谢谢

I double checked all my OpenCL variables, command queues, kernels and programs, and made sure that they are all properly released...

好吧,我仍然在 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

... but still, when testing on sample programs, every call to the mmc_run_cl() function bumps up memory by 300MB-400MB and won't release at return

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

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

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