簡體   English   中英

在 64 位處理器上交換 4 個 16 位整數的最有效方法是什么?

[英]What's the most efficient way to swap 4 16-bit integers on a 64-bit processor?

我有四個分別命名為 a,b,c,d 的 uint16,現在我想像這樣交換它們:

void swap4(uint16_t &a, uint16_t &b, uint16_t &c, uint16_t &d) {
    uint16_t temp = a;
    a = b;
    b = c;
    c = d;
    d = temp;
}

我能做些什么來加快這個過程嗎?

在 C++ 這是

void swap4(uint16_t &a, uint16_t &b, uint16_t &c, uint16_t &d) {
    std::tie(a, b, c, d) = std::make_tuple(b, c, d, a);
}

如前所述,首先確保這確實是一個瓶頸:大多數編譯器應該為此生成有效的代碼(除非參數之間存在別名的可能性)。

如果碰巧這些 16 位值連續存儲在 memory 中(例如,這是一個四元素向量),那么 (a) 確保它們在右邊界上對齊,並且 (b) 您可以使用 CPU 的 shuffle操作說明。 這是您的編譯器可能會或可能不會自行識別的優化,在您進一步使用 go 之前; 檢查編譯器的匯編輸出; 帶有 -O2 的現代 GCC 實際上會自動識別這種簡化( https://godbolt.org/z/qo1jxnbds )。

如果你真的想手動滾動,GCC 為此提供了一個可移植的 __builtin_shuffle 宏; 對於您的用例,您可以編寫

typedef uint16_t quadword __attribute__ ((vector_size (8)));
quadword input = {a, b, c, d};
const quadword rotate_mask = {1, 2, 3, 0};
quadword output = __builtin_shuffle (input, rotate_mask);

(您可能不想完全寫出來,而是將您的數據重新轉換為這些四字類型的數組——請參閱上面的編譯器資源管理器鏈接以獲取示例。)

For x86 the underlying instruction generated by this macro is pshufb/pshufw, which (if you're not on GCC, or don't want to be portable) you could access with the _mm_shuffle_pi16 intrinsic ( https://www.intel.com /content/www/us/en/docs/intrinsics-guide/index.html#text=shuffle&techs=MMX,SSE&ig_expand=6426 )。 每個現代 RISC 架構都提供類似的東西。

好吧,應該將代碼原樣編譯為匯編指令的最佳序列,假設最低優化級別。 也就是說,如果允許別名,否則請參閱273k之前加載所有值而不是全部寫入。

但是它太短了,而且有太多的間接性,這並不是所有優化潛力的所在。

內聯和優化產生的更大的塊會產生更大的影響。 此外,它將允許編譯器查看是否發生了別名。

好消息是,如果您允許編譯器,它將完成這項工作,這要歸功於 lto、whole-program-optimization 等(因此取決於正確調用編譯器),或者定義在同一個 TU 中調用(可能需要將其作為內聯函數放入 header,或將其標記為靜態)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM