标签: simd

计算距离平方的最快方法

我的代码在很大程度上依赖于计算3D空间中两点之间的距离.为了避免昂贵的平方根,我使用整个平方距离.但它仍然占用了计算时间的很大一部分,我想用更快的东西替换我的简单函数.我现在有:

double distance_squared(double *a, double *b)
{
  double dx = a[0] - b[0];
  double dy = a[1] - b[1];
  double dz = a[2] - b[2];

  return dx*dx + dy*dy + dz*dz;
}
Run Code Online (Sandbox Code Playgroud)

我也尝试使用宏来避免函数调用,但它没有多大帮助.

#define DISTANCE_SQUARED(a, b) ((a)[0]-(b)[0])*((a)[0]-(b)[0]) + ((a)[1]-(b)[1])*((a)[1]-(b)[1]) + ((a)[2]-(b)[2])*((a)[2]-(b)[2])
Run Code Online (Sandbox Code Playgroud)

我想过使用SIMD指令但是找不到一个好的例子或完整的指令列表(理想情况下是一些乘法+加两个向量).

GPU不是一个选项,因为每个函数调用只知道一组点.

计算距离平方的最快方法是什么?

c optimization simd

14
推荐指数
2
解决办法
5434
查看次数

如何在256位AVX向量中找到水平最大值

我有一个__m256d向量,包含四个64位浮点值.
我需要找到向量元素的水平最大值,并将结果存储在双精度标量值中;

我的尝试最终都使用了很多矢量元素的改组,使得代码不是很优雅也没有效率.此外,我发现不可能只留在AVX域.在某些时候,我不得不使用SSE 128位指令来提取最终的64位值.但是,我想在最后的声明中被证明是错误的.

因此理想的解决方案将:
1)仅使用AVX指令.
2)最小化指令数量.(我希望不超过3-4条说明)

话虽如此,任何优雅/高效的解决方案都将被接受,即使它不符合上述指导原则.

谢谢你的帮助.

-Luigi

x86 simd vector-processing avx avx2

14
推荐指数
2
解决办法
6709
查看次数

用于SSE和AVX的SIMD数学库

我正在为SSE和AVX寻找SIMD数学库(最好是开源).我的意思是,例如,如果我有一个具有8个浮点值的AVX寄存器v,我希望sin(v)一次返回所有八个值的sin.

AMD有一个propreitery库,LibM http://developer.amd.com/tools/cpu-development/libm/,它有一些SIMD数学函数,但如果它检测到Intel CPU没有的FMA4,LibM只使用AVX.另外我不确定它是否完全使用AVX,因为所有的功能名称都以s4(d2)而不是s8(d4)结尾.它提供了比英特尔CPU上的标准数学库更好的性能,但它并没有好多少.

英特尔将SVML作为其C++编译器的一部分,但编译器套件在Windows上非常昂贵.此外,英特尔还削弱了非英特尔CPU上的库.

我找到了以下AVX库,http://software-lisc.fbk.eu/avx_mathfun/,它支持一些数学函数(exp,log,sin,cos和sincos).它为我提供了非常快的结果,比SVML更快,但我没有检查准确性.它仅适用于单个浮点,并且在Visual Studio中不起作用(尽管这很容易修复).它基于另一个SSE库.

有没有人有任何其他建议?

编辑:我发现一个SO线程有很多关于这个主题的答案 Vectorized Trig函数在C?

sse simd math.h avx

14
推荐指数
1
解决办法
1万
查看次数

使用AVX/AVX2转置8x8浮点数

通过制作四个4x4矩阵并转置每个矩阵,可以实现8x8矩阵的转置.这不是我想要的.

在另一个问题中,一个答案提供了一个解决方案,只需要24个8x8矩阵指令.但是,这不适用于花车.

由于AVX2包含256位寄存器,因此每个寄存器适合8个32位整数(浮点数).但问题是:

如何使用AVX/AVX2转换8x8浮点矩阵,尽可能使用最小的指令?

simd avx avx2

14
推荐指数
2
解决办法
6323
查看次数

分支和谓词指令

"CUDA C编程指南" 第5.4.2节规定,分支差异由"分支指令"处理,或者在某些条件下由"预测指令"处理.我不明白两者之间的区别,以及为什么一个导致比另一个更好的性能.

该评论表明,分支指令导致更多数量的执行指令,由于"分支地址解析和获取"而导致停止,以及由于"分支本身"和"发散保留"导致的开销,而预测指令仅产生"指令执行延迟,以进行条件测试并设置谓词".为什么?

cuda simd

14
推荐指数
1
解决办法
3241
查看次数

使用SSE计算绝对值的最快方法

我知道3种方法,但据我所知,通常只使用前2种方法:

  1. 使用andps或屏蔽符号位andnotps.

    • 优点:一个快速指令,如果掩码已经在寄存器中,这使得它非常适合在循环中多次执行此操作.
    • 缺点:掩码可能不在寄存器中或更糟糕,甚至不在缓存中,导致非常长的内存提取.
  2. 将值从零减去否定,然后得到原始的最大值并否定.

    • 优点:固定成本,因为无需取物,就像面具一样.
    • 缺点:如果条件理想,将始终比掩码方法慢,并且我们必须等待subps完成才能使用该maxps指令.
  3. 与选项2类似,将原始值从零减去否定,但随后使用原始值"按位"和"按位" andps.我运行了一个测试,将其与方法2进行比较,除了处理NaNs 之外,它似乎与方法2的行为相同,在这种情况下,结果将NaN与方法2的结果不同.

    • 优点:应该比方法2略快,因为andps通常比速度快maxps.
    • 缺点:当NaN涉及到s 时,这是否会导致任何意外行为?也许不是,因为a NaN仍然是a NaN,即使它是一个不同的值NaN,对吧?

欢迎提出想法和意见.

x86 sse simd vectorization absolute-value

14
推荐指数
1
解决办法
5397
查看次数

我可以使用AVX FMA单元进行精确的52位整数乘法吗?

AXV2没有任何整数乘法,其源大于32位.它提供32 x 32 - > 32乘法,以及32 x 32 - > 64乘以1,但没有64位源.

假设我需要一个输入大于32位但小于或等于52位的无符号乘法 - 我可以简单地使用浮点DP乘法或FMA指令,并且当整数输入和输出时输出将是位精确的结果可以用52或更少的比特表示(即,在[0,2 ^ 52-1]范围内)?

如果我想要产品的所有104位更一般的情况怎么样?或整数乘积超过52位的情况(即,产品在位索引中的非零值> 52) - 但我只想要低52位?在后一种情况下,它MUL会给我更高的位并舍去一些低位(也许这就是IFMA帮助的?).

编辑:事实上,根据这个答案,也许它可以做任何高达2 ^ 53的事情- 我忘记了1在尾数之前隐含的领先有效地给了你一点.


1有趣的是,正如Mysticial 在评论中所解释的那样,64位产品PMULDQ操作的延迟是32位PMULLD版本的一半,吞吐量是32位版本的两倍.

floating-point x86 simd avx2 fma

14
推荐指数
1
解决办法
1278
查看次数

获取__m256变量中第一个不为零的元素的索引

__m256  dst = _mm256_cmp_ps(value1, value2, _CMP_LE_OQ);
Run Code Online (Sandbox Code Playgroud)

如果dst是,[0,0,0,-nan, 0,0,0,-nan]; 我希望能够知道第一个-nan索引,在这种情况下,3无需进行for循环8迭代。这可能吗?

c c++ sse simd avx

14
推荐指数
1
解决办法
318
查看次数

使用英特尔上的SSE2减少无溢出的无符号字节数

我试图在Intel i3处理器上找到32个元素(每个1字节数据)的总和减少量.我这样做了:

s=0; 
for (i=0; i<32; i++)
{
    s = s + a[i];
}  
Run Code Online (Sandbox Code Playgroud)

但是,由于我的应用程序是一个需要更少时间的实时应用程序,因此需要花费更多时间.请注意,最终金额可能超过255.

有没有办法可以使用低级SIMD SSE2指令实现这一点?不幸的是我从未使用过SSE.我试图为此目的搜索sse2函数,但它也不可用.(sse)是否可以保证减少这种小型问题的计算时间?

有什么建议??

注意:我已经使用OpenCL和CUDA实现了类似的算法,虽然问题规模很大,但效果很好.对于小型问题,开销成本更高.不确定它在SSE上是如何工作的

x86 sse simd sse2 sse3

13
推荐指数
2
解决办法
4952
查看次数

使用AVX2收集指令时加载地址计算

查看AVX2内在函数文档,收集了加载指令,例如VPGATHERDD:

__m128i _mm_i32gather_epi32 (int const * base, __m128i index, const int scale);
Run Code Online (Sandbox Code Playgroud)

从文档中我不清楚的是计算的加载地址是 元素地址还是字节地址,即元素的加载地址i:

load_addr = base + index[i] * scale;               // (1) element addressing ?
Run Code Online (Sandbox Code Playgroud)

要么:

load_addr = (char *)base + index[i] * scale;       // (2) byte addressing ?
Run Code Online (Sandbox Code Playgroud)

英特尔文档看起来它可能是(2),但是这没有多大意义,因为聚集的负载的最小元素大小是32位 - 为什么要从未对齐的地址加载(即使用比例<4) )?

x86 sse simd avx2

13
推荐指数
2
解决办法
4146
查看次数