相关疑难解决方法(0)

在x86上做水平浮点矢量和的最快方法

你有一个三(或四)个浮点数的向量.总结它们的最快方法是什么?

SSE(movaps,shuffle,add,movd)总是比x87快吗?SSE4.2中的水平加法说明值得吗?移动到FPU的成本是多少,然后是faddp,faddp?什么是最快的特定指令序列?

"尝试安排事情,这样你可以一次总结四个向量"将不被接受作为答案.:-)

floating-point optimization x86 assembly sse

41
推荐指数
4
解决办法
2万
查看次数

使用SSE进行高效的4x4矩阵向量乘法:水平加点和点积 - 重点是什么?

我试图使用SSE找到使用向量(u)的4x4矩阵(M)乘法的最有效实现.我的意思是Mu = v.

据我所知,有两种主要方法可以解决这个问题:

    method 1) v1 = dot(row1, u), v2 = dot(row2, u), v3 = dot(row3, u), v4 = dot(row4, u)
    method 2) v = u1 col1 + u2 col2 + u3 col3 + u4 col4.
Run Code Online (Sandbox Code Playgroud)

方法2易于在SSE2中实现.方法1可以用SSE3中的水平加法指令或SSE4中的点积指令来实现.但是,在我的所有测试中,方法2总是优于方法1.

我认为方法1有优势的一个地方是3x4矩阵,例如仿射变换.在这种情况下,最后一个点积是不必要的.但即使在这种情况下,4x4矩阵上的方法2也比3x4矩阵上的方法1快.我发现的唯一方法比4x4矩阵上的方法2快4x3矩阵上的方法2.

那么水平加法和点积指令有什么意义呢?事实上,点生产指令在这种情况下表现最差.也许它与数据格式有关?如果无法定义矩阵的排序方式,那么转置是必要的,在这种情况下,方法1可能会更好吗?

请参阅下面的一些代码.

__m128 m4x4v_colSSE(const __m128 cols[4], const __m128 v) {
  __m128 u1 = _mm_shuffle_ps(v,v, _MM_SHUFFLE(0,0,0,0));
  __m128 u2 = _mm_shuffle_ps(v,v, _MM_SHUFFLE(1,1,1,1));
  __m128 u3 = _mm_shuffle_ps(v,v, _MM_SHUFFLE(2,2,2,2));
  __m128 u4 = _mm_shuffle_ps(v,v, _MM_SHUFFLE(3,3,3,3));

  __m128 prod1 = _mm_mul_ps(u1, cols[0]);
  __m128 prod2 = _mm_mul_ps(u2, cols[1]);
  __m128 …
Run Code Online (Sandbox Code Playgroud)

c optimization performance sse matrix-multiplication

15
推荐指数
1
解决办法
9454
查看次数

如何横向汇总__m256?

我想__m256使用AVX指令水平地对矢量的分量求和.在SSE我可以使用

_mm_hadd_ps(xmm,xmm);
_mm_hadd_ps(xmm,xmm);
Run Code Online (Sandbox Code Playgroud)

在向量的第一个组件处获得结果,但这不能与函数(_mm256_hadd_ps)的256位版本一起扩展.

计算__m256向量水平和的最佳方法是什么?

sse vectorization intrinsics avx

11
推荐指数
2
解决办法
6666
查看次数

与AVX一起使用4个水平双精度和

问题可以描述如下.

输入

__m256d a, b, c, d
Run Code Online (Sandbox Code Playgroud)

产量

__m256d s = {a[0]+a[1]+a[2]+a[3], b[0]+b[1]+b[2]+b[3], 
             c[0]+c[1]+c[2]+c[3], d[0]+d[1]+d[2]+d[3]}
Run Code Online (Sandbox Code Playgroud)

到目前为止我所做的工作

这看起来很容易:两个VHADD之间有一些混乱,但实际上结合AVX特有的所有排列不能产生实现该目标所需的非常排列.让我解释:

VHADD x, a, b => x = {a[0]+a[1], b[0]+b[1], a[2]+a[3], b[2]+b[3]}
VHADD y, c, d => y = {c[0]+c[1], d[0]+d[1], c[2]+c[3], d[2]+d[3]}
Run Code Online (Sandbox Code Playgroud)

我是否能够以相同的方式置换x和y来获得

x1 = {a[0]+a[1], a[2]+a[3], c[0]+c[1], c[2]+c[3]}
y1 = {b[0]+b[1], b[2]+b[3], d[0]+d[1], d[2]+d[3]}
Run Code Online (Sandbox Code Playgroud)

然后

VHADD s, x1, y1 => s1 = {a[0]+a[1]+a[2]+a[3], b[0]+b[1]+b[2]+b[3], 
                         c[0]+c[1]+c[2]+c[3], d[0]+d[1]+d[2]+d[3]}
Run Code Online (Sandbox Code Playgroud)

这是我想要的结果.

因此,我只需要找到如何执行

x,y => {x[0], x[2], y[0], y[2]}, {x[1], x[3], y[1], y[3]}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我得出的结论是,使用VSHUFPD,VBLENDPD,VPERMILPD,VPERM2F128,VUNPCKHPD,VUNPCKLPD的任何组合都是不可能的.问题的关键在于,在__m256d的实例u中交换u [1]和u [2]是不可能的.

题 …

sum intel avx

8
推荐指数
1
解决办法
2442
查看次数

LLVM IR:有效地对矢量求和

我正在编写一个生成LLVM IR指令的编译器.我正在广泛地使用矢量.

我希望能够将向量中的所有元素相加.现在我只是单独提取每个元素并手动添加它们,但它让我觉得这正是硬件应该能够帮助的东西(因为它听起来像一个非常常见的操作).但似乎并没有做到这一点.

最好的方法是什么?我正在使用LLVM 3.2.

llvm llvm-ir llvm-3.2

5
推荐指数
1
解决办法
1834
查看次数