SIMD 函式庫
出自 cppreference.com
< cpp | experimental
SIMD 函式庫提供了可攜式型別,用於明確說明資料平行處理,並建構資料以實現更高效的 SIMD 存取。
simd<T> 型別的物件行為類似於 T 型別的物件。然而,當 T 儲存並操作單一值時,simd<T> 儲存並操作多個值(稱為寬度,但為與標準函式庫其餘部分保持一致,識別為 size;參閱 simd_size)。
simd<T> 上的每個運算子和操作都採取元素級(除了清楚標示為水平的操作外)。此簡單規則表達了資料平行處理,並將由編譯器用於產生 SIMD 指令及/或獨立的執行流。
simd<T> 和 native_simd<T> 型別的寬度由實作在編譯時期決定。相比之下,fixed_size_simd<T, N> 型別的寬度由開發者固定為特定大小。
建議使用 native_simd 和 rebind_simd 來組合使用不同 SIMD 型別以獲得高效率的模式。
#include <experimental/simd> namespace stdx = std::experimental; using floatv = stdx::native_simd<float>; using doublev = stdx::rebind_simd_t<double, floatv>; using intv = stdx::rebind_simd_t<int, floatv>;
這確保了一組型別都具有相同的寬度,因此可以互相轉換。寬度不符的轉換未定義,因為它會導致數值丟失或必須虛構數值。對於調整大小的操作,SIMD 函式庫提供了 split 和 concat 函式。
| 定義於標頭檔
<experimental/simd> |
目錄 |
[編輯] 主要類別
| (平行運算 TS v2) |
資料並行向量型別 (類別模板) |
| (平行運算 TS v2) |
元素型別為 bool 的資料並行型別 (類別模板) |
[編輯] ABI 標籤
| 定義於命名空間
std::experimental::simd_abi | |
| (平行運算 TS v2) |
用於儲存單一元素的標籤型別 (typedef) |
| (平行運算 TS v2) |
用於儲存指定數量元素的標籤型別 (別名模板) |
| (平行運算 TS v2) |
確保 ABI 相容性的標籤型別 (別名模板) |
| (平行運算 TS v2) |
最高效的標籤型別 (別名模板) |
| (平行運算 TS v2) |
保證被 fixed 支援的最大元素數量 (常數) |
| (平行運算 TS v2) |
為給定的元素型別和元素數量取得 ABI 型別 (類別模板) |
[編輯] 對齊標籤
| (平行運算 TS v2) |
指示載入/儲存位址對齊至元素對齊的旗標 (類別) |
| (平行運算 TS v2) |
指示載入/儲存位址對齊至向量對齊的旗標 (類別) |
| (平行運算 TS v2) |
指示載入/儲存位址對齊至指定對齊方式的旗標 (類別模板) |
[編輯] Where 表達式
| (平行運算 TS v2) |
具有非可變操作的選定元素 (類別模板) |
| (平行運算 TS v2) |
具有可變操作的選定元素 (類別模板) |
| (平行運算 TS v2) |
產生 const_where_expression 和 where_expression (函式模板) |
[編輯] 轉型
| (平行運算 TS v2) |
元素級 static_cast (函式模板) |
| (平行運算 TS v2) |
元素級 ABI 轉型 (函式模板) |
| (平行運算 TS v2) |
將單一 simd 物件分割為多個物件 (函式模板) |
| (平行運算 TS v2) |
將多個 simd 物件串聯為單一物件 (函式模板) |
[編輯] 演算法
| (平行運算 TS v2) |
元素級 min 操作 (函式模板) |
| (平行運算 TS v2) |
元素級 max 操作 (函式模板) |
| (平行運算 TS v2) |
元素級 minmax 操作 (函式模板) |
| (平行運算 TS v2) |
元素級 clamp 操作 (函式模板) |
[編輯] 歸約
| (平行運算 TS v2) |
將向量歸約為單一元素 (函式模板) |
[編輯] 遮罩歸約
| (平行運算 TS v2) |
simd_mask 對 bool 的歸約 (函式模板) |
| (平行運算 TS v2) |
simd_mask 對 true 值數量的歸約 (函式模板) |
| (平行運算 TS v2) |
simd_mask 對第一個或最後一個 true 值的索引歸約 (函式模板) |
[編輯] 特徵 (Traits)
| (平行運算 TS v2) |
檢查型別是否為 simd 或 simd_mask 型別 (類別模板) |
| (平行運算 TS v2) |
檢查型別是否為 ABI 標籤型別 (類別模板) |
| (平行運算 TS v2) |
檢查型別是否為 simd 旗標型別 (類別模板) |
| (平行運算 TS v2) |
取得給定元素型別和 ABI 標籤的元素數量 (類別模板) |
| (平行運算 TS v2) |
取得適用於 vector_aligned 的適當對齊方式 (類別模板) |
| (平行運算 TS v2) |
更改 simd 或 simd_mask 的元素型別或元素數量 (類別模板) |
[編輯] 數學函式
<cmath> 中的所有函式(特殊數學函式除外)皆已為 simd 多載。
[編輯] 範例
執行此程式碼
#include <experimental/simd> #include <iostream> #include <string_view> namespace stdx = std::experimental; void println(std::string_view name, auto const& a) { std::cout << name << ": "; for (std::size_t i{}; i != std::size(a); ++i) std::cout << a[i] << ' '; std::cout << '\n'; } template<class A> stdx::simd<int, A> my_abs(stdx::simd<int, A> x) { where(x < 0, x) = -x; return x; } int main() { const stdx::native_simd<int> a = 1; println("a", a); const stdx::native_simd<int> b([](int i) { return i - 2; }); println("b", b); const auto c = a + b; println("c", c); const auto d = my_abs(c); println("d", d); const auto e = d * d; println("e", e); const auto inner_product = stdx::reduce(e); std::cout << "inner product: " << inner_product << '\n'; const stdx::fixed_size_simd<long double, 16> x([](int i) { return i; }); println("x", x); println("cos²(x) + sin²(x)", stdx::pow(stdx::cos(x), 2) + stdx::pow(stdx::sin(x), 2)); }
輸出
a: 1 1 1 1 b: -2 -1 0 1 c: -1 0 1 2 d: 1 0 1 2 e: 1 0 1 4 inner product: 6 x: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cos²(x) + sin²(x): 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[編輯] 參閱
| 數值陣列、陣列遮罩與陣列切片 (類別樣板) |
[編輯] 外部連結
| 1. | ISO/IEC TS 19570:2018 第 9 節「資料平行型別」的實作 — github.com |
| 2. | TS 實作對 GCC/libstdc++ 的支援範圍 (std::experimental::simd 隨 GCC-11 一起發佈) — gcc.gnu.org |