【问题标题】:Speed up nested for loops and improve performance加快嵌套 for 循环并提高性能
【发布时间】:2015-01-24 12:33:40
【问题描述】:

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

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

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

【问题讨论】:

  • 我不确定您的例程在做什么,但您是否尝试删除 SqrtPow 操作并改用 Abs
  • 我没有,我现在试试。你碰巧知道一种加速 for 循环的方法吗?我很确定它们是执行时间如此缓慢的原因
  • 这是很奇怪的计算。你要计算什么?你能更详细地解释你的意图吗?
  • 我正在搜索和比较图像上的不同补丁。基本上它是用于图像识别,给出传入的两个补丁(p1和p2)我计算每个像素与原始图像和比较图像的距离。 (希望这是有道理的)
  • @ConorShannon - 好吧,你似乎是一个 ^2,实际上只是删除了 - 符号 - 但我看不出你在做什么将实现计算的目标距离(但有时我们并不总是有大局)

标签: c# performance for-loop


【解决方案1】:
  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;
          }
    ...
    

这应该比原来的速度快几倍。

【讨论】:

    【解决方案2】:

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

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

    有大量的矩阵库,看这里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();
    }
    

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

    【讨论】:

      猜你喜欢
      • 2012-11-25
      • 2021-12-01
      • 2019-04-01
      • 1970-01-01
      • 2013-01-29
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      相关资源
      最近更新 更多