在多线程 C++ 应用程序中测量时间

Posted

技术标签:

【中文标题】在多线程 C++ 应用程序中测量时间【英文标题】:Measuring time in a multithreaded C++ application 【发布时间】:2014-10-01 12:34:11 【问题描述】:

我正在使用 C++ 和 OpenMP 编写一个应用程序,我想可靠地(并且正确地)测量它的部分执行时间。我查看了一些选项(Windows、TDM-GCC x64 4.8.1):

    omp_get_wprocclock 似乎可以完成这项工作,但文档(与实际行为直接矛盾)说它们测量给定进程消耗的总时间资源(即,例如,两个工作线程的一秒计为两秒)。 “正确”的行为是不是我想要的, time/difftime分辨率不够, GetProcessTime (WinAPI) 做时钟应该做的事情,并且是特定于平台的, QueryPerformanceCounter (WinAPI) 似乎是可行的方法,但它是特定于平台的, C++11 high_resolution_clock 工作正常,但它是新标准的一部分。

我的问题主要是:从事科学计算的人是如何做到这一点的,为什么要这样做?而且,clock 的行为是我的标准库实现中的错误还是太流行的误解?

编辑: 小解释:我对使用 C++11 有点犹豫,因为我可能会在带有一些旧软件的集群上运行我的代码。

【问题讨论】:

W.r.t 新标准和high_resolution_clock 是与 C++03 兼容所需的代码吗? 你也可以看看 boost::chrono,它为当前可用的任何东西提供了一个方便的包装器。 对,我实际上已经查看了 boost::chrono,发现对于 Windows,它实际上使用了 QueryPerformanceCounter 【参考方案1】:

直接复制自我目前的研究项目:

#include <chrono>
#include <type_traits>

/** @brief Best available clock. */
using clock_type = typename std::conditional<
  std::chrono::high_resolution_clock::is_steady,
  std::chrono::high_resolution_clock,
  std::chrono::steady_clock>::type;

为了公平起见,我们希望衡量挂墙时间,而不是用户空间 CPU 周期,同时还要考虑多线程开销。不幸的是,许多实现将high_resolution_clock 定义为real_time_clock 的别名,如果在我们测量期间调整系统时间,这会破坏我们的结果。

是的,std::chrono 是 C++11 的一项功能,但如果这是您所说的研究,那么是什么阻止您使用最现代的编译器?您不需要在客户某个尘土飞扬的地下室某处可能存在的最奇怪的平台上编译您的代码。无论如何,如果你不能拥有 C++11,你可以自己轻松地实现这些时钟。它们(至少在 GNU libstdc++ 中)只是 clock_gettime 的薄包装。

【讨论】:

在此类型开关上:通常high_resolution_clocksystem_clocksteady_clock 的类型定义。因此,如果is_steady 部分为真,则要跟踪std::conditional,然后选择high_resolution_clock,它是steady_clock 的(类型定义)。如果它是假的,那么你再次选择steady_clock。从一开始就使用steady_clock ... @NikosAthanasiou 虽然这可能是“通常”的情况,但标准并没有强制要求。 std::chrono::system,steady,high_resolution_clock可以实现为三个不同的时钟。这并不是说steady_clock 在实践中不是一个不错的选择。 注意,您还应该为您和您的代码的用户找到一种方法,以避免不可移植地混合不同时钟的时间点(如果这种类型的开关获得了意义,它的行为会有所不同在不同的平台上)【参考方案2】:

你没有提到boost::chrono。与 C++11 chrono 相同,但适用于 C++03 编译器。

另外,我无法理解您对 C++11 的犹豫。我们快到 2015 年了,C++11 并不是那么新。它甚至不是最新的标准。所以,#include &lt;chrono&gt; 是一条路。

但是请注意,chrono 在 Visual Studio 2013 标准库实现中有些损坏。我个人在任何地方都使用std::chrono,并通过条件definestypedefs 将其交换为boost::chrono。希望他们能在 Visual Studio Next 中修复它。

【讨论】:

哦,是的,Boost 可能是比自己进行系统调用更好的选择。至少如果 Boost 已经是您项目的依赖项。 @5gon12eder 够公平的。更糟糕。实际上,要使用 boost,您需要两个已编译的库:boost_chronoboost_system。不过,如果我们谈论的是 C++03 的跨平台线程,我们可能已经将 boost::threadboost::system 作为依赖项,所以 boost::chrono 非常适合这里。

以上是关于在多线程 C++ 应用程序中测量时间的主要内容,如果未能解决你的问题,请参考以下文章

为啥在多线程应用程序 C++ 中没有发生同步

在多线程 C++ 程序中使用 std::vector 时应用程序崩溃

动态内存分配的线程争用

在多线程应用程序中使用 opencv waitKey()

gdb:在多线程程序中调用函数而不进行线程

在多线程 C++ 中捕获进程的输出