层次计时器
(类来自 pyomo.common.timing)
- class pyomo.common.timing.HierarchicalTimer[source]
基础类:
object一个用于收集和显示分层计时信息的类
在实现具有嵌套子程序的迭代算法(例如优化求解器)时,我们通常希望知道每个子程序所花费的累计时间以及该时间占调用程序所花费时间的比例。此类收集用户指定键的计时信息,这些信息在计时器对象的生命周期内累积,并保留计时类别的层次(嵌套)结构。
示例
>>> import time >>> from pyomo.common.timing import HierarchicalTimer >>> timer = HierarchicalTimer() >>> timer.start('all') >>> time.sleep(0.2) >>> for i in range(10): ... timer.start('a') ... time.sleep(0.1) ... for i in range(5): ... timer.start('aa') ... time.sleep(0.01) ... timer.stop('aa') ... timer.start('ab') ... timer.stop('ab') ... timer.stop('a') ... >>> for i in range(10): ... timer.start('b') ... time.sleep(0.02) ... timer.stop('b') ... >>> timer.stop('all') >>> print(timer) Identifier ncalls cumtime percall % --------------------------------------------------- all 1 2.248 2.248 100.0 ---------------------------------------------- a 10 1.787 0.179 79.5 ----------------------------------------- aa 50 0.733 0.015 41.0 ab 10 0.000 0.000 0.0 other n/a 1.055 n/a 59.0 ========================================= b 10 0.248 0.025 11.0 other n/a 0.213 n/a 9.5 ============================================== ===================================================
列包括:
- ncalls
计时器启动和停止的次数
- cumtime
计时器处于活动状态(已启动但未停止)的累计时间(以秒为单位)
- percall
累计时间(以秒为单位)/ 调用次数
- “%”
这是计时器的累计时间除以父计时器的累计时间乘以100
>>> print('a total time: %f' % timer.get_total_time('all.a')) a total time: 1.902037 >>> print('ab num calls: %d' % timer.get_num_calls('all.a.ab')) ab num calls: 10 >>> print('aa %% time: %f' % timer.get_relative_percent_time('all.a.aa')) aa % time: 44.144148 >>> print('aa %% total: %f' % timer.get_total_percent_time('all.a.aa')) aa % total: 35.976058
在实现算法时,收集详细的层次化时间信息通常很有用。然而,在传达时间配置文件时,通常最好只保留最相关的信息,并以扁平化的数据结构呈现。在下面的示例中,假设我们想要比较在
"c"和"f"子程序中花费的时间。我们希望生成一个时间配置文件,仅显示在这两个子程序中花费的时间,并以扁平化的结构呈现,以便于比较。为此,我们忽略对于此比较不必要的
"c"和"f"的子程序展平分层的时间信息
消除所有我们不关心的信息
>>> import time >>> from pyomo.common.timing import HierarchicalTimer >>> timer = HierarchicalTimer() >>> timer.start("root") >>> timer.start("a") >>> time.sleep(0.01) >>> timer.start("b") >>> timer.start("c") >>> time.sleep(0.1) >>> timer.stop("c") >>> timer.stop("b") >>> timer.stop("a") >>> timer.start("d") >>> timer.start("e") >>> time.sleep(0.01) >>> timer.start("f") >>> time.sleep(0.05) >>> timer.stop("f") >>> timer.start("c") >>> timer.start("g") >>> timer.start("h") >>> time.sleep(0.1) >>> timer.stop("h") >>> timer.stop("g") >>> timer.stop("c") >>> timer.stop("e") >>> timer.stop("d") >>> timer.stop("root") >>> print(timer) Identifier ncalls cumtime percall % ------------------------------------------------------------------ root 1 0.290 0.290 100.0 ------------------------------------------------------------- a 1 0.118 0.118 40.5 -------------------------------------------------------- b 1 0.105 0.105 89.4 --------------------------------------------------- c 1 0.105 0.105 100.0 other n/a 0.000 n/a 0.0 =================================================== other n/a 0.013 n/a 10.6 ======================================================== d 1 0.173 0.173 59.5 -------------------------------------------------------- e 1 0.173 0.173 100.0 --------------------------------------------------- c 1 0.105 0.105 60.9 ---------------------------------------------- g 1 0.105 0.105 100.0 ----------------------------------------- h 1 0.105 0.105 100.0 other n/a 0.000 n/a 0.0 ========================================= other n/a 0.000 n/a 0.0 ============================================== f 1 0.055 0.055 31.9 other n/a 0.013 n/a 7.3 =================================================== other n/a 0.000 n/a 0.0 ======================================================== other n/a 0.000 n/a 0.0 ============================================================= ================================================================== >>> # Clear subroutines under "c" that we don't care about >>> timer.timers["root"].timers["d"].timers["e"].timers["c"].timers.clear() >>> # Flatten hierarchy >>> timer.timers["root"].flatten() >>> # Clear except for the subroutines we care about >>> timer.timers["root"].clear_except("c", "f") >>> print(timer) Identifier ncalls cumtime percall % ---------------------------------------------- root 1 0.290 0.290 100.0 ----------------------------------------- c 2 0.210 0.105 72.4 f 1 0.055 0.055 19.0 other n/a 0.025 n/a 8.7 ========================================= ==============================================
注释
HierarchicalTimer使用堆栈来跟踪在任何时间点哪些计时器是活动的。此外,每个计时器都有一个用于其子计时器的计时器字典。考虑>>> timer = HierarchicalTimer() >>> timer.start('all') >>> timer.start('a') >>> timer.start('aa')
上述代码运行后,
timer.stack将会是['all', 'a', 'aa']并且timer.timers将会有一个键,'all'和一个值,该值将会是一个_HierarchicalHelper。这个_HierarchicalHelper有它自己的计时器字典:{'a': _HierarchicalHelper}等等。这样,我们就可以像访问堆栈一样轻松地访问任何计时器。逻辑是递归的(尽管代码不是)。
方法
__init__()clear_except(*args)修剪所有“子计时器”,除了指定的那些
flatten()将HierarchicalTimer扁平化,将所有计时类别移动到单一层级
get_num_calls(identifier)get_relative_percent_time(identifier)get_total_percent_time(identifier)get_total_time(identifier)reset()完全重置计时器。
start(identifier)开始递增由标识符标识的计时器
stop(identifier)停止递增由标识符标识的计时器
成员文档
- flatten()[source]
将HierarchicalTimer扁平化,将所有计时类别移动到单一层级
如果移动到同一级别的任何计时器具有相同的标识符,
total_time和n_calls字段将被加在一起。 “向上移动”的“子计时器”的total_time将从该计时器原始父级的total_time中减去。