如何估计c++程序中的性能单元

how to estimate a performance unit in a c++ program

本文关键字:性能 单元 程序 何估计 c++      更新时间:2023-10-16

我的意思是,为了衡量某些算法的性能,我需要用一些单位来衡量。所以,基本上,如果我忽略对象的声明和定义,只考虑操作,你会如何估计每个操作在运行时消耗的时间?。

c++11中有std::chrono库(请参阅std::chrono)。否则,您可以使用boost::chrono(请参阅boost::chrono)。这2个是非常基本的时间测量库,您可以从中开始。

EDIT:在c++0x中,您有clock()函数,但正如注释部分所述,这不是一个非常准确的测量值。此外,大多数平台还为时间相关操作提供某种API。

如何衡量绩效取决于环境。首先,您需要比较足够大和足够多样化的样本数据的性能。足够大意味着它至少可以在几秒钟内测量。足够多样化意味着它可以统一地或单独地覆盖所有运行场景的重复(您至少应该知道样本数据代表什么)。

对于足够简单的情况,您要做的第一件事是将算法划分为尽可能多的段,让我们称之为A_1,...,A_N(或者A_1...A_N是同一问题的不同解决方案,这个概念仍然适用)。您要做的是在相同的样本数据上测量每个分区所花费的时间。在伪代码中:

times <- (0,...,0) //vector of size N
for each input in sample data:
    start = now()
    //Run A_1 on input
    end = now()
    times[1] <- times[1] + (end-start)
    ...
    ...
    ...
    start = now()
    //Run A_N on input
    end = now()
    times[N] <- times[N] + (end-start)

在这次运行结束时,您会得到一个时间向量,它显示您在每个元素上花费了多少时间这是最基本的方法。但剖析的关键要素是:剖析青蛙有很多方法。您还可以查看您在一个特定操作上花费了多少时间,该操作可以从算法的许多分区调用。你可以选择查看加载/存储操作的数量、缓存性能等。变化很多,巨大的回报往往来自意想不到的来源(至少对粗心的观察者来说是这样)。

对于更高级的评测,您可以使用第三方评测框架(一些IDE具有内置的评测功能)。

在现代机器上,它在很大程度上取决于上下文。大多数指令将在单个时钟中执行;在一些机器上,每个时钟甚至可以得到几个指令。另一方面,内存访问时间可能会有很大差异,这取决于访问的位置是在缓存中、在主内存中还是交换出去;如果操作系统必须访问磁盘才能映射内存,那么访问时间是毫秒,就好像数据在顶级缓存中一样,它几乎是即时的。(换句话说,我们谈论的是100皮秒,而不是10毫秒。)这就是为什么你会听到这么多关于局部性的消息。

衡量性能的方法有很多,"正确"的方法在很大程度上取决于您实际在做什么。通常,确定性能的简单方法只是让应用程序做它通常做的事情,然后测量时间——如果时间足够长,只需使用秒表(例如手机应用程序、实际手表上的功能或类似功能)就可以了。对于较短的时间段,您可能需要其他方法——一直到使用"CPU时钟周期"和CPU本身的"TSC"时间戳计数器。

如果它只需要很短的时间,但你的应用程序会做很多,那么多次运行相同的代码。

对于其他应用程序,因为所花费的时间并不是真正用于使用CPU时钟周期,所以会变得更困难——例如,如果应用程序的一部分正在读取某个大文件,那么所使用的CPU时间可能只有2-3%,其余时间则用于等待硬盘从其中的实际磁盘中获取数据。

如果应用程序使用网络,那么CPU可能只使用1GB网络链路上发送数据包所需时间的百分之几。

数据的类型以及数据的组织、排序和使用方式也很重要。如果从已经排序的源中插入要排序的内容,它的执行方式可能与未排序的项目列表完全不同——令人惊讶的是,它可能更好,也可能更差,这取决于数据的存储/排序方式。

"查看代码"并确定其性能可能相当困难。除了"代码看起来像什么"之外,还有很多其他因素会影响它

如果您有一个可用的现有应用程序,那么衡量它的性能,并使用评测软件来查看在哪里花费了多少时间是一个好的计划。

所有这些答案的测量都取决于运行算法的硬件。如果你想对算法的复杂程度进行通用测量,你应该执行大O和大Omega分析。

如果你对此有更多的问题,请告诉我,但根据你的问题标题,你应该寻找算法执行的指令数量,作为其数据输入的函数,而不是基于特定硬件来衡量性能。