对于具有所有相同组件的SSE向量,可以动态生成或预计算
For for an SSE vector that has all the same components, generate on the fly or precompute?
当我需要做一个矢量操作,它的操作数只是一个广播到每个组件的浮点数,我应该预先计算__m256
或__m128
,并在需要时加载它,或者每次我需要向量时使用_mm_set1_ps
广播浮点数到寄存器吗?
我一直在预先计算非常重要和高度使用的向量,并在飞行中生成不太重要的向量。但是预计算真的能提高我的速度吗?值得这么麻烦吗?
_mm_set1_ps
是用一条指令实现的吗?这也许能回答我的问题。
我认为通常最好将SSE向量从代码中提取出来(例如循环),并在需要时使用它,假设您注意不要意外地将其强制放入内存。(例如,如果你取它的地址或通过引用传递给另一个函数,那么它可能会被强制进入内存,你可能会得到奇怪的行为。)
这个想法是,通常最好避免在SSE寄存器中输入和输出值,如果在您的特定情况下不是这种情况,编译器已经知道值是如何构造的,并且可以在需要时重新实现它。我认为这比一般的循环不变代码运动要容易得多,这是反向优化(即编译器为您考虑的地方),并且需要编译器证明代码确实是循环不变的。
我正在播放广播,以最快的方式填充向量(SSE2)具有一定的值。模板友好。看一看广播的asm转储。
每次使用 set1
应该没有太大的区别,只要编译器知道要广播的值不会别名任何东西。(如果编译器不能假设它没有别名,它将不得不在每次写入可能别名的数组或指针后重新广播。)
将set1
结果存储在命名变量中通常是很好的风格。如果编译器用完了向量寄存器,它可能会将向量溢出到堆栈中,然后重新加载,或者它可能会重新广播。我不确定编码风格是否会影响这个决定。
我不会使用static const
变量在调用函数之间缓存它。(这可能导致编译器生成代码来检查变量是否已经在每次调用中初始化。)
编译时常量的广播有时会导致编译时广播,所以你的代码在内存中只有16B的const数据。
AVX1广播寄存器中已经存在的值是最坏的情况。AVX1只提供内存源vbroadcastps
(只使用加载端口)。广播使用shufps / vinsertf128
。
AVX2需要vbroadcastps ymm, xmm
(使用shuffle端口))。
当然,这很大程度上取决于您的代码,但我已经使用这两种方法实现了两个简单的函数。看到代码
__m128 calc_set1(float num1, float num2)
{
__m128 num1_4 = _mm_set1_ps(num1);
__m128 num2_4 = _mm_set1_ps(num2);
__m128 result4 = _mm_mul_ps(num1_4, num2_4);
return result4;
}
__m128 calc_mov(float* num1_4_addr, float* num2_4_addr)
{
__m128 num1_4 = _mm_load_ps(num1_4_addr);
__m128 num2_4 = _mm_load_ps(num2_4_addr);
__m128 result4 = _mm_mul_ps(num1_4, num2_4);
return result4;
}
和装配
calc_set1(float, float):
shufps $0, %xmm0, %xmm0
shufps $0, %xmm1, %xmm1
mulps %xmm1, %xmm0
ret
calc_mov(float*, float*):
movaps (%rdi), %xmm0
mulps (%rsi), %xmm0
ret
你可以看到calc_mov()
和你所期望的一样,calc_set1()
使用了一个shuffle指令。
movps
指令大约需要4个周期来生成地址,如果L1缓存的加载端口很忙,则需要更多周期,如果发生缓存丢失,则需要更多周期。
shufps
将在任何最新的英特尔微架构上使用一个周期。我相信无论是SSE128还是AVX256都是如此。因此,我建议使用mm_set1_ps
方法。
当然,shuffle指令假设浮点数已经在SSE/AVX寄存器中。如果您从内存加载它,那么广播将会更好,因为它将在单个指令中捕获movps
和shufps
的最佳性能。
- C++ 如何使用动态计算的新节点实现 A*?
- 动态计算 unicode 字符
- 计算圆,椭圆的面积(动态法)
- C++/CUDA:动态计算最大网格大小和块大小
- 动态规划:计算集合中存在多少个升序子集
- 特征库:计算倒数时静态和动态大小矩阵之间的不同行为
- 使用动态编程计算二项式系数
- 将一个主题中的数据放入 Callback 函数中的动态数组中并进行一些计算
- 动态和静态分配数组元素计算
- 计算5*n板的正确配置(动态编程,C++)
- MPI_REDUCE动态计算的数组
- 使用动态规划计算网格中的路径数
- cudaMalloc 在静态大小方面取得了成功,但在动态计算大小方面失败了
- 我计算两个动态数组乘积的函数不起作用
- 动态规划:计算连续跳跃列表的所有可能的结束位置
- 在不模板的情况下计算另一个类的动态函数指针
- 如何使用运算符 new 来计算动态内存分配的次数
- 计算文件中的整数并复制到动态数组
- 如何计算动态内存请求是否会导致无效分配
- 在c++中创建一个动态链接库,用于不断计算数学函数