我的情况几乎与这发布在服务器故障上。总结一下:
我有一个非常简单的 C++ 应用程序,它使用哈希映射来计算和合并大量大文件。我std::unordered_map::reserve()
在填充内存并开始迭代之前用 with 保留内存。当使用大约 60Gb 的内存(系统有 378Gb)时,进程开始交换,并且散列插入的速率降为零。
该程序的基本要点是这里。
一些注意事项:
swapoff -a
彻底解决问题- 交换性设置为 1
- 更好的哈希图实现(例如martinus/罗宾汉哈希)不解决问题。
- 一切都编译为 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
答案1
我不确定现代 C++ 的做法是什么,但您可能想研究一下mlock(2)
禁用内存页面交换。
我也有点好奇如果立即重新运行会发生什么。我希望您使用的保留调用实际上不会触及所有内存页面(因此不会强制它们实际分配) - 如果是这种情况,您在一段时间后开始看到的将是系统努力实际提供您首先要求的内存,而不是交换它(您应该能够通过查看驻留大小来反驳这一点)。