【问题标题】:SSE (SIMD): multiply vector by scalarSSE (SIMD):向量乘以标量
【发布时间】:2012-02-23 04:11:06
【问题描述】:

我在我的程序中执行的一个常见操作是按标量缩放向量(V*s,例如 [1,2,3,4]*2 == [2,4,6,8])。除了首先在向量中的每个位置加载标量(例如 _mm_set_ps(2,2,2,2))然后相乘之外,是否有 SSE(或 AVX)指令来执行此操作?

这就是我现在所做的:

__m128 _scalar = _mm_set_ps(s,s,s,s);
__m128 _result = _mm_mul_ps(_vector, _scalar);

我正在寻找类似...的东西

__m128 _result = _mm_scale_ps(_vector, s);

【问题讨论】:

    标签: c x86 sse simd


    【解决方案1】:

    根据您的编译器,您可以使用_mm_set1_ps 稍微改进代码生成:

    const __m128 scalar = _mm_set1_ps(s);
    __m128 result = _mm_mul_ps(vector, scalar);
    

    然而,像这样的标量常量应该只需要在任何循环之外初始化一次,因此性能成本应该是无关紧要的。 (除非标量值在循环内发生变化?)

    与往常一样,您应该查看编译器生成的代码,并尝试在合适的分析器下运行您的代码,以查看热点的真正位置。

    【讨论】:

      【解决方案2】:

      没有向量乘以标量的指令。但是,这里有一些指令用于将相同的标量值加载到向量寄存器的所有位置。

      AVX 指令集提供 _mm_broadcast_ss/_mm256_broadcast_ss/_mm256_broadcast_sd 内部函数,用于使用相同的浮点/双精度值填充 SSE 和 AVX 寄存器。

      在 SSE3 指令集中,您可能会发现 _mm_loaddup_pd intrinsic 使用相同的双精度值填充 SSE 寄存器。

      在其他版本的 SSE 中,通常最好的选择是使用 _mm_load_ss/_mm_load_sd 加载标量值,然后使用 _mm_shuffle_ps/_mm_unpacklo_pd 将其复制到向量寄存器的所有元素。

      【讨论】:

        【解决方案3】:

        我不知道有任何一条指令可以满足您的要求。集合操作真的是瓶颈吗?如果您将一个大向量乘以同一个常数,则用四个常数副本填充 XMM/YMM 寄存器所需的时间应该只是总时间的一小部分。

        作为一个简单的优化,如果常量为 2,就像在您的示例中一样,您可以将乘法替换为加法指令,而不需要任何常量。

        【讨论】:

          猜你喜欢
          • 2011-07-13
          • 2017-11-14
          • 2013-04-04
          • 2021-03-25
          • 2020-03-16
          • 2011-07-05
          • 2021-08-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多