处理C++中执行时间的重度剖析

6
我目前正在从事一个涉及大量数据和复杂算法的科学计算项目,因此需要进行大量的代码分析。我目前依赖于<ctime>clock_t来计时我的代码执行时间。我对这个解决方案非常满意...除了我基本上会计时所有东西,因此对于每一行真正的代码,我都必须调用start_time_function123 = clock()end_time_function123 = clock()cout << "function123 execution time: " << (end_time_function123-start_time_function123) / CLOCKS_PER_SEC << endl。这导致代码膨胀严重,很快就使我的代码难以阅读。你会如何处理这个问题?
我能想到的唯一解决方案是找到一个允许我标记代码片段(在不同位置,甚至在不同文件中)并切换隐藏/显示所有标记代码的IDE。这将允许我大部分时间隐藏与分析相关的代码部分,并仅在需要时显示它们。

2
你应该研究一下 std::chrono - Jesper Juhl
@NickPavini 当然,我可以让它变得更简短,但这不是主要问题。我不想每次更改内容并想测试时都写/擦除甚至注释/取消注释每个单独的时间代码行。我目前正在使用一个基于函数中额外冗长标志参数的系统来决定是否应该打印时间。我想要的是不让我编写的代码的一半与时间有关。 - Adrien
@JesperJuhl 好的,抱歉!但我不明白告诉我去查看一个库而没有任何解释如何帮助我。我知道的是<chrono>是关于高精度的(这对我来说并不重要,因为我的执行时间不短),而<ctime>保证它测量的是程序时间而不是系统时间(这对我很重要)。 - Adrien
2
什么操作系统?使用哪个编译器及版本?难道你不能使用像gprof(1)oprofile这样的分析工具吗?在Linux上,请仔细阅读time(7) - Basile Starynkevitch
1
不要手动为分析仪添加代码,你应该投资于一款工具。 - Eugene
显示剩余3条评论
2个回答

7

有一个RAII类型,可以将代码标记为定时代码。

struct timed {
  char const* name;
  clock_t start;
  timed( char const* name_to_record):
    name(name_to_record),
    start(clock())
  {}
  ~timed(){
    auto end=clock();
    std::cout << name << " execution time: " << (end-start) / CLOCKS_PER_SEC << std::endl;
  }
};

使用它:

void foo(){
  timed timer(__func__);
  // code
}

噪音明显降低。

您可以使用非范围限定的完成操作进行增强。在进行重度分析时,有时我喜欢包含唯一的ID。使用cout和endl可能会导致它占用时间;快速记录到一个大缓冲区中,然后以异步方式转储可能是最优的选择。如果需要计时毫秒级时间,甚至应避免分配、锁定和字符串操作。


1

你没有明确说明,但我假设你正在寻找可能的加速方法-减少所需时间的方法。

你认为通过测量不同部分的时间来实现这一点。如果您有兴趣,还有一种正交的方法可以处理它。

只需在调试器下运行它(使用非优化的调试版本)。 通过Ctrl-C、Ctrl-Break或IDE的“暂停”按钮随机中断它。 显示调用堆栈并仔细检查程序在所有级别上的操作。

要怀疑它正在执行的任何操作可能是一些浪费资源的事情,你需要找到更好的做法。

然后,如果您再次启动它,并再次将其停止,并看到它正在执行相同的事情或类似的事情,那么您知道如果您修复它,您将获得大幅度的加速。您获取的样本数量越少,则获得的加速越多。

那就是随机暂停技术,其统计学原理在此处。 你在调试版本上使用它的原因在此处。 使用这种方法削减代码后,你可以切换到优化版本并获得额外的余量。

1
非常感谢,这很有趣!然而我不同意在调试模式下进行分析的想法:我只想优化代码的瓶颈,并且发布模式/优化标志提供的加速因子绝对不是程序所有部分都相同的,那么在调试模式下进行分析如何帮助我找到代码的瓶颈呢? - Adrien
@Adrien:因为正如该链接所解释的那样,优化器只能加速调用栈底部的内容,并且仅在它们位于编译器实际看到的非库代码中时才能加速。它可以优化更高层次的内容,但程序计数器在那里花费的时间很少。它能做的是使您难以找到只有可以修复的加速,例如不必要的内存分配、需要记忆化的函数、需要特殊处理的函数等等。 - Mike Dunlavey

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