加速嵌套的for循环并提升性能

3

我正在开发一个程序,它的执行时间相当长。我试图在能力范围内提高性能,但是我的知识在这个领域有限。有没有人能推荐一种加速下面方法的方式?

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;
}

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

1
我不确定你的例程在做什么,但你尝试过去掉 SqrtPow 操作,使用 Abs 替代吗? - Shaun Wilde
我正在搜索和比较图像上的不同补丁。基本上这是为了图像识别,给定传递的两个补丁(p1和p2),我计算每个像素与原始图像和比较图像之间的距离。(希望这有意义) - Conor Shannon
@ConorShannon - 希望你有一些已知“输入”和“结果”的测试数据,以便对你的算法进行测试。 - Shaun Wilde
你确定需要 double 类型的输入而不是 int 类型吗?这些数组里具体存储了什么内容? - PTwr
补丁大小通常有多大? - Zoom
显示剩余4条评论
2个回答

3
  1. Think about your algorithm. Probably a pixel-distance isn't the best thing to get an acurate image-distance.

  2. replace sqrt(x^2) by abs(x) or even faster:

    if(x < 0) x = -x;
    
  3. Rename your routine to OverallImageDistance or similar(will not improve performance) ;)

  4. Use unsafe pointers, and calculate your distance in a single loop using these pointers:

    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;
          }
    ...
    
这应该比原来的快几倍。

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();
}

基本上,循环会减慢您的代码。在进行批量处理时,最好尽量避免使用循环。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接