[英]Why will the same compile options of gcc behave differently on different computer architecture?
我使用以下兩個makefile來編譯我的程序來做高斯模糊。
g++ -Ofast -ffast-math -march=native -flto -fwhole-program -std=c++11 -fopenmp -o interpolateFloatImg interpolateFloatImg.cpp
g++ -O3 -std=c++11 -fopenmp -o interpolateFloatImg interpolateFloatImg.cpp
我的兩個測試環境是:
但是,第一個輸出在E5上的速度為2倍,在i7上的速度為0.5倍。 第二個輸出在i7上表現得更快,但在E5上表現得更慢。
任何人都可以給出一些解釋嗎?
這是源代碼: https : //github.com/makeapp007/interpolateFloatImg
我會盡快給出更多細節。
i7上的程序將在8個線程上運行。 我不知道這個程序會在E5上生成多少線程。
====更新====
我是這個項目的原作者的隊友,結果如下。
Arch-Lenovo-Y50 ~/project/ca/3/12 (git)-[master] % perf stat -d ./interpolateFloatImg lobby.bin out.bin 255 20
Kernel kernelSize : 255
Standard deviation : 20
Kernel maximum: 0.000397887
Kernel minimum: 1.22439e-21
Reading width 20265 height 8533 = 172921245
Micro seconds: 211199093
Performance counter stats for './interpolateFloatImg lobby.bin out.bin 255 20':
1423026.281358 task-clock:u (msec) # 6.516 CPUs utilized
0 context-switches:u # 0.000 K/sec
0 cpu-migrations:u # 0.000 K/sec
2,604 page-faults:u # 0.002 K/sec
4,167,572,543,807 cycles:u # 2.929 GHz (46.79%)
6,713,517,640,459 instructions:u # 1.61 insn per cycle (59.29%)
725,873,982,404 branches:u # 510.092 M/sec (57.28%)
23,468,237,735 branch-misses:u # 3.23% of all branches (56.99%)
544,480,682,764 L1-dcache-loads:u # 382.622 M/sec (37.00%)
545,000,783,842 L1-dcache-load-misses:u # 100.10% of all L1-dcache hits (31.44%)
38,696,703,292 LLC-loads:u # 27.193 M/sec (26.68%)
1,204,703,652 LLC-load-misses:u # 3.11% of all LL-cache hits (35.70%)
218.384387536 seconds time elapsed
這些是工作站的結果:
workstation:~/mossCAP3/repos/liuyh1_liujzh/12$ perf stat -d ./interpolateFloatImg ../../../lobby.bin out.bin 255 20
Kernel kernelSize : 255
Standard deviation : 20
Kernel maximum: 0.000397887
Kernel minimum: 1.22439e-21
Reading width 20265 height 8533 = 172921245
Micro seconds: 133661220
Performance counter stats for './interpolateFloatImg ../../../lobby.bin out.bin 255 20':
2035379.528531 task-clock (msec) # 14.485 CPUs utilized
7,370 context-switches # 0.004 K/sec
273 cpu-migrations # 0.000 K/sec
3,123 page-faults # 0.002 K/sec
5,272,393,071,699 cycles # 2.590 GHz [49.99%]
0 stalled-cycles-frontend # 0.00% frontend cycles idle
0 stalled-cycles-backend # 0.00% backend cycles idle
7,425,570,600,025 instructions # 1.41 insns per cycle [62.50%]
370,199,835,630 branches # 181.882 M/sec [62.50%]
47,444,417,555 branch-misses # 12.82% of all branches [62.50%]
591,137,049,749 L1-dcache-loads # 290.431 M/sec [62.51%]
545,926,505,523 L1-dcache-load-misses # 92.35% of all L1-dcache hits [62.51%]
38,725,975,976 LLC-loads # 19.026 M/sec [50.00%]
1,093,840,555 LLC-load-misses # 2.82% of all LL-cache hits [49.99%]
140.520016141 seconds time elapsed
====更新==== E5的規格:
workstation:~$ cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
20 Intel(R) Xeon(R) CPU E5-2650 v3 @ 2.30GHz
workstation:~$ dmesg | grep cache
[ 0.041489] Dentry cache hash table entries: 4194304 (order: 13, 33554432 bytes)
[ 0.047512] Inode-cache hash table entries: 2097152 (order: 12, 16777216 bytes)
[ 0.050088] Mount-cache hash table entries: 65536 (order: 7, 524288 bytes)
[ 0.050121] Mountpoint-cache hash table entries: 65536 (order: 7, 524288 bytes)
[ 0.558666] PCI: pci_cache_line_size set to 64 bytes
[ 0.918203] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[ 0.948808] xhci_hcd 0000:00:14.0: cache line size of 32 is not supported
[ 1.076303] ehci-pci 0000:00:1a.0: cache line size of 32 is not supported
[ 1.089022] ehci-pci 0000:00:1d.0: cache line size of 32 is not supported
[ 1.549796] sd 4:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 1.552711] sd 5:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 1.552955] sd 6:0:0:0: [sdc] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
根據您指定的編譯器標志,第一個Makefile正在使用-march=native
標志,這部分解釋了為什么您在使用或不使用標志的兩個CPU上觀察不同的性能差距。
該標志允許GCC使用特定於給定CPU架構的指令,並且不一定在不同的架構上可用。 它還意味着-mtune=native
,它調整機器特定CPU 的編譯代碼 ,並支持在該CPU上運行得更快的指令序列。 請注意,如果在具有不同CPU的系統上運行,或者速度明顯較慢,則使用-march=native
編譯的代碼可能根本不起作用 。
因此,即使選項看起來相同,它們也會在幕后采取不同的行動,具體取決於您用於編譯的機器。 您可以在GCC文檔中找到有關此標志的更多信息。
要查看為每個CPU 專門啟用的選項 ,可以在每台計算機上運行以下命令:
gcc -march=native -Q --help=target
此外, 不同版本的GCC也會影響不同的編譯器標志如何優化您的代碼,尤其是-march=native
標志,它在舊版本的GCC上沒有啟用那么多的調整(較新的架構不一定完全當時支持)。 這可以進一步解釋您所觀察到的差距。
您的程序具有非常高的緩存未命中率。 它對程序有好處還是對它不好?
545,000,783,842次L1-dcache-load-miss:u#100.10%的所有L1-dcache命中
545,926,505,523 L1-dcache-load-miss#92.35%的所有L1-dcache命中
i7和E5中的緩存大小可能不同,因此它是差異的一個來源。 其他是 - 不同的匯編程序代碼,不同的gcc版本,不同的gcc選項。
您應該嘗試查看代碼,查找熱點,分析命令處理的像素數以及處理順序對cpu和內存的處理方式。 重寫熱點(花費大部分時間的代碼部分)是解決任務的關鍵http://shtech.org/course/ca/projects/3/ 。
您可以在record
/ report
/ annotate
模式下使用perf
profiler來查找熱點(如果您將使用-g
選項重新編譯項目將更容易):
# Profile program using cpu cycle performance counter; write profile to perf.data file
perf record ./test test_arg1 test_arg2
# Read perf.data file and report functions where time was spent
# (Do not change ./test file, or recompile it after record and before report)
perf report
# Find the hotspot in the top functions by annotation
# you may use Arrows and Enter to do "annotate" action from report; or:
perf annonate -s top_function_name
perf annonate -s top_function_name > annotate_func1.txt
我能夠在我的移動i5-4 *(intel haswell)上增加7個小bin文件和277個10個參數的速度,其中2個核心(4個虛擬核心啟用了HT)和AVX2 + FMA。
需要重寫一些循環/循環嵌套。 您應該了解CPU緩存的工作原理以及它更容易實現:經常錯過或不經常錯過。 此外,gcc可能是愚蠢的,可能並不總是檢測到讀取數據的模式; 可能需要這種檢測來並行處理幾個像素。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.