Linux

即使有足夠多的可用記憶體,大記憶體分配也會導致核心交換

  • November 4, 2019

我的情況與 serverfault 上的這篇文章幾乎相同。總結一下:

我有一個非常簡單的 C++ 應用程序,它使用雜湊映射來計算和合併許多大文件。std::unordered_map::reserve()在填充記憶體並開始迭代之前,我使用 with 保留記憶體。在使用大約 60Gb 的記憶體(系統有 378Gb)時,程序開始交換並且散列插入的速率降級為無。

該程序的準系統要點在這裡

一些注意事項:

  • swapoff -a徹底解決問題
  • 交換性設置為 1
  • 更好的 hashmap 實現(如martinus/robin-hood-hashing)不能解決問題。
  • 一切都編譯為 64 位,gcc 的唯一選項是-std=c++11 -fopenmp -O3
  • 程序在這一步使用 1 個執行緒
  • 伺服器上的高 I/O 負載似乎使問題惡化

更多資訊

file執行檔的輸出:

../script/jelly_union: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=65917c99ec9480c1dfb859f10920fce15a8fefc1, not stripped

uname -a:

Linux picea 4.15.0-66-generic #75-Ubuntu SMP Tue Oct 1 05:24:09 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

CPU 資訊(最後一個核心):

processor       : 63
vendor_id       : AuthenticAMD
cpu family      : 21
model           : 1
model name      : AMD Opteron(tm) Processor 6282 SE
stepping        : 2
microcode       : 0x600063e
cpu MHz         : 1156.138
cache size      : 2048 KB
physical id     : 3
siblings        : 16
core id         : 7
cpu cores       : 8
apicid          : 143
initial apicid  : 111
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid amd_dcm aperfmperf pni pclmulqdq monitor ssse3 cx16 sse4_1 sse4_2 popcnt aes xsave avx lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs xop skinit wdt lwp fma4 nodeid_msr topoext perfctr_core perfctr_nb cpb hw_pstate ssbd ibpb vmmcall arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold
bugs            : fxsave_leak sysret_ss_attrs null_seg spectre_v1 spectre_v2 spec_store_bypass
bogomips        : 5187.19
TLB size        : 1536 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm 100mhzsteps hwpstate cpb

我不確定現代 C++ 的做法是什麼,但您可能想研究mlock(2)禁用交換記憶體頁面。

我也有點好奇如果你立即重新執行它會發生什麼。我希望您使用的保留呼叫實際上不會觸及所有記憶體頁面(因此不會強制它們被實際分配) - 如果是這種情況,您在一段時間後開始看到的是系統正在努力實際提供您首先要求的記憶體,而不是交換它(您應該能夠通過查看駐留大小來反駁這一點)。

引用自:https://unix.stackexchange.com/questions/549781