web-dev-qa-db-ja.com

十分なメモリが解放されていても、メモリの割り当てが大きいとカーネルがスワップします

私の状況は、実質的に this serverfaultへの投稿と同じです。要約する:

ハッシュマップを使用して多数の大きなファイルをカウントしてマージする、非常にシンプルなC++アプリがあります。 std::unordered_map::reserve()でメモリを予約してから、それを埋めて反復を開始します。約60Gbのメモリが使用されると(システムには378Gbがあります)、プロセスはスワッピングを開始し、ハッシュ挿入の速度はゼロに低下します。

プログラムの要点は ここ です。

いくつかの注意:

  • swapoff -aは問題を完全に修正します
  • swappinessは1に設定されます
  • より良いハッシュマップの実装( 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)を調べて、メモリページのスワッピングを無効にすることをお勧めします。

また、すぐに再実行するとどうなるかについても少し興味があります。使用する予約呼び出しが実際にすべてのメモリページに影響を与えるわけではない(したがって、実際に割り当てられるように強制しない)と思います-その場合、しばらくするとシステムが実際に提供するのに苦労します。スワップではなく、最初に要求したメモリ(常駐サイズを確認することでこれを反証できるはずです)。

1
Pontus