Alives 的回答已經提到了編譯器的預設選項很保守。我列一下 Linux 發行版的預設選項,可以對保守程度有一個直觀的認知:
如果是想確認能不能正常執行,一般情況下不需要辨識。絕大多數軟件二進制釋出都是用的非常保守的指令集。少部份軟件需要充分利用新指令集的優勢,通常會編譯多個版本的庫,主程式啟動時根據 cpuid 的結果來動態載入合適的庫,新 CPU 可以充分發揮優勢,舊 CPU 也能正常執行。至於必須要用新指令集才能執行的軟件,都會在發行註記裏面寫清楚的。
當然根據 cpuid 動態載入也有可能會因為測試覆蓋不全面出問題,尤其是遊戲,很難透過虛擬機器遮蔽指令集來測試。但這個也沒有什麽可靠的方法來辨識(否則開發者自己辨識了就不會出問題了)。比如某著名 MMORPG 最近才出過問題:
如果是想確認軟件能不能發揮新指令集的優勢,除了發行註記裏面明確提到的,其它軟件看看動態連結庫的檔名基本上就能確認了。根據 cpuid 動態載入的,都會有類似
libxxx-generic.so
libxxx-avx.so
libxxx-avx2.so
這樣的命名。
GCC/Clang
-march
和一大堆
-m
的選項(如
-msse3
-mavx
)來控制采用哪些指令集。(註意 GCC 的 x86 包括 x86-32、x86-64、x86-x32。)
最簡單的方法就是直接用
-march=native
,讓編譯器自己根據 cpuid 開關選項。如果想知道
-march=native
開了哪些選項,執行
gcc -c -Q -march=native --help=target
MSVC 的控制沒有這麽精細,但也有
/arch:SSE
/arch:SSE2
/arch:AVX
/arch:AVX2
/arch:AVX512
這幾個選項。