c ++中std :: min的效率

时间:2017-07-26 05:20:27

标签: c++ performance stl std min

我用c ++实现了Floyd-Warshall的算法,用C ++编写了Coursera的MOOC。我使用std :: min来查找两个节点之间的当前距离和包含跳转的最小值(根据算法的标准伪代码)。 我发现与使用if条件相比,使用std :: min会增加程序的运行时间。

e.g。

if(a[i][j] > a[i][k]+a[k][j])
  a[i][j] = a[i][k]+a[k][j];
而不是 a[i][j] = min (a[i][j], a[i][k] + a[k][j]);

我使用这些测试用例https://github.com/beaunus/stanford-algs/tree/master/testCases/course4/assignment1AllPairsShortestPath运行了这两个程序,并发现在较大的测试用例中,与带有if条件的代码相比,使用std :: min的代码需要两倍到三倍的时间。

[我知道已经提出了类似的问题,但这确实有任何真正的答案。] 编辑: 我标记了“HERE”,我用“std :: min”替换了if条件,性能差异很明显。 完整的代码在这里:

    //This implements Floyd Warshall algorithm for all pairs- shortest paths.
#include<cstdio>
#include<algorithm>
const int INF=10000, NMAX=2048; //According to the constraints of the test-files.
using namespace std;
int A[NMAX+1][NMAX+1];

int main()
{
    int n, m;   //n= number of vertices, m = number of edges in the directed graph.
    scanf("%d %d",&n,&m);
    //Initializing array of distances.
    for(int i=1; i<=n; i++)
    {   for(int j=1; j<=n; j++)
        {   A[i][j]=INF;        //This makes distance from every node to every other node = INF.
        }
        A[i][i]=0;              //distance from every node to itself is zero.
    }

    //Taking input of m edges and storing them.
    int x, y, dist;
    for(int i=0; i<m; i++)
    {   scanf("%d %d %d",&x,&y,&dist);

        if(A[x][y]>dist)        // HERE.
            A[x][y]=dist;       // There is an edge with weight "dist", tail x and head y.
    }

    for(int k=1; k<=n; k++)
    {   for(int i=1; i<=n; i++)
        {   for(int j=1; j<=n; j++)
            {   if(A[i][j] > A[i][k]+A[k][j])   //HERE.
                    A[i][j] = A[i][k]+A[k][j];
            }
        }
    }

    //This finds the minimum distance in shortest paths.
    int mindist=0, mini, minj;
    for(int i=1; i<=n; i++)
    {   if(A[i][i]<0)           //This happens iff there is negative cycle.
        {   printf("NULL\n");
            return 0;
        }
        for(int j=1; j<=n; j++) //Find the min shortest path distance between any pair of nodes.
        {   if(mindist > A[i][j])    //HERE
            {   mindist= A[i][j];
            }
        }
    }
    printf("%d\n",mindist);
    return 0;
}

1 个答案:

答案 0 :(得分:1)

这里的主要区别在于第二种形式,你(基本上)强制更新每个元素(虽然它可能是一个无变化的更新)。

在第一个版本中,您只需执行所需的更新。

这取决于您的体系结构,但如果数组较大且第二项较小的情况数相对较少,则可能导致不必要的内存写入。

调查问题的一种方法是使用条件运算符min替换?:。 如果是这种情况,性能将大致相同,因为开销不在min()中,而是在不必要地将a[i][j]的值写在自身上。

您也可以考虑创建对a[i][j]的引用:

auto &v(a[i][j]);

为了帮助最小化索引计算(优化程序可能会为您执行此操作,但您不能伤害它)。

auto &v(a[i][j]);
if(v > a[i][k]+a[k][j]) {
  v = a[i][k]+a[k][j];
}

注意:关于本地参考。任何合理的编译器都应该(通过优化)发现这个并发出相同的代码。但如果你不熟悉优化和学习,可能不是时候进入。手优化的常见缺点是可读性。我认为,优化版本无论如何都是可读的。