加速嵌套循环并提高性能

时间:2015-01-24 12:33:41

标签: c# performance for-loop

我正在开发一个程序,它的执行时间很长。我尽力提高性能,但是我的知识在这方面有限。任何人都可以推荐一种方法来加快下面的方法吗?

public static double DistanceBetween2Points(double[,] p1, double[,] p2, int patchSize)
{
    double sum = 0;
    for (int i = 0; i < patchSize; i++)
    {
        for (int j = 0; j < patchSize; j++)
        {
            sum += Math.Sqrt(Math.Pow(p1[i, j] - p2[i, j], 2));
        }
    }
    return sum;
}

该方法通过计算两幅图像上两点之间所有距离的总和来计算两幅图像之间的距离

2 个答案:

答案 0 :(得分:3)

嗯,这个方法真的很奇怪,看起来不像像素之间的距离。但肯定你会想要使用线性代数而不是简单的数组计算。

图像识别,自然语言处理和机器学习算法都使用矩阵,因为当您需要批处理时,矩阵库会针对这种情况进行高度优化。

野外有大量的矩阵库,请看这里Recommendation for C# Matrix Library

编辑:好的,感谢您提供反馈,尝试改进答案......

您可以使用Math.Net Numerics开源库(安装MathNet.Numerics nuget包)并重写您的方法,如下所示:

using MathNet.Numerics.LinearAlgebra;

public static double DistanceBetween2Points(double[,] p1, double[,] p2, int patchSize)
{
   var A = Matrix<double>.Build.DenseOfArray(p1).SubMatrix(0, patchSize, 0, patchSize);
   var B = Matrix<double>.Build.DenseOfArray(p2).SubMatrix(0, patchSize, 0, patchSize);

   return (A - B).RowAbsoluteSums().Sum();
}

基本上,循环会降低代码的速度。理想情况下,在进行批处理时,应该完全避免循环。

答案 1 :(得分:2)

  1. 考虑一下你的算法。可能像素距离不是获得精确图像距离的最佳选择。

  2. sqrt(x^2)替换为abs(x)甚至更快:

    if(x < 0) x = -x;
    
  3. 将您的例程重命名为OverallImageDistance或类似(不会提高性能);)

  4. 使用unsafe指针,并使用这些指针在单个循环中计算距离:

    unsafe
    {
      sum = 0.0;
      int numPixels = patchsize*patchsize;
      fixed(int *pointer1 = &p1[0])
      {
        fixed(int* pointer2 = &p2[0])
        {
    
          while(numPixels-- > 0) 
          {
            double dist = *pointer1++ - *pointer2++;
            if(dist < 0) dist = -dist;
            sum += dist;
          }
    ...
    
  5. 这应该比你原来快几倍。