C# 数学功率vs乘法运算符(性能)
有人知道乘法运算符是否比使用Math.Pow方法更快吗?比如:C# 数学功率vs乘法运算符(性能),c#,.net,performance,pow,C#,.net,Performance,Pow,有人知道乘法运算符是否比使用Math.Pow方法更快吗?比如: n * n * n vs 基本上,您应该基准来查看 有根据的猜测(不可靠): 如果某些编译器没有将其优化为相同的内容 很可能x*x*x比Math快。Pow(x,3)asMath。Pow必须处理一般情况下的问题,处理分数幂和其他问题,而x*x*x只需要几条乘法指令,因此,它很可能会更快。这是一个非常微小的问题,您可能应该针对特定平台对其进行基准测试,我不认为奔腾Pro的结果必然与ARM或奔腾II的结果相同 总而言之,它很可能是完全不
n * n * n
vs
基本上,您应该基准来查看 有根据的猜测(不可靠): 如果某些编译器没有将其优化为相同的内容
很可能
x*x*x
比Math快。Pow(x,3)
asMath。Pow
必须处理一般情况下的问题,处理分数幂和其他问题,而x*x*x
只需要几条乘法指令,因此,它很可能会更快。这是一个非常微小的问题,您可能应该针对特定平台对其进行基准测试,我不认为奔腾Pro的结果必然与ARM或奔腾II的结果相同
总而言之,它很可能是完全不相关的。我检查过,并且
Math.Pow()
被定义为两倍。这意味着它不能重复乘法,但必须使用更通用的方法。如果有一个Math.Pow(double,int)
,它可能会更有效率
也就是说,性能差异几乎肯定是微不足道的,因此您应该使用更清晰的。像这样的微优化几乎总是毫无意义的,几乎可以在任何时候引入,并且应该留到开发过程的末尾。在这一点上,您可以检查软件是否太慢,热点在哪里,并将您的微优化工作花费在它真正起作用的地方。让我们使用约定x^n。让我们假设n始终是一个整数 对于较小的n值,无聊的乘法会更快,因为Math.Pow(可能取决于实现)使用了奇特的算法来允许n为非整数和/或负 对于较大的n值,Math.Pow可能会更快,但如果您的库不是非常智能,它将使用相同的算法,如果您知道n始终是整数,这是不理想的。为此,您可以编写一个或一些其他奇特算法的实现
当然,现代计算机速度非常快,在对程序进行基准测试并确信使用不同的算法将获得显著的加速之前,您可能应该坚持使用最简单、最容易阅读、最不可能出现错误的方法。我刚刚重新安装了windows,因此没有安装visual studio,代码很难看
using System;
using System.Diagnostics;
public static class test{
public static void Main(string[] args){
MyTest();
PowTest();
}
static void PowTest(){
var sw = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 333333333; i++){
res = Math.Pow(i,30); //pow(i,30)
}
Console.WriteLine("Math.Pow: " + sw.ElapsedMilliseconds + " ms: " + res);
}
static void MyTest(){
var sw = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 333333333; i++){
res = MyPow(i,30);
}
Console.WriteLine("MyPow: " + sw.ElapsedMilliseconds + " ms: " + res);
}
static double MyPow(double num, int exp)
{
double result = 1.0;
while (exp > 0)
{
if (exp % 2 == 1)
result *= num;
exp >>= 1;
num *= num;
}
return result;
}
}
在我的测试中,平方求幂(参见)比Math.Pow快得多(我的CPU是2GHz的奔腾T3200)
编辑:.NET版本是3.5 SP1,操作系统是Vista SP1,power plan是高性能的。在图像处理和科学计算领域10多年的优化实践中总结出一些经验法则: 算法级别的优化胜过低级别的任何优化。尽管有“写显而易见的,然后优化”的传统智慧,但这必须在一开始就完成。以后不要了 手工编码的数学运算(尤其是SIMD SSE+类型)通常会优于完全错误检查的广义内置运算 任何编译器事先知道需要做什么的操作都会由编译器进行优化。这些措施包括: 1.内存操作,如Array.Copy()
2.对于给定数组长度的数组上的循环。至于(
;我不同意手工构建的函数总是更快。余弦函数比我能写的任何函数都要快得多,也更准确。至于pow()。我做了一个快速测试,看看javascript中Math.pow()的速度有多慢,因为Mehrdad警告不要猜测
for (i3 = 0; i3 < 50000; ++i3) {
for(n=0; n < 9000;n++){
x=x*Math.cos(i3);
}
}
如果您不同意,请尝试在上的程序。我昨天碰巧测试了这个程序,现在看到了您的问题
在我的机器上,一个运行1个测试线程的Core 2 Duo,使用乘法的速度快到9倍。在10倍时,Math.Pow(b,e)更快
然而,即使在系数为2时,结果也往往不相同。存在舍入误差
有些算法对舍入误差非常敏感。我必须运行一百万次随机测试,直到我发现这一点。Math.Pow(x,y)
通常在内部计算为Math.Exp(Math.Log(x)*y)
。每一个幂方程都需要找到一个自然对数、一个乘法,并将e
提高到一个幂
正如我在上一个答案中提到的,只有10的幂才能Math.Pow()
会变得更快,但如果使用一系列乘法,精度会受到影响。为什么您认为这种情况很可能发生?需要两个整数乘法指令。如果Math.Pow没有针对同一问题进行优化,它可能会做更多的工作(记住,它必须解决一个更一般的问题,比如分数幂…“很可能x*x*x比Math.Pow(完全是猜测)快。”这句话似乎有点不对劲。我认为System.Math是作为InternalCall实现的。但我还没有检查它。@divo:事实上,这不是猜测。这是以前的测试造成的。我想指出,这确实取决于运行代码的特定基础结构,您应该始终依赖于基准测试而不是猜测。谢谢。你的方法看起来很好。它比nnn更好吗?它需要两次乘法,就像nnn一样,但有一些开销,所以对于四(或更高)的指数来说,它会稍微差一些但是它可能比nnn*n好,因为它仍然只需要两次乘法,而直接方法需要三次。MyPow()仅适用于正数。它应该以if(exp<0)return(1/MyPow(num,Math.Abs(exp))开头
通过将模数更改为按位检查,您可以看到~1.5%的性能提高,即(exp%2==1)->((exp&1)!=0)我刚刚在笔记本电脑上运行了这个,但作为.NET Core 2.1控制台应用程序,我得到的结果是:MyPow:23545 ms,
MyPow: 6224 ms: 4.8569351667866E+255
Math.Pow: 43350 ms: 4.8569351667866E+255
for (i3 = 0; i3 < 50000; ++i3) {
for(n=0; n < 9000;n++){
x=x*Math.cos(i3);
}
}
Each function run 50000 times
time for 50000 Math.cos(i) calls = 8 ms
time for 50000 Math.pow(Math.cos(i),9000) calls = 21 ms
time for 50000 Math.pow(Math.cos(i),9000000) calls = 16 ms
time for 50000 homemade for loop calls 1065 ms