2012-09-20 91 views
3

我寫了一個C++ openmp代碼,它在並行區域中有一個動態分配的內存私有變量,該區域在while循環中。內存動態分配在每個循環的並行區域結束時釋放。我正在通過linux機器上的/ proc/self/stat文件監視內存,在每次分配和釋放後。我在居民組大小中發現一些內存較少。爲什麼這樣?該代碼是一樣的東西 -C++ OpenMP代碼中的內存泄漏

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; 
    } 
} 
+2

'do_operation'裏有什麼? – Hbcdev

+0

dynm數組已被線程用於計算 – Abhi

回答

5

測量RSS是不是搜索,因爲正在計算它的方式很複雜的內存泄漏一個非常準確的方法。有特殊的內存調試器,如valgrind或內置於glibc的內存調試器可以告訴你內存是否泄漏。你還必須明白,glibc使用兩種完全不同的機制來動態分配內存。

對於大型分配,它使用mmap(2)系統調用執行專用匿名內存映射。此方法只能分配大小爲系統頁大小倍數的塊(在大多數現代體系結構中爲4 KiB),因此不適用於小分配。當浪費太多內存時,甚至不適用於較大的分配。如果您想要分配一個17 KiB的塊,那麼必須分配20 KiB(5倍4 KiB),並且將浪費15%的內存。

對於較小的分配,使用系統提供的堆。有一種叫的系統中斷,這是過程的數據段結束的地方。可以調用brk(2)系統調用分配更多內存並釋放內存。由於每個進程只有一個堆區,操作系統將其視爲一個塊,因此glibc中內置了一個特殊的堆管理器,可以將該塊進一步細分爲更小的分配。

C++ new運算符調用malloc(3)glibc執行內存分配。 malloc(3)取決於要分配的存儲器塊的大小調用上述兩個存儲器分配機制中的一個。 C++ delete運營商從glibc調用free(3),這是malloc(3)的重新分配對應部分。內存塊解除分配後會發生什麼很大程度取決於它是如何分配的。

使用mmap(2)機制分配的內存通過將其與munmap(2)取消映射而取消分配。這會從進程的虛擬地址空間中刪除內存映射,並釋放用於備份分配的物理內存頁面。

對於在堆中分配的內存而言,事情是比較複雜的,並且更大程度上取決於用於管理它的算法。如果被釋放的塊不在堆的末尾,而是位於其他位置,那麼堆大小不能減少,因爲在高位內存地址上有其他分配。這只是所謂的堆碎片表現出來的許多形式之一。另一個可能的原因是不會看到已使用內存的減少,因爲堆管理器可能會決定不考慮未來可能的分配情況而回退中斷位置,並且調用brk(2)是一項昂貴的操作。

+0

感謝您的解釋......這是非常有用的 – Abhi