我已经编写了一些在Ubuntu 18.04的i9-9900K上运行的C ++反向传播代码。
我看到的问题是,随着新版g ++的出现,多线程性能越来越差。
使用较新的g ++版本,单线程基准测试会按预期改进:
g++ 4.8: 5437 cycles/s
g++ 5.5: 5929 cycles/s
g++ 6.5: 5932 cycles/s
g++ 7.4: 6117 cycles/s
g++ 8.3: 6921 cycles/s
多线程基准测试(8个内核上有14个pthread)在较新的版本中会大大降低:
g++ 4.8: 25456 cycles/s
g++ 5.5: 17212 cycles/s
g++ 6.5: 18616 cycles/s
g++ 7.4: 17054 cycles/s
g++ 8.3: 14797 cycles/s
我在CentOS 7.6和Clear Linux中也看到了类似的行为。在所有经过测试的操作系统中,最快的性能来自于在g ++ 4.8中使用14个线程。
这是我正在使用的编译标志: g ++ -c -std = c ++ 11 -march = native -Ofast
我使用错误的标志进行编译吗?我尝试过-O3,但降级效果相似,尽管极端程度较低(并且比-Ofast慢)
g++ 4.8 -O3: 17256 cycles/s
g++ 5.5 -O3: 15129 cycles/s
g++ 6.5 -O3: 15779 cycles/s
g++ 7.4 -O3: 15736 cycles/s
g++ 8.3 -O3: 13361 cycles/s
我觉得我遇到了这么多内核的内存带宽问题。是否有任何编译选项可以帮助解决这么多线程带来的内存压力?
答案 0 :(得分:1)
进一步的测试表明,该问题与-march = native优化标志有关。
g ++ 4.8将i9-9900k本地视为core-avx2,它会激活: MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,AVX,AES和PCLMUL
g ++ 4.9及更高版本将i9-9900k自然地视为可激活的Broadwell: MOVBE,MMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX和PREFETCHW
显然,这会导致过度优化。
完全删除-march标志可以解决此问题。禁用AVX还可以使用-mno-avx和-mno-avx2