【问题标题】:improving performance for graph connectedness computation提高图连通性计算的性能
【发布时间】:2011-08-06 02:36:52
【问题描述】:


我正在编写一个程序来生成图形并检查它是否已连接。下面是代码。这是一些解释:我在平面上随机位置生成了许多点。然后我连接节点,而不是仅基于接近度。我的意思是说一个节点更有可能连接到更近的节点,这是由我在代码中使用的随机变量(h_sq)和距离决定的。因此,我生成所有链接(对称,即,如果我可以与 j 交谈,反之亦然),然后使用 BFS 检查图形是否已连接。
我的问题是代码似乎工作正常。但是,当节点数大于 ~2000 时,速度非常慢,我需要多次运行此函数以进行模拟。我什至尝试将其他库用于图形,但性能是相同的。 有谁知道我怎么可能加快一切?

谢谢,

int Graph::gen_links() {
    if( save == true ) { // in case I want to store the structure of the graph
        links.clear();
        links.resize(xy.size());
    }

    double h_sq, d;
    vector< vector<luint> > neighbors(xy.size());

    // generate links
    double tmp = snr_lin / gamma_0_lin;
    // xy is a std vector of pairs containing the nodes' locations
    for(luint i = 0; i < xy.size(); i++) {
        for(luint j = i+1; j < xy.size(); j++) {
            // generate |h|^2
            d = distance(i, j);
            if( d < d_crit ) // for sim purposes
                d = 1.0;
            h_sq = pow(mrand.randNorm(0, 1), 2.0) + pow(mrand.randNorm(0, 1), 2.0);
            if( h_sq * tmp  >= pow(d, alpha) ) {
                // there exists a link between i and j
                neighbors[i].push_back(j);
                neighbors[j].push_back(i);
                // options
                if( save == true )
                    links.push_back( make_pair(i, j) );
            }
        }
        if( neighbors[i].empty() && save == false  ) {
        // graph not connected. since save=false i dont need to store the structure, 
        // hence I exit
            connected = 0; 
            return 1;  
        }
    }

    // here I do BFS to check whether the graph is connected or not, using neighbors
    // BFS code...
    return 1;
}

更新: 主要问题似乎是内部 for 循环中的 push_back 调用。在这种情况下,这是花费大部分时间的部分。我应该使用reserve() 来提高效率吗?

【问题讨论】:

    标签: c++ performance graph simulation


    【解决方案1】:

    您确定缓慢是由生成引起的,而不是由您的搜索算法引起的吗?

    图形生成是 O(n^2),你不能做太多。但是,如果至少某些实验的点位置是固定的,您显然可以使用内存来交换一些时间。

    首先,所有节点对的距离和 pow(d, alpha) 可以预先计算并保存到内存中,这样您就不需要一次又一次地计算它们。 10000 个节点的额外内存成本为 double 约 800mb,float 约 400mb..

    另外,如果我没记错的话,正态变量的平方和是卡方分布。如果准确度允许,您可能可以进行一些预先计算的表格查找?

    最后,如果距离超过某个值,两个节点连接的概率很小,那么你不需要 O(n^2) 并且可能你只能计算那些距离更小的节点对超出一些限制?

    【讨论】:

    • 即使我修复了位置,算法的不同运行也会产生不同的链接配置,所以我无法预先计算。 BFS 引入了额外的复杂性,但如果我想检查图形是否连接,则无法避免。不过,通过稍微玩一下代码,似乎两个 for 循环花费了大部分时间,原因是平均而言,如果图断开连接,BFS 可能会终止
    【解决方案2】:

    作为第一步,您应该尝试为内部和外部向量使用保留。

    如果这没有使性能达到您的预期,我相信这是因为内存分配仍在发生。

    我在类似情况下使用过一个方便的类,llvm::SmallVector(在 Google 中找到)。它提供了一个带有少量预分配项目的向量,因此您可以将每个向量的分配数量减少一个。 当预分配空间中的项目用完时,它仍然可以增长。

    所以: 1)在运行期间检查您的向量中平均拥有的项目数(我说的是内部和外部向量) 2) 放入具有这种大小的预分配的 llvm::SmallVector (因为向量是在堆栈上分配的,您可能需要增加堆栈大小,或者如果您受到可用堆栈内存的限制,则减少预分配)。

    SmallVector 的另一个好处是它具有与 std::vector 几乎相同的接口(可以很容易地代替它)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-16
      • 2018-08-19
      • 2018-04-27
      • 2017-11-02
      相关资源
      最近更新 更多