简体   繁体   English

C ++ OpenMP代码中的内存泄漏

[英]Memory Leak in C++ OpenMP code

I have written a c++ openmp code it is having a dynamically allocated memory private variable in parallel region, the region is in while loop. 我编写了一个c ++ openmp代码,它在并行区域中有一个动态分配的内存私有变量,该区域在while循环中。 Memory dynamically allocated is freed at the end of parallel region in each loop. 在每个循环中,在并行区域的末尾释放动态分配的内存。 I am monitoring memory through /proc/self/stat file on linux machine, after every allocation and deallocation. 我在每次分配和释放后通过linux机器上的/ proc / self / stat文件监视内存。 I am finding some less memory in resident set size. 我发现驻留集大小的内存较少。 Why is it so ? 为什么会这样? The code is something like - 代码是这样的 -

float *dynm;
while(condition)
{
    pragma omp parallel shared(list of variables) private(dynm)
    {
        read_values_from_/proc/self/stat_print_rss;
        dynm = new float[size]; 
        read_values_from_/proc/self/stat_print_rss;
        pragma omp for schedule(static, chunk) nowait
                for(counter)
        {
            do_operation;
        }
        delete []dynm;
        read_values_from_/proc/self/stat_print_rss;
    }
}

Measuring RSS is not a very accurate way to search for memory leaks because of the very complicated way it is being calculated. 测量RSS不是一种非常准确的搜索内存泄漏的方法,因为它的计算方式非常复杂。 There are special memory debuggers like valgrind or the one built into glibc that can tell you if memory is leaking. 有一些特殊的内存调试器,如valgrind或内置于glibc中的内存调试器,可以告诉你内存是否泄漏。 You also have to understand that glibc uses two completely different mechanisms to dynamically allocate memory. 您还必须了解glibc使用两种完全不同的机制来动态分配内存。

For large allocations it performs private anonymous memory maps using the mmap(2) system call. 对于大型分配,它使用mmap(2)系统调用执行私有匿名内存映射。 This method can only allocate blocks with sizes which are multiple of the system page size (4 KiB on most modern architectures), hence is not appropriate for small allocations. 此方法只能分配大小为系统页面大小的倍数的块(在大多数现代体系结构上为4 KiB),因此不适合小分配。 It is not even appropriate for larger allocations when too much memory would be wasted, eg if you'd like to allocate a block of 17 KiB then 20 KiB (5 times 4 KiB) have to be allocated and 15% of the memory would be wasted. 当浪费太多内存时,它甚至不适合更大的分配,例如,如果你想分配17 KiB的块,那么必须分配20 KiB(5倍4 KiB)并且15%的内存将被分配浪费了。

For smaller allocations the system provided heap is used. 对于较小的分配,使用系统提供的堆。 There is something called the system break , which is where the data segment of the process ends. 有一种称为系统中断的东西,它是进程数据段结束的地方。 It could be moved with the brk(2) system call up to allocate more memory and down to free it. 它可以通过brk(2)系统调用来移动以分配更多内存并向下移动以释放它。 Since there is only one heap area per process and the OS treat it as a single block, a special heap manager is built into glibc that can further subdivide this block into smaller allocations. 由于每个进程只有一个堆区域,并且OS将其视为单个块,因此glibc中内置了一个特殊的堆管理器,可以进一步将该块细分为更小的分配。

The C++ new operator calls malloc(3) from glibc to perform the memory allocation. C ++ new运算符从glibc调用malloc(3)来执行内存分配。 malloc(3) calls into one of the two memory allocation mechanisms described above depending on the size of the memory block to be allocated. malloc(3)根据要分配的存储块的大小调用上述两种存储器分配机制之一。 The C++ delete operator calls free(3) from glibc which is the deallocation counterpart of malloc(3) . C ++ delete运算符从glibc调用free(3)glibcmalloc(3)的释放对应物。 What happens after the memory block is deallocated very much depends on how it was allocated in the first place. 内存块被解除分配后发生的事情很大程度上取决于它首先如何分配。

Memory, that was allocated using the mmap(2) mechanism is deallocated by unmapping it with munmap(2) . 使用mmap(2)机制分配的内存通过使用munmap(2)取消munmap(2)来解除分配。 This removes the memory mapping from the virtual address space of the process and releases the physical memory pages that were used to back the allocation. 这将从进程的虚拟地址空间中删除内存映射,并释放用于支持分配的物理内存页。

Things are way more complicated for memory that was allocated in the heap and largerly depends on the algorithm that is used to manage it. 对于在堆中分配的内存而言,事情变得更加复杂,并且更大程度上取决于用于管理它的算法。 If the block being freed is not located at the end of the heap, but is rather located somewhere else, then the heap size cannot be decreased as there are other allocations on upper memory addresses. 如果被释放的块不是位于堆的末尾,而是位于其他位置,那么堆大小不能减少,因为在高端内存地址上有其他分配。 This is just one of the many forms under which the so-called heap fragmentation manifests itself. 这只是所谓的堆碎片表现形式的众多形式之一。 Another possible reason not to see a decrease in the used memory is that the heap manager might decide against moving back the position of the break in anticipation of possible future allocations and calling brk(2) is an expensive operation. 另一个不能看到已用内存减少的可能原因是堆管理器可能会决定在预期可能的未来分配时拒绝中断的位置,并且调用brk(2)是一项昂贵的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM