如何使用Cuda避免segfault上的内存泄漏
How to avoid memory leak on segfault with Cuda
我在集成分支上使用cuda设备,在完成工作时仍有一些segfault。
每次崩溃后,我的内存消耗都会增加500 Mo(使用free -m
、htop
和另一个,但我记不起名字了)。这个内存从来没有释放过,所以在这台有4Go RAM的计算机上,所以我必须在一些崩溃后重新启动,否则内存交换真的很慢(就像往常一样,当内存交换发生时)。
我知道最好的答案是:"修复你的segfault!!"但我想了解为什么会发生这种行为,以及我如何防止它。
我读到CUDA内存应该由操作系统在segfault上发布,但看起来并没有。
当我尝试调试我的程序时,我注意到如果我修复了segfault,内存就可以正常释放了,但如果我也注释了cuda发布行:cudaFreeHost(buf)
(修复了sedfault),我仍然存在内存泄漏。
我的内存被分配为固定页面:cudaHostAlloc(&ret, n*sizeof(my_struct), cudaHostAllocPortable)
。
我想确保使用unique_ptr
调用"free"代码,但它不能解决segfault的问题。
我研究了CUDA的持久模式:http://docs.nvidia.com/deploy/driver-persistence/index.html但它在我的电脑上是禁用的(我用nvidia-smi
检查了它)。
我试图重置cuda设备:nvidia-smi -r
,但它说我的计算机不支持它。
问题是:
- 我们如何要求程序(或操作系统)在程序结束时释放这些资源
- 如果我们不能,是否存在在崩溃后恢复这些资源的命令
版本:
-
CUDA 6.0.1
-
gcc 4.9.2
-
驱动程序版本:340.65
-
卡:GeForce 610M
更新:
下面是重现该问题的示例代码。有了评论行,我每次运行泄漏10 Mo。
#include <cuda.h>
#include <cuda_runtime.h>
int main() {
int *ret;
cudaHostAlloc(&ret, 10000000 * sizeof(*ret), cudaHostAllocPortable);
//cudaFreeHost(ret);
return 0;
}
更新2:
total used free shared buffers cached
Mem: 3830056 1487156 2342900 66336 142840 527088
-/+ buffers/cache: 817228 3012828
Swap: 7811068 0 7811068
1Erreur de segmentation
2Erreur de segmentation
3Erreur de segmentation
4Erreur de segmentation
5Erreur de segmentation
6Erreur de segmentation
7Erreur de segmentation
8Erreur de segmentation
9Erreur de segmentation
10Erreur de segmentation
11Erreur de segmentation
12Erreur de segmentation
13Erreur de segmentation
14Erreur de segmentation
15Erreur de segmentation
16Erreur de segmentation
17Erreur de segmentation
18Erreur de segmentation
19Erreur de segmentation
20Erreur de segmentation
total used free shared buffers cached
Mem: 3830056 1766580 2063476 64152 142860 531032
-/+ buffers/cache: 1092688 2737368
Swap: 7811068 0 7811068
我为您的repro case构建了一个稍微修改过的版本:
#include <cuda.h>
#include <cuda_runtime.h>
#include <signal.h>
int main() {
int *ret;
const size_t sz = 1 << 30;
cudaHostAlloc(&ret, sz * sizeof(*ret), cudaHostAllocPortable);
raise(SIGSEGV);
return 0;
}
在我的系统上,它应该分配8Gb的固定便携式内存,并引发一个segfault,这会产生异常退出和核心转储。我在一台16Gb机器上运行了这个程序,该机器带有352.39驱动程序和CUDA 6运行时,处于shell循环中,根据您的分析,这应该会在两三次运行内导致泄漏和缓存抖动:
$ free; for i in {1..20}; do echo -n $i; ./a.out; done; free
total used free shared buffers cached
Mem: 16308996 3509924 12799072 0 303588 2313332
-/+ buffers/cache: 893004 15415992
Swap: 8257532 0 8257532
1Segmentation fault (core dumped)
2Segmentation fault (core dumped)
3Segmentation fault (core dumped)
4Segmentation fault (core dumped)
5Segmentation fault (core dumped)
6Segmentation fault (core dumped)
7Segmentation fault (core dumped)
8Segmentation fault (core dumped)
9Segmentation fault (core dumped)
10Segmentation fault (core dumped)
11Segmentation fault (core dumped)
12Segmentation fault (core dumped)
13Segmentation fault (core dumped)
14Segmentation fault (core dumped)
15Segmentation fault (core dumped)
16Segmentation fault (core dumped)
17Segmentation fault (core dumped)
18Segmentation fault (core dumped)
19Segmentation fault (core dumped)
20Segmentation fault (core dumped)
total used free shared buffers cached
Mem: 16308996 3510740 12798256 0 303588 2313272
-/+ buffers/cache: 893880 15415116
Swap: 8257532 0 8257532
然而,您可以看到,在分配160Gb的固定内存并且从不调用内存版本API或允许代码遵循正常代码路径退出后,可用内存仅减少0.006%。未发生内存泄漏或可用资源发生净更改。
CUDA驱动程序和运行时将在退出时释放主机和GPU资源,无论是正常还是异常,无论是否显式调用无内存API。我不能告诉你你的代码或系统有什么问题,但CUDA运行时或驱动程序在应用程序退出时缺乏主机资源释放很可能不是根本原因。
我鼓励您修改我的代码以适应机器上物理内存的大小(使用一半的物理内存),并像我在循环中所做的那样运行它,在循环之前或之后直接报告内存。我非常怀疑你是否会看到与我在回复中发布的内容不同的内容。如果你这样做,我强烈建议你更新最新版本的驱动程序。
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 尽管遵循了规则,内存泄漏在哪里
- 为什么调用堆栈数组会导致内存泄漏
- 在简单示例中,Python3 + ctypes 回调会导致内存泄漏
- 使用模板类的自定义列表类型中的内存泄漏
- 为什么以下C++代码中存在内存泄漏?
- OpenCV 我应该使用智能指针来防止内存泄漏吗?
- 我是否生成线程并导致内存泄漏?
- 多线程程序中出现意外的内存泄漏
- 为什么此函数会导致内存泄漏?
- 在 C++ 库中使用cythonized python时内存泄漏
- 需要帮助查找内存泄漏
- 瓦尔格林德的内存泄漏使用新的
- 无法找出我的代码中的内存泄漏
- C++ 结构内部的unordered_map会导致内存泄漏问题吗?
- 可视化 使用 VS Code 查找C++应用程序中的内存泄漏
- Shared_ptr双链接列表内存泄漏
- C++ 在类中使用常量引用文本时 O2 内存泄漏