我正在开发一个扩展 OpenCV、HALCON、...的图像处理库。该库必须与 .NET Framework 3.5 一起使用,并且由于我对 .NET 的经验有限,因此我想就性能提出一些问题。
我遇到了一些具体的事情,我无法正确地向自己解释,希望你问:a)为什么,b)处理这些案件的最佳做法是什么。
我的第一个问题是关于 Math.pow。我已经在 StackOverflow 上找到了一些答案,这很好地解释了它(a),但不知道该怎么做(b)。我的基准程序看起来像这样
Stopwatch watch = new Stopwatch(); // from the Diagnostics class
watch.Start();
for (int i = 0; i < 1000000; i++)
double result = Math.Pow(4,7) // the function call
watch.Stop()
结果不是很好(在我的计算机上约为 300 毫秒)(我已经运行了 10 次测试并计算了平均值)。
我的第一个想法是检查这是否是因为它是一个静态函数。所以我实现了自己的课程
class MyMath
{
public static double Pow (double x, double y) //Using some expensive functions to calculate the power
{
return Math.Exp(Math.Log(x) * y);
}
public static double PowLoop (double x, int y) // Using Loop
{
double res = x;
for(int i = 1; i < y; i++)
res *= x;
return res;
}
public static double Pow7 (double x) // Using inline calls
{
return x * x * x * x * x * x * x;
}
}
我检查的第三件事是我是否会直接通过 4*4*4*4*4*4*4 替换 Math.Pow(4,7)。
结果是(10 次测试运行的平均值)
300 ms Math.Pow(4,7)
356 ms MyMath.Pow(4,7) //gives wrong rounded results
264 ms MyMath.PowLoop(4,7)
92 ms MyMath.Pow7(4)
16 ms 4*4*4*4*4*4*4
现在我现在的情况基本上是这样的:Don't use Math for Pow。我唯一的问题是……我现在真的必须实现自己的数学课吗?仅仅为 power 函数实现一个自己的类似乎有点无效。(顺便说一句。PowLoop 和 Pow7 在 Release 构建中的速度甚至快了约 25%,而 Math.Pow 则没有)。
所以我最后的问题是
a)如果我根本不使用 Math.Pow(但可能是分数)(这让我有点难过),我错了。
b) 如果你有代码需要优化,你真的是直接写所有这些数学运算吗?
c)可能已经有一个更快的(开源^^)数学运算库
d) 我的问题的来源基本上是:我假设.NET Framework 本身已经为这些基本操作提供了非常优化的代码/编译结果 - 无论是数学类还是处理数组,我有点惊讶有多少好处我会通过编写自己的代码来获益。在我不能直接信任 C# 的 C# 中是否有一些其他的通用“字段”或其他东西需要注意。