基准测试工具 - torch.utils.benchmark¶
- 类 torch.utils.benchmark 中。Timer(stmt='pass', setup='pass', global_setup='', timer=<内置函数 perf_counter>, globals=无, label=无, sub_label=无, description=无, env=None, num_threads=1, language=Language.PYTHON)[来源]¶
用于测量 PyTorch 语句执行时间的帮助程序类。
有关如何使用此类的完整教程,请参阅:https://pytorch.org/tutorials/recipes/recipes/benchmark.html
PyTorch 计时器基于 timeit。Timer 的 Timer (实际上使用 timeit.Timer 内部),但有几个关键区别:
- 运行时感知:
Timer 将执行预热(因为 PyTorch 的某些元素很重要 lazily initialized),请设置 ThreadPool 大小,以便比较为 apples-to-apples,并在 必要。
- 专注于仿行:
在测量代码时,尤其是复杂的内核/模型时, 运行间差异是一个重要的混杂因素。是的 预期所有测量都应包括要量化的重复 noise 并允许中位数计算,这比 mean 更稳健。 为此,该类与 timeit API 的差异 从概念上合并 Timeit。Timer.repeat 和 timeit 的 Timer.Repeat。Timer.autorange 的 Timer.autorange 命令。 (确切的算法在 method docstrings中讨论.)timeit 方法在自适应策略不是 期望。
- 可选元数据:
定义 Timer 时,可以选择指定 label、sub_label、description 和 env。(稍后定义)这些字段包含在 结果对象的表示形式,并通过 Compare 类组 并显示结果以进行比较。
- 指令计数
除了实际时间之外,Timer 还可以在 Callgrind 下运行语句 并报告执行的指令。
直接类似于 timeit。计时器构造函数参数:
stmt, 设置, 计时器, 全局变量
PyTorch Timer 特定的构造函数参数:
标签、sub_label、描述、环境num_threads
- 参数
stmt (str) – 要在循环中运行并定时的代码片段。
setup (str) – 可选的设置代码。用于定义 stmt 中使用的变量
global_setup (str) –(仅限 C++) code 中,该代码位于文件的顶层,用于 #include 语句等内容。
timer (Callable[[], float]) - 可调用,返回当前时间。如果构建了 PyTorch 如果没有 CUDA 或不存在 GPU,则默认为 timeit.default_timer;否则它会在 测量时间。
globals (Optional[Dict[str, Any]]) – 定义 stmt 时全局变量的字典 执行。这是提供 stmt 需要的变量的另一种方法。
label (Optional[str]) – 总结 stmt 的字符串。例如,如果 stmt 为 “torch.nn.functional.relu(torch.add(x, 1, out=out))” 可以将 label 设置为 “ReLU(x + 1)” 以提高可读性。
提供补充信息以消除测量的歧义 具有相同的 stmt 或标签。例如,在我们的示例中 上面的 sub_label 可能是 “float” 或 “int”,因此很容易 要区分: “ReLU(x + 1):(浮点型)”
“ReLU(x + 1): (int)” 打印测量值或使用 Compare 进行汇总时。
String 来区分具有相同标签的测量值,以及 sub_label。description 的主要用途是向 Compare the columns of data 发出信号。例如,人们可能会设置它 根据 Input size 创建表单的表:
| n=1 | n=4 | ... ------------- ... ReLU(x + 1): (float) | ... | ... | ... ReLU(x + 1): (int) | ... | ... | ...
使用 Compare。打印 Measurement 时也包含此 Measurement。
env (Optional[str]) – 此标签表示在 不同的环境,因此不等效,因为 实例。比较 will 将具有不同环境规范的测量视为 distinct 合并复制运行时。
num_threads (int) – 执行 stmt 时 PyTorch 线程池的大小。单 线程性能很重要,因为它既是关键的推理工作负载 以及内在算法效率的良好指标,因此 default 设置为 1。这与默认的 PyTorch 形成对比 threadpool 大小,该大小尝试利用所有核心。
- adaptive_autorange(阈值=0.1, *, min_run_time=0.01, max_run_time=10.0, callback=None)[来源]¶
与 blocked_autorange 类似,但也检查测量中的变异性 并重复,直到 IQR/中位数小于阈值或达到 max_run_time。
概括地说,adaptive_autorange 执行以下伪代码:
`setup` times = [] while times.sum < max_run_time start = timer() for _ in range(block_size): `stmt` times.append(timer() - start) enough_data = len(times)>3 and times.sum > min_run_time small_iqr=times.iqr/times.mean<threshold if enough_data and small_iqr: break
- blocked_autorange(callback=None, min_run_time=0.2)[来源]¶
测量多个仿行,同时将计时器开销保持在最低限度。
概括地说,blocked_autorange 执行以下伪代码:
`setup` total_time = 0 while total_time < min_run_time start = timer() for _ in range(block_size): `stmt` total_time += (timer() - start)
请注意内部循环中的变量 block_size。块的选择 尺寸对于测量质量很重要,并且必须平衡两者 竞争目标:
小块大小会导致更多的重复,并且通常 更好的统计数据。
较大的区块大小可以更好地分摊 timer 调用的成本,并减少测量的偏差。这是 重要,因为 CUDA 同步时间非同小可 (订单个位数到低两位数微秒)并且会 否则会使测量产生偏差。
blocked_autorange 通过运行预热期来设置block_size, 增加区块大小,直到计时器开销小于 整体计算。然后,此值将用于 main 测量循环。
- 返回
一个 Measurement 对象,其中包含测得的运行时间 repetition 计数,并可用于计算统计信息。 (平均值、中位数等)
- 返回类型
- collect_callgrind(number: int, *, repeats: None, collect_baseline: bool, retain_out_file: bool) CallgrindStats [来源]¶
- collect_callgrind(number: int, *, repeats: int, collect_baseline: bool, retain_out_file: bool) Tuple[CallgrindStats, ...]
使用 Callgrind 收集指令计数。
与实际时间不同,指令计数是确定性的 (程序本身中的模非确定性和少量 来自 Python 解释器的抖动。这使它们成为详细 性能分析。此方法在单独的进程中运行 stmt 以便 Valgrind 可以检测该程序。性能严重 由于检测而降低,但通过以下方式改善 事实上,少量迭代通常足以 获得良好的测量结果。
要使用这种方法,必须安装 valgrind、callgrind_control 和 callgrind_annotate。
因为调用方 (this process) 之间存在进程边界 和 stmt 执行时,全局变量不能包含任意内存中的 数据结构。(与计时方法不同)相反,全局变量是 仅限于 builtins, nn.模块和 TorchScripted 函数/模块 减少序列化和后续的意外因素 反序列化。GlobalsBridge 类提供了有关此的更多详细信息 主题。请特别小心 nn.模块:它们依赖于 pickle 和 您可能需要将 Import 添加到 Setup 中,以便它们正确传输。
默认情况下,将收集空语句的配置文件,并且 cached 来指示有多少条指令来自 Python 循环,其中 驱动器 stmt。
- 返回
一个 CallgrindStats 对象,它提供指令计数和 一些用于分析和操作结果的基本功能。
- timeit(number=1000000)[来源]¶
镜像 timeit 的语义。Timer.timeit() 的 Timer.timeit() 中。
执行 main 语句 (stmt) 次数。https://docs.python.org/3/library/timeit.html#timeit.Timer.timeit
- 返回类型
- 类 torch.utils.benchmark 中。测量(number_per_run, raw_times, task_spec, metadata=None)[来源]¶
Timer 测量的结果。
此类存储给定语句的一个或多个度量值。是的 serializable 并提供了多种便捷的方法 (包括详细的__repr__)为下游使用者提供服务。
- 类 torch.utils.benchmark 中。CallgrindStats(task_spec、number_per_run、built_with_debug_symbols、baseline_inclusive_stats、baseline_exclusive_stats、stmt_inclusive_stats、stmt_exclusive_stats stmt_callgrind_out)[来源]¶
Timer 收集的 Callgrind 结果的顶级容器。
操作通常使用 FunctionCounts 类完成,该类是 通过调用 CallgrindStats.stats(...) 获得。几大便利 还提供了方法;最重要的是 CallgrindStats.as_standardized()。
- as_standardized()[来源]¶
从函数字符串中删除库名称和一些前缀。
当比较两组不同的指令计数时,在 stumbling block 可以是路径前缀。Callgrind 包含完整的文件路径 在报告函数时(应该这样做)。但是,这可能会导致 比较配置文件时的问题。如果 Python 等关键组件 或 PyTorch 构建在两个配置文件中的不同位置,其中 可能会导致类似于以下内容:
23234231 /tmp/first_build_dir/thing.c:foo(...) 9823794 /tmp/first_build_dir/thing.c:bar(...) ... 53453 .../aten/src/Aten/...:function_that_actually_changed(...) ... -9823794 /tmp/second_build_dir/thing.c:bar(...) -23234231 /tmp/second_build_dir/thing.c:foo(...)
剥离前缀可以通过规范化 字符串,并更好地取消等效调用站点 当 diffing 时。
- 返回类型
- 类 torch.utils.benchmark 中。FunctionCounts(_data,含,truncate_rows=True,_linewidth=None)[来源]¶
用于操作 Callgrind 结果的容器。
- 它支持:
加法和减法以合并或比较结果。
类似元组的索引。
一个降噪函数,用于去除已知的 CPython 调用 是非确定性的,而且相当嘈杂。
用于自定义的两种高阶方法(filter 和 transform) 操纵。
- 类 torch.utils.benchmark 中。比较(结果)[来源]¶
Helper 类,用于在 格式化表。
表格格式基于 (描述、标签、sub_label、num_threads 等)中
提供的信息字段。
有关如何使用此类的完整教程,请参阅:https://pytorch.org/tutorials/recipes/recipes/benchmark.html
- 参数
results (List[Measurement]) – 要显示的测量列表。