是反向更好还是更糟?

时间:2009-03-17 18:35:33

标签: .net algorithm optimization math

处理 double 时,数据类型乘以更好还是更差?

哪种方式更快? 哪种方式使用更少的内存? 哪种方式更受欢迎?

MSIL如何处理这个问题?

SquareInches = MMSquared / 645.16 
SquareInches = MMSquared * 0.0015500031000062000124000248000496

  

NB: 10K用户会注意到这是this question的副本,   因为原来被删除了   提问者决定谴责   每个人都在“评论”部分   问题。

这个问题被重新发布,因为这是一个“好”的问题。

请“取消选中”社区Wiki以获取答案,因为我只是将其作为CW发布,因此不会将其视为“声誉”抓取。

相关问题:

  

Should I use multiplication or division?

11 个答案:

答案 0 :(得分:17)

乘以逆是更快。编译器不会自动优化它,因为它可能导致精度损失很小。 (这实际上出现在D新闻组Walter Bright经常出现,并且他明确表示编译器不会自动执行此操作。)您通常应该划分,因为它更具可读性和准确性。

如果你在一个循环中执行一个浮点代码十亿次,你不关心精确度的小损失你将分裂通过相同的数次几次,然后乘以逆可以是一个很好的优化。实际上我在一些情况下获得了显着的真实世界加速,例如通过乘以逆所描述的那些,但是这些是在循环执行数十亿次的极端边缘情况,除了多次浮动之外几乎什么都不做。

答案 1 :(得分:11)

哪一个是“更快”确实是cpu特定的问题,或者至少是CPU特定的快多少,是的,除法通常被认为比乘法慢。当然,所有性能问题都可以通过“它取决于”来回答。

然而,如果你问哪个是“更好”而不是哪个更快会得到一个明确的答案,那么可读性越高越好。你所看到的性能提升很可能是几个时钟周期的顺序,所以除非你在谈论这样做数百万次,否则你试图节省自己的微秒。并且没有值得牺牲可读性和可维护性的微秒优化

答案 2 :(得分:11)

根据编译器和硬件的不同,优势将非常小或为零。

但它仍然很重要(紧密循环),然后为了可读性,你应该写

SquareInches = MMSquared * (1 / 645.16)

最好使用645.16的常数。

答案 3 :(得分:5)

答案取决于执行环境的体系结构。一般而言,在大多数处理器上,划分通常比乘法成本稍高。

所以除非这实际上是一个性能问题,否则我可能不会担心。选择更容易理解的转换因子。

答案 4 :(得分:4)

来自我的VB代码计时器

Dim SquareInches As Double
Dim MMSquared As Double = 81
Const d As Double = 645.16
Const m As Double = 1 / 645.16
Private Function TestCase1() As Boolean 'One
    'Test One Code Here
    SquareInches = MMSquared / d
    'end test code
    Return True
End Function
Private Function TestCase2() As Boolean 'Two
    'Test Two Code Here
    SquareInches = MMSquared * m
    'end test code
    Return True
End Function

结果

     3/17/2009 2:13:27 PM   CPU - 1.794GHz
 One - Using Division
 Two - Using Multiplication
 Outer Loops(OL)=7  Inner Loops=262,144
  ( times in ticks.  1 ms. = 10,000 ticks )
 >> Two faster, 0.0488 ticks/loop
  Ticks / Loop
 0.0342         0.0819          0.0331          0.0488
 OL Base        One             Two              One - Two
 1   8,936          21,459          8,609           12,850
 2   9,008          21,416          8,682           12,734
 3   8,965          21,423          8,643           12,780
 4   8,964          21,457          8,659           12,798
 5   8,966          21,469          8,640           12,829
 6   8,987          21,660          8,688           12,972
 7   8,963          21,429          8,802           12,627

  Average
 8,969          21,473          8,674           12,799
  Variance
 431.4          6,160.3         3,315.9       
  Standard Deviation
 20.8           78.5            57.6          
 3/17/2009 2:13:27 PM

答案 5 :(得分:3)

在大多数情况下,除法算法比乘法算法更慢

这是一种权衡,您可以选择更易读的方式,也可以选择更快的方式。

// Using division operation
SquareInches = MMSquared / 645.16 

这很容易阅读和维护,但执行速度比乘法对应的慢:

// Using a multiplication 
SquareInches = MMSquared * 0.0015500031000062000124000248000496

如果你这样做,你需要更多的内存空间来存储倒数字位数,但算法运算速度更快。用户在VS2005项目上对其进行了测试,并报告了乘法版本的性能提升了8倍。

原因是乘法可以盲目地转换为在处理器上移位和添加操作,这是CPU上最优化的操作。一个很好的带符号乘法算法是Booth的算法(处理器为你做这个)。另一方面,在执行除法算法时需要更多的控制开销,因此使得除法算法更慢。

如果你需要表现,可以使用加法,减法(只不过是添加两个补码),乘法,换档,但绝不使用。如果您事先计算所有的逆,并使用它们在分区密集型程序中相乘,您将获得实质性不可忽视的改进。

答案 6 :(得分:1)

关于对mult执行优化的编译器,他们可以对此进行优化(GCC): SquareInches = MMSquared *(1 / 645.16)。

答案 7 :(得分:0)

如果你除以像645.16这样的文字值,那么很可能没有区别,因为编译器可以很容易地确定哪个版本更快并使用它。
如果你正在除以或乘以一个变量,那么乘法可能会稍快一些,因为逻辑通常更简单。
与任何事情一样,可以使用分析器。

答案 8 :(得分:0)

倍增和添加是处理器支持的最快操作。有些处理器甚至没有像分区,平方根等那样的硬件实现。

答案 9 :(得分:0)

对于大多数处理器来说,乘法比乘法更快。但对于大多数应用程序而言,它实际上是微不足道的,在我看来,除非分析显示它是一个关键路径,否则你会更好地使用更具可读性的东西。

如果它是一种解释型语言,那么读取源并将其转换为数字的时间将超过实际进行数学运算所花费的时间,特别是如果你使用那么多有效数字进行乘法运算。 (你确定你真的需要那么多有效数字吗?)

答案 10 :(得分:0)

我认为第一种方法显然是首选,因为它是明确的。想象一下,在其他人的代码中找到这个。你怎么确定0.00155 ......真的是1 / 645.16?如果原始程序员犯了错误怎么办?此外,我怎么知道645.16是正确的转换因子?为简单起见,最好不要将数字压缩或表示为统一。最基本的例子如下:

//hours per day * days per year
int hoursPerYear = 24*365;

我们可以清楚地看到这个数字是正确的,但你怎么知道,8760是正确的答案?如果需要执行许多这些操作,可能需要在输入密集计算之前将数据预处理为正确的格式。通过这种方式,您不需要令人难以置信的效率,问题就变得没有实际意义了。