c - 使用 SSE 将 vector 乘以常数

标签 c gcc clang sse simd

我有一些对 4D vector 进行操作的代码,目前我正在尝试将其转换为使用 SSE。我在 64b Linux 上同时使用 clang 和 gcc。
只对 vector 进行操作就很好理解了。但现在是我必须将整个 vector 乘以一个常数的部分 - 像这样:

float y[4];
float a1 =   25.0/216.0;  

for(j=0; j<4; j++){  
    y[j] = a1 * x[j];  
} 

像这样:

float4 y;
float a1 =   25.0/216.0;  

y = a1 * x;  

哪里:

typedef double v4sf __attribute__ ((vector_size(4*sizeof(float)))); 

typedef union float4{
    v4sf v;
    float x,y,z,w;
} float4;

这当然行不通,因为我正在尝试对不兼容的数据类型进行乘法运算。
现在,我可以做类似的事情:
float4 a1 = (v4sf){25.0/216.0, 25.0/216.0, 25.0/216.0, 25.0/216.0} 但这让我觉得很傻,即使我写了一个宏来做到这一点。 另外,我很确定这不会产生非常高效的代码。

用谷歌搜索没有得到明确的答案(参见 Load constant floats into SSE registers)。

那么将整个 vector 乘以同一常数的最佳方法是什么?

最佳答案

只需使用内在函数并让编译器处理它,例如

__m128 vb = _mm_set_ps(1.0f, 2.0f, 3.0f, 4.0f); // vb = { 1.0, 2.0, 3.0, 4.0 }
__m128 va = _mm_set1_ps(25.0f / 216.0f); // va = { 25.0f / 216.0f, 25.0f / 216.0f, 25.0f / 216.0f, 25.0f / 216.0f }
__m128 vc = _mm_mul_ps(va, vb); // vc = va * vb

如果您查看生成的代码,它应该非常高效 - 25.0f/16.0f 值将在编译时计算,_mm_set1_ps 生成通常生成相当高效用于喷射 vector 的代码。

另请注意,在进入将执行大部分实际工作的循环之前,您通常只初始化一个常量 vector (如 va)一次,因此它往往不是性能 -关键。

关于c - 使用 SSE 将 vector 乘以常数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5273929/

相关文章:

c - 初始化一个int有什么副作用吗?

c - 奇怪的 mktime() 行为

c - 使用结构数组与结构指针数组的优缺点是什么?

c++ - 符号可见性和命名空间

c++ - 用于 gcc 或 clang 的 LTO 是否可以跨 C 和 C++ 方法进行优化

c++ - __restrict__ 可以应用于 shared_ptr<T> 吗?

c - 如何计算 pthread 矩阵乘法程序的运行时间?

c - 为什么编译器显示 "Call to function with no prototype"?

c - 如何修复 “for loop initial declaration used outside C99 mode” GCC 错误?

c - ANSI C -> Arrays -> Variablely modified at file scope