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
无法识别的自定义内存分配器或执行其他一些技巧。有很多关于此的话题:
- clGetPlatformIDs Memory Leak
- https://software.intel.com/en-us/forums/opencl/topic/753786
- https://github.com/KhronosGroup/OpenCL-ICD-Loader/issues/13
一般来说,除非您想深入研究库代码并为此做些事情,否则您对此无能为力。
我建议小心压制那些来自图书馆的报道。可以按照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 的软件并重新测试。
我 运行 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
无法识别的自定义内存分配器或执行其他一些技巧。有很多关于此的话题:
- clGetPlatformIDs Memory Leak
- https://software.intel.com/en-us/forums/opencl/topic/753786
- https://github.com/KhronosGroup/OpenCL-ICD-Loader/issues/13
一般来说,除非您想深入研究库代码并为此做些事情,否则您对此无能为力。 我建议小心压制那些来自图书馆的报道。可以按照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 的软件并重新测试。