我使用 GCC 11.1 構建了一個小程式(~1000 LOC),并在啟用和不啟用的情況下運行了多次迭代,-march=native但總體而言,程式執行時間(以毫秒為單位)沒有差異。但為什么?因為它是單執行緒的?還是我的石器時代硬體(第一代 i5,沒有 AVX 的Westmere微架構)不夠強大?
我的Makefile中的幾行:
CXX = g
CXXFLAGS = -c -std=c 20 -Wall -Wextra -Wpedantic -Wconversion -Wshadow -O3 -march=native -flto
LDFLAGS = -O3 -flto
這里(編譯器資源管理器)是程式中的一個免費功能,GCC 不會為其生成 SSE 指令:
[[ nodiscard ]] size_t
tokenize_fast( const std::string_view inputStr, const std::span< std::string_view > foundTokens_OUT,
const size_t expectedTokenCount ) noexcept
{
size_t foundTokensCount { };
if ( inputStr.empty( ) ) [[ unlikely ]]
{
return foundTokensCount = 0;
}
static constexpr std::string_view delimiter { " \t" };
size_t start { inputStr.find_first_not_of( delimiter ) };
size_t end { };
for ( size_t idx { }; start != std::string_view::npos && foundTokensCount < expectedTokenCount; idx )
{
end = inputStr.find_first_of( delimiter, start );
foundTokens_OUT[ idx ] = inputStr.substr( start, end - start );
foundTokensCount;
start = inputStr.find_first_not_of( delimiter, end );
}
if ( start != std::string_view::npos )
{
return std::numeric_limits<size_t>::max( );
}
return foundTokensCount;
}
我想知道為什么?也許是因為無法對此類代碼進行矢量化?
另外,我要提到的另一件事是最終可執行檔案的大小根本沒有改變,我什至嘗試-march=westmere查看-march=alderlake大小是否有任何差異,但 GCC 生成的大小相同。
uj5u.com熱心網友回復:
我認為您也應該將其指定-march=native為 LDFLAGS 的一部分,因此-flto針對同一臺機器也是如此。
但是您的代碼生成似乎尊重您指定的拱門,因為您說-march=alderlake制作與 SIGILL 一起崩潰的代碼,可能是在向量指令的 AVX 編碼上。
很可能會-mtune=generic做出與 相同的調整決定-march=native,并且除了 SSE2 之外沒有什么能從任何東西中受益。您的 CPU 支持 SSE4.2 和 popcnt,但 x86-64 的基線已經是 SSE2,相同的向量寬度只是缺少一些指令,特別是對于 dword 和 qword 元素大小(如壓縮的 min/max)。
GCC/clang 不能自動矢量化搜索回圈(只有在第一次迭代之前在運行時知道行程計數的回圈),所以inputStr.find_first_of要么編譯為一次一個位元組的搜索,要么呼叫memchr只受益無論如何來自 SSE2,但可以基于 CPU 功能動態調度,因為它位于共享庫中。
(Glibc 使用“決議器”函式多載動態鏈接程序,該函式決定memchr在當前機器上哪個實作最好,SSE2 或 AVX2。這兩個版本都是手寫 asm,例如SSE2 版本的源代碼。一些函式如strstr具有 CPU 可以利用的 SSE4.2 版本,但此選擇不依賴于-march編譯時設定,純粹是運行時動態聯結器 glibc。)
如果您想查看程式大部分時間都花在哪里,請使用perf record ./a.out / perf report -Mintel(默認是 AT&T 語法反匯編;我更喜歡 Intel)。
如果它在庫函式中,則不同的調整選項和可用的新指令可能對您的主代碼沒有幫助。如果它在您的程式中,而不是庫中,那么顯然 x86-64 的基線指令集和“通用”調整選項很好,或者 GCC 不知道如何從 SSSE3 / SSE4.x 中獲得任何用途你的代碼。
我沒有看太多你的代碼在做什么來看看手動矢量化可能是什么。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/459793.html
