Reputation: 31
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. 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. 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;
}
}
Upvotes: 3
Views: 895
Reputation: 74395
Measuring RSS is not a very accurate way to search for memory leaks because of the very complicated way it is being calculated. There are special memory debuggers like valgrind
or the one built into glibc
that can tell you if memory is leaking. You also have to understand that glibc
uses two completely different mechanisms to dynamically allocate memory.
For large allocations it performs private anonymous memory maps using the mmap(2)
system call. 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. It is not even appropriate for larger allocations when too much memory would be wasted, e.g. 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.
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. 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.
The C++ new
operator calls malloc(3)
from glibc
to perform the memory allocation. malloc(3)
calls into one of the two memory allocation mechanisms described above depending on the size of the memory block to be allocated. The C++ delete
operator calls free(3)
from glibc
which is the deallocation counterpart of malloc(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)
. 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.
Upvotes: 5