如何将std::simd作为SIMD固有函数的输入?兼容GCC与Clang
在GCC和Clang中为std::experimental::simd调用SIMD固有函数的方法
std::datapar::simd和std::experimental::simd当前提供的功能确实有限,像元素混洗、复杂加载(比如gather操作)这类需求没法直接通过标准接口实现。针对你给出的示例,想要用_mm256_i32gather_epi64这类固有函数操作simd对象,在GCC和Clang里可以通过类型重转换实现——这两个编译器的experimental simd类型和底层SIMD寄存器类型(如__m256i)内存布局完全兼容。
可行的实现方案
核心思路是把std::experimental::fixed_size_simd对象通过reinterpret_cast转换成对应的固有SIMD类型,调用固有函数后再转换回来。以下是修改后的可编译代码:
#include <array> #include <experimental/simd> #include <immintrin.h> int main() { std::array<unsigned long long int, 16> a = { 0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500 }; std::array<int, 4> vindex_data = {3, 7, 11, 15}; unsigned long long int* base_addr = a.data(); std::experimental::fixed_size_simd<int, 4> vindex( vindex_data.data(), std::experimental::element_aligned ); int scale = sizeof(unsigned long long int); std::experimental::fixed_size_simd<unsigned long long int, 4> v; // 转换为固有类型并调用gather函数 auto vindex_raw = reinterpret_cast<__m128i>(vindex); __m256i gather_result = _mm256_i32gather_epi64(base_addr, vindex_raw, scale); // 将结果转换回simd类型 v = reinterpret_cast<std::experimental::fixed_size_simd<unsigned long long int, 4>&>(gather_result); return 0; }
关键注意事项
- 类型匹配:必须确保simd的大小和固有SIMD类型的位宽一致。比如
fixed_size_simd<int,4>是128位(4×32位),对应__m128i;fixed_size_simd<unsigned long long,4>是256位(4×64位),对应__m256i。 - 编译选项:需要开启对应的SIMD指令集支持,比如编译AVX2代码要加
-mavx2参数。 - 非标准依赖:这个方法依赖GCC和Clang对
std::experimental::simd的具体实现,移植到其他编译器(如MSVC)可能需要调整。
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

