【问题标题】:C++ speed up method callC++加速方法调用
【发布时间】:2016-07-15 19:46:31
【问题描述】:

我正在开发一个非常耗时的应用程序,我想加快速度。我使用 ctime 库的 clock() 函数分析了单个部分的运行时,发现了一些对我来说并不完全清楚的东西。

我有时间在方法的内外打印,我们称之为 Method1。 Method1 里面的 print 包括了它的全部内容,当然只排除了一个 float 的返回。嗯,问题是,外部打印状态是 Method1 内部打印时间的两倍到三倍。很明显,外面的打印应该说明更多的时间,但在我看来差异很大。

我的方法如下所示,我使用引用和指针作为参数来防止数据复制。请注意,数据向量包含 330.000 个指向实例的指针。

float ClassA::Method1(vector<DataClass*>& data, TreeClass* node)
{
    //start time measurement
    vector<Mat> offset_vec_1 = vector<Mat>();
    vector<Mat> offset_vec_2 = vector<Mat>();
    for (int i = 0; i < data.size(); i++)
    {
        DataClass* cur_data = data.at(i);
        Mat offset1 = Mat();
        Mat offset2 = Mat();

        getChildParentOffsets(cur_data, node, offset1, offset2);

        offset_vec_1.push_back(offset1);
        offset_vec_2.push_back(offset2);
    }

    float ret = CalculateCovarReturnTrace(offset_vec_1) + CalculateCovarReturnTrace(offset_vec_2);
    //end time measurement
    return ret;
}

有什么“明显”的方法可以提高通话速度吗?出于可读性原因,我更愿意保留该方法,因此,我可以更改任何内容以加快速度吗?

我很感激任何建议!

【问题讨论】:

  • 除非您找到内联函数的方法,否则提高调用速度的潜力不大。
  • 可能有析构函数调用占用时间...如果函数中创建了很多复杂的结构,可能有很多需要清理的地方
  • 就目前而言,两个参数(一个通过引用,另一个是指针)并返回一个浮点数本身不会产生太多开销
  • 提供的细节太少。 Method 是虚函数吗?目标架构是什么?什么是编译器优化标志?
  • 在 return 语句之后仍有 660,000 次 Mat 释放。

标签: c++ performance methods call


【解决方案1】:

根据您更新的代码,结束时间测量和函数调用后测量之间的唯一代码是函数中构造对象的析构函数。那是每个 330,000 Mats 的两个向量。这可能需要一些时间,具体取决于每个Mats 使用的资源。

【讨论】:

  • 这样的事情可能会出现的一个普遍问题是,您可能很快就会在堆中放置数千个这些动态对象的副本,等待垃圾收集......而且,不仅垃圾收集现在相当昂贵,当它确实出现时,但整体堆区域很大。 (因此,很可能会导致大量页面错误。)如果对这个 Mat 对象进行“擦除”操作,将删除的元素放入某种空闲列表中进行回收,这可能会有所帮助。但如果它只是“free()s”一切,它就不会。虚拟机分页会扼杀时钟时间。
  • 垫子很小,它们只包含 3 个花车。因此,它们应该需要少于 8 MB。
  • 嗯,只是好奇这些 OpenCV Mats 还是其他结构?我真正要问的是类似于@MikeRobinson 所说的。因为如果它们是单独的分配,那将需要一些时间来释放,但如果它们不是并且因此成为通过std::vector 连续分配的一部分,那么我希望它会很快
  • @vu1p3n0x 这些是 OpenCV Mats,是的。是的,我知道你的意思。但是,我怎么知道它们是否真的连续存储在内存中?问题是,我确实在堆栈上分配它们,然后将它们添加到vector -> 是Mats 然后复制到它,这意味着堆栈上的初始分配需要“删除”?跨度>
  • std::vector 保证连续存储其元素,但该向量中的结构使用的资源将单独分配。
【解决方案2】:

没有试图声称任何其他人向 OP 制作的 cmets ...

(1) 简短的回答很可能是,“不”。 这个函数看起来很清楚,它做了很多工作 30,000 次。然后,它对“所有数据”进行计算。

(2) 考虑重新使用“offset1”和“offset2”矩阵,而不是为每次迭代创建全新的矩阵。当然,这是否真的会更快还有待观察。 (在任何情况下,见下文,这相当于“玩弄代码”。)

(3) 因此,借用 The Elements of Programming Style: “不要为了加快速度而‘篡改’代码:找到更好的算法。”在这种情况下,可能没有。您可能需要通过“向其扔硅”来解决运行时问题,我建议您首先要做的是为这台计算机添加尽可能多的 RAM。 “处理大量数据”的进程非常容易受到虚拟内存页面错误的影响,每个页面错误都需要大约 *milli-*seconds 才能解决。 (那百分之一秒的加起来真的很快。)

我个人认为这段代码没有任何明确错误,也没有任何明确会导致它运行得更快的地方。我也不主张重写("diddling")你现在拥有的非常清晰的代码。

【讨论】:

  • 我投了赞成票。但我确实想指出,您实际上并没有解决这个问题。您就如何优化该方法提出了建议,但您没有解释为什么内部测量显示的值比外部测量小得多。 (可能是因为矩阵释放,正如 vu1p3n0x 指出的那样。)
  • 确实我没有回答这个问题,因为我能提供的任何意见都只是一个有根据的猜测......一个与你的猜测非常相似的猜测。
  • 谢谢。我会在(2)中尝试你的建议。关于(3)你是对的。但是,我确信 RAM 不会用完(我已经对其进行了优化)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-11
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多