层次计时器

(类来自 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"子程序中花费的时间。我们希望生成一个时间配置文件,仅显示在这两个子程序中花费的时间,并以扁平化的结构呈现,以便于比较。为此,我们

  1. 忽略对于此比较不必要的"c""f"的子程序

  2. 展平分层的时间信息

  3. 消除所有我们不关心的信息

>>> 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__()[source]

方法

__init__()

clear_except(*args)

修剪所有“子计时器”,除了指定的那些

flatten()

将HierarchicalTimer扁平化,将所有计时类别移动到单一层级

get_num_calls(identifier)

get_relative_percent_time(identifier)

get_timers()

get_total_percent_time(identifier)

get_total_time(identifier)

reset()

完全重置计时器。

start(identifier)

开始递增由标识符标识的计时器

stop(identifier)

停止递增由标识符标识的计时器

成员文档

clear_except(*args)[source]

修剪所有“子计时器”,除了指定的那些

Parameters:

args (str) – 将被保留的键

flatten()[source]

将HierarchicalTimer扁平化,将所有计时类别移动到单一层级

如果移动到同一级别的任何计时器具有相同的标识符, total_timen_calls 字段将被加在一起。 “向上移动”的“子计时器”的 total_time 将从该计时器原始父级的 total_time 中减去。

get_num_calls(identifier)[source]
Parameters:

identifier (str) – 计时器的全名,包括用点分隔的父计时器。

Returns:

n_calls – 指定计时器调用 start 的次数。

Return type:

int

get_relative_percent_time(identifier)[source]
Parameters:

identifier (str) – 计时器的全名,包括用点分隔的父计时器。

Returns:

percent_time – 指定计时器相对于其直接父计时器所花费的时间百分比。

Return type:

float

get_timers()[source]
Returns:

identifiers – 返回所有计时器标识符的列表

Return type:

liststr

get_total_percent_time(identifier)[source]
Parameters:

identifier (str) – 计时器的全名,包括用点分隔的父计时器。

Returns:

percent_time – 在指定计时器中花费的时间相对于所有计时器总时间的百分比。

Return type:

float

get_total_time(identifier)[source]
Parameters:

identifier (str) – 计时器的全名,包括用点分隔的父计时器。

Returns:

total_time – 指定计时器激活时花费的总时间。

Return type:

float

reset()[source]

完全重置计时器。

start(identifier)[source]

开始递增由标识符标识的计时器

Parameters:

identifier (str) – 计时器的名称

stop(identifier)[source]

停止递增由标识符标识的计时器

Parameters:

identifier (str) – 计时器的名称