首頁 >後端開發 >C++ >重新解釋硬體 SIMD 向量指標和對應類型之間的轉換是否是 C 中未定義的行為?

重新解釋硬體 SIMD 向量指標和對應類型之間的轉換是否是 C 中未定義的行為?

DDD
DDD原創
2024-12-27 14:38:09248瀏覽

Is Reinterpreting Casts Between Hardware SIMD Vector Pointers and Corresponding Types Undefined Behavior in C  ?

硬體 SIMD 向量指標和對應類型之間的重新解釋轉換是否是未定義的行為?

在C 中,是否允許重新解釋_轉換浮點數 到__m256 並透過不同的指標存取浮點物件type?

以下程式碼範例說明了這一點:

#include <immintrin.h>

constexpr size_t _m256_float_step_sz = sizeof(__m256) / sizeof(float);
alignas(__m256) float stack_store[100 * _m256_float_step_sz ]{};
__m256& hwvec1 = *reinterpret_cast<__m256*&>(&stack_store[0 * _m256_float_step_sz]);

using arr_t = float[_m256_float_step_sz];
arr_t& arr1 = *reinterpret_cast<float(*)[_m256_float_step_sz]&>(&hwvec1);

hwvec1 和arr1是否有未定義的行為?是否違反了嚴格的別名規則([basic.lval]/11)?或者,是否只有一個定義的內在方式:

__m256 hwvec2 = _mm256_load_ps(&stack_store[0 * _m256_float_step_sz]);
_mm256_store_ps(&stack_store[1 * _m256_float_step_sz], hwvec2);

答案:

ISO C 沒有定義__m256,所以我們需要看看定義了什麼在支持他們的實現上的行為。 Intel 的內在函數將像 __m256 這樣的向量指標定義為允許為其他任何東西起別名,就像 ISO C 將 char 定義為允許起別名一樣。 (但反之亦然:在實踐中將int* 指向__m256i 並取消引用它是UB 和中斷。)

所以,是的,取消引用__m256 是安全的,而不是使用_mm256_load_ps( ) 內在的對齊負載。但特別是對於 float/double,使用內在函數通常更容易,因為它們也負責從 float 進行轉換。對於整數,AVX512 載入/儲存內在函數被定義為採用void,但AVX2 及更早版本需要像(__m256i)&arr[i] 這樣的強制轉換,這是相當笨重的API 設計,並且使用它的程式碼會變得混亂。

也使用 void 增加了一些非 AVX512 內在函數,例如movd/movq 載入/儲存對齊和別名安全內在函數,例如 _mm_loadu_si32(void)。以前我認為英特爾假設你會使用_mm_cvtsi32_si128 ,它需要自己安全地加載一個int ,這意味著使用memcpy 來避免UB (至少在經典ICC 和MSVC 之外的編譯器上,如果它們允許未對齊的int*並且不強制執行嚴格的

這可能是在英特爾開始考慮遷移到LLVM的時候ICX/ICPX / OneAPI,並意識到處理強制嚴格別名的編譯器上的狹窄負載是多麼混亂。

以上是重新解釋硬體 SIMD 向量指標和對應類型之間的轉換是否是 C 中未定義的行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn