为什么不应该直接访问__m128i字段

Why should you not access the __m128i fields directly?

本文关键字:m128i 字段 访问 不应该 为什么      更新时间:2023-10-16

我在MSDN上读到这个,它说

不应直接访问__m128i字段。但是,可以在调试器中看到这些类型。类型为 __m128i 的变量映射到 XMM[0-7] 寄存器。

但是,它没有解释原因。这是为什么呢?例如,是以下"坏":

void func(unsigned short x, unsigned short y)
{
    __m128i a;
    a.m128i_i64[0] = x;
    __m128i b;
    b.m128i_i64[0] = y;
    // Now do something with a and b ...
}

与其像上面的例子那样做赋值,不如使用某种load函数吗?

字段m128i_i64和family是编译器特定的扩展Microsoft。它们在大多数其他编译器中不存在。

尽管如此,它们对于测试目的还是有用的。


避免使用它们的真正原因是性能。硬件无法有效地访问 SIMD 矢量的各个元素。

  • 没有允许您直接访问单个元素的说明。(SSE4.1 可以,但它需要一个编译时常量索引。
  • 由于存储转发失败,通过内存可能会招致非常大的损失。

AVX 和 AVX2 不会扩展 SSE4.1 指令以允许访问 256 位矢量中的元素。据我所知,AVX512 不会用于 512 位矢量。

同样,集合内联(如_mm256_set_pd())也会遇到同样的问题。它们要么作为一系列数据改组操作实现。或者通过记忆并承担商店转发摊位。


这就引出了一个问题:是否有一种有效的方法可以从标量组件填充 SIMD 矢量?(或将 SIMD 矢量分离为标量分量)

简短回答:不是真的。使用 SIMD 时,您需要以矢量化形式完成大量工作。因此,初始化开销应该无关紧要。