首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在SIMD上有更快的方法乘2(不用乘法)吗?

在SIMD上有更快的方法乘2(不用乘法)吗?
EN

Stack Overflow用户
提问于 2014-08-28 19:36:13
回答 2查看 461关注 0票数 4

使用旧浮标的技巧过去是永远不乘以2,而是自己添加一个操作数,例如,2*a = a +a。对于SSE/SSE 2/SSSE3 3/NEON/…今天的指令集之类的?我的操作数将是一个向量(例如,4浮点数,我想乘2)。乘以3,4怎么样.?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-08-29 09:20:32

我还在努力找一个例子来说明这会有什么不同。我的直觉是,如果延迟是一个问题,那么有些情况下x+x会更好,但是如果延迟不是问题,只有吞吐量才重要,那么情况可能会更糟。但首先让我们讨论一些硬件。

让我坚持英特尔的x86处理器,因为这是我最了解的。让我们考虑以下几代硬件:Core2 2/Nehalem、SandyBridge/IvyBridge和Haswell/Broadwell

SIMD浮动指针算法操作的延迟和吞吐量:

  • 加法的延迟为3。
  • 除布罗德韦尔外,乘法的潜伏期为5。
  • 在Broadwell上,乘法的潜伏期为3。
  • 添加的吞吐量为1。
  • 除Haswell和Broadwell外,乘法的吞吐量为1。
  • 在Haswell和Broadwell上,乘法素的吞吐量为2。
  • 不带FMA的加法和乘法的吞吐量为2。
  • FMA的延迟为5。
  • FMA的吞吐量为2,这相当于4的加法和乘法吞吐量。

,这里是我用来生成Mandelbrot集的一个例子,它的因子为2。在主循环中,最关键的代码行有两行:

代码语言:javascript
复制
x = x*x - y*y + x0;
y = 2*xtemp*y + y0;

这里的所有变量都是SIMD (SSE或AVX)寄存器,因此我一次对多个像素进行操作(4与SSE,8与AVX用于单个浮点)。为此,我使用了一个SIMD类,它围绕着本质。对于y,我可以代替

代码语言:javascript
复制
y = xtemp*y + xtemp*y + y0

那FMA呢?

代码语言:javascript
复制
y = fma(2*xtemp, y, y0)

代码语言:javascript
复制
y = xtemp*y + fma(xtemp, y, y0);

有许多变化是可以尝试的。我还没有试过y=xtemp*y + xtemp*y + y0,但我认为情况会更糟。顺便说一句,到目前为止,我在Haswell系统上实现FMA的方式并没有多大帮助。我的帧率只增加了15%左右使用FMA,而当我从使用4像素的SSE到8像素与AVX,它几乎加倍。

编辑:这里有一些我认为会有所改变的案例,但它们要么在实践中行不通,要么就没有意义。

考虑这个案子

代码语言:javascript
复制
for(int i=0; i<n; i++) y[i] = 2*x[i];

在这种情况下,延迟并不重要,吞吐量很重要。在Haswell和Broadwell上,乘法的吞吐量是两倍加法,所以在这种情况下,做x+x可能会更糟,但是由于Haswell/Broadwell每个时钟周期只能写32字节,所以没有什么区别。

在这里,使用x+x似乎更好。

代码语言:javascript
复制
for(int i=0; i<n; i++) prod = prod * (2*x[i]);

相反,你可以这样做:

代码语言:javascript
复制
for(int i=0; i<n; i++) prod = prod * (x[i]+x[i]);

在这两种情况下,这将不会有任何区别,因为他们是主导的潜伏期的prod增殖。然而,如果你对循环展开足够多的时间,以至于延迟不重要,那么第二种情况通常会更好,因为所有处理器至少可以在每个时钟周期进行加法和乘法。虽然哈斯韦尔和布罗德威尔每个时钟周期可以进行两次乘法,但也可以使用FMA进行每个时钟周期的两次乘法和加法,因此即使在它们上,这也会更好。

然而,在这种情况下,明智的做法是

代码语言:javascript
复制
for(int i=0; i<n; i++) prod *= x[i];
prod *= pow(2,n);

因此,没有必要执行x+x而不是2*x

票数 5
EN

Stack Overflow用户

发布于 2014-08-28 19:52:28

编译器编写者很聪明。对于浮点数x,2.0 *x和x+x是完全相同的。因此,编译器很有能力用x+x代替2.0*x,反之亦然,这取决于哪种方法更快。

这可能会很复杂。加法通常更快。但考虑一个处理器,它可以做一个乘法和每个周期的加法。然后你想用2*x和y+y替换2*x和2*y。如果你有一个操作2*x和y+z,那么你不想用x+x替换2*x,因为你有两个加法,只能在两个循环中完成。还有一个处理器,它可以在一次运算中计算a*b +c。所以你不想把2*x + y改为(x + x) +y。

最好把它留给编译器。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25556683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档