是否可以在std :: bitset的基础数据上使用SSE指令?我正在使用的位集大于无符号长整数,因此to_ulong()方法是不够的.例如,我可以使用这样的指令:
__m128i* ptr= (__m128i*)(&my_bitset[0]);
Run Code Online (Sandbox Code Playgroud)
然后按正常情况执行SSE操作?
对于使用带有SSE的std :: bitset的人来说,我试图搜索互联网,但它似乎并不是一个常见的用例.
是否可以对 std::bitset 的基础数据使用 SSE 指令?
在
__m128i* ptr= (__m128i*)(&my_bitset[0]);
Run Code Online (Sandbox Code Playgroud)
my_bitset[0]返回未指定布局的临时代理对象,其中包含指向容器/存储的指针和位索引(例如GNU C++std::bitset::reference实现)。将指针转换为指向此临时代理对象是__m128i*没有意义的。但 C++ 根本不允许获取临时对象的地址,因此&my_bitset[0]会导致编译器错误。
std::bitset如果/当编译器选择对其进行向量化时,可以自动为其成员函数使用 SIMD 指令。
在此示例中,gcc 决定使用 AVX-256 指令,而 clang 决定不使用。这两种选择都不理想:
gcc 生成具有 256 位ymm寄存器的 AVX 指令,这会降低较旧的 Intel CPU 上的 CPU 频率(或使超频的 CPU 崩溃并强制 AVX 偏移量为 0)。ymm但向量大小太小,不足以证明在使用零星寄存器指令时付出增加 CPU 功耗和可能降低频率的代价是合理的。
clang 生成 64 位通用寄存器指令,与具有 128 位xmm寄存器的 SSE 相比,它需要更多的指令字节和更多的加载/存储。CPU 每个周期只能执行固定数量的加载/存储指令(而不是字节),因此最大化每条指令加载和存储的数据量是有意义的。
本例中的理想选择可能是使用具有 128 位xmm寄存器的 SSE 指令 - 最大限度地减少加载/存储指令的数量,而无需降低 CPU 的时钟频率。这表明编译器矢量化通常并不理想。
std::bitset不幸的是,它不提供对其存储的直接访问,并且通过 C 风格转换对其进行的任何访问都可能会导致未定义的行为,而不会由于布局、对齐或严格别名冲突而出现警告或错误。
std::bitset由于可移植性限制,不太可能使用任何非标准/SIMD 类型进行存储,因此将其存储转换为更广泛的 SIMD 类型几乎可以保证对齐和严格的别名冲突。有一些不可移植的方法可以解决这个问题,但这对于未来的变化来说很脆弱,这就是为什么我不建议这样做。
您可能希望寻找其他以 SIMD 设计的容器,例如Vc:可移植、零开销的 C++ 类型,用于显式数据并行编程。它允许选择在每个容器类的基础上使用的 SIMD 指令类型,例如,xmm即使有 256 位寄存器ymm可用,您可能只喜欢针对该特定容器类型使用 128 位寄存器指令。
gcc 和 clang 都支持通过内置函数对使用 声明的类型使用向量指令__attribute__((vector_size (N))),这是另一种方式:
目前,GCC 允许在这些类型上使用以下运算符:+、-、*、/、一元减号、^、|、&、~、%。
但这些不允许在每个容器类的基础上选择底层 SIMD 类型/指令,只能为每个具有编译器选项(如-mno-avx.
bitset没有访问其内部数据的标准方法。
itsy_bitsy库提供了与其他数据类似的接口bitset。bit_view是您所需要的,它包装具有操作位能力的数据,但没有insert/erase操作。
不确定是否可以bitsy::bit_view直接使用__m128i类型,但它支持 like bitsy::bit_view<std::span<char>>,因此您可以拥有__m128i变量并将其重新解释为chars 的范围,
| 归档时间: |
|
| 查看次数: |
525 次 |
| 最近记录: |