目录

整体痕量分析简介

创建时间: 2024 年 1 月 2 日 |上次更新时间: 2024 年 1 月 5 日 |上次验证: Nov 05, 2024

作者: Anupam Bhatnagar

在本教程中,我们将演示如何使用 Holistic Trace Analysis (HTA) 分析来自分布式训练作业的跟踪。要开始使用,请按照以下步骤操作 下面。

安装 HTA

我们建议使用 Conda 环境安装 HTA。要安装 Anaconda,请参阅 Anaconda 官方文档

  1. 使用 pip 安装 HTA:

    pip install HolisticTraceAnalysis
    
  2. (可选和推荐)设置 Conda 环境:

    # create the environment env_name
    conda create -n env_name
    
    # activate the environment
    conda activate env_name
    
    # When you are done, deactivate the environment by running ``conda deactivate``
    

开始

启动 Jupyter 笔记本并将变量设置为跟踪的位置。trace_dir

from hta.trace_analysis import TraceAnalysis
trace_dir = "/path/to/folder/with/traces"
analyzer = TraceAnalysis(trace_dir=trace_dir)

时间划分

为了有效利用 GPU,了解它们的支出方式至关重要 特定作业的时间。他们主要从事计算、通信、 memory 事件,还是它们处于空闲状态?时间细分功能提供了详细的 分析在这三个类别中花费的时间。

  • 空闲时间 - GPU 处于空闲状态。

  • 计算时间 - GPU 用于矩阵乘法或向量运算。

  • 非计算时间 - GPU 用于通信或内存事件。

为了实现高训练效率,代码应最大限度地利用计算时间,并且 最大限度地减少空闲时间和非计算时间。以下函数生成一个 dataframe 提供每个等级的临时使用情况的详细细分。

analyzer = TraceAnalysis(trace_dir = "/path/to/trace/folder")
time_spent_df = analyzer.get_temporal_breakdown()
../_images/temporal_breakdown_df.png

当参数在 get_temporal_breakdown 函数中设置为 时,它还会生成一个条形图,表示按排名划分的划分。visualizeTrue

../_images/temporal_breakdown_plot.png

空闲时间细分

深入了解 GPU 空闲的时间量,以及 其背后的原因可以帮助指导优化策略。GPU 是 当没有内核运行时,被视为 idle。我们开发了一种 算法将空闲时间分为三个不同的类别:

  • 主机等待:指 GPU 上的空闲时间,由 CPU 没有足够快地将内核排队以保持 GPU 得到充分利用。 这些类型的低效率可以通过检查 CPU 来解决 导致速度变慢的 Operator,增加 Batch 大小并应用 Operator Fusion。

  • 内核等待:这是指与启动相关的短暂开销 连续的内核。归属于此类别的空闲时间 可以通过使用 CUDA 图形优化来最小化。

  • 其他等待:此类别包括当前无法的空闲时间 由于信息不足而被归因。可能的原因包括 使用 CUDA 事件和 CUDA 流之间的同步和启动延迟 内核。

主机等待时间可以解释为 GPU 因 GPU 而停止的时间 添加到 CPU。要将空闲时间归因于内核等待,我们使用以下命令 启发式:

连续内核之间的差距 < 阈值

默认阈值为 30 纳秒,可以使用 参数进行配置。默认情况下,空闲时间细分为 仅针对排名 0 计算。为了计算其他等级的细分, 在 get_idle_time_breakdown 函数中使用参数。空闲时间细分可以按如下方式生成:consecutive_kernel_delayranks

analyzer = TraceAnalysis(trace_dir = "/path/to/trace/folder")
idle_time_df = analyzer.get_idle_time_breakdown()
../_images/idle_time_breakdown_percentage.png

该函数返回一个 DataFrame 元组。第一个 DataFrame 包含 每个排名的每个流上按类别划分的空闲时间。

../_images/idle_time.png

当设置为 时,将生成第二个 DataFrame。它包含每个流的空闲时间的摘要统计信息 在每个等级上。show_idle_interval_statsTrue

../_images/idle_time_summary.png

提示

默认情况下,空闲时间细分显示每个 空闲时间类别。将参数设置为 , 该函数在 y 轴上使用绝对时间进行渲染。visualize_pctgFalse

内核分解

内核细分功能会细分每种内核类型所花费的时间。 例如通信 (COMM)、计算 (COMP) 和内存 (MEM),跨越所有 对每个类别中花费的时间比例进行排名和显示。这是 以饼图形式显示的每个类别中逗留的时间百分比:

../_images/kernel_type_breakdown.png

内核细分可以按以下方式计算:

analyzer = TraceAnalysis(trace_dir = "/path/to/trace/folder")
kernel_type_metrics_df, kernel_metrics_df = analyzer.get_gpu_kernel_breakdown()

该函数返回的第一个 DataFrame 包含用于 生成饼图。

内核持续时间分布

get_gpu_kernel_breakdown 返回的第二个 DataFrame 包含每个内核的持续时间摘要统计信息。特别是,此 包括 Count (计数)、 Min(最小值)、Max(最大值)、Average(平均值)、Standard Deviation(标准差)、Sum (总和) 和 Kernel 类型(kernel type) 对于每个等级上的每个内核。

../_images/kernel_metrics_df.png

使用这些数据,HTA 可以创建许多可视化来识别性能 瓶颈。

  1. 每个等级的每种内核类型的顶级内核的饼图。

  2. 每个排名靠前的所有等级的平均持续时间的条形图 kernels 和每种 kernel type 的 Kernel。

../_images/pie_charts.png

提示

所有图像均使用 plotly 生成。将鼠标悬停在图表上会显示 模式栏,允许用户缩放、平移、选择和 下载图表。

上面的饼图显示了前 5 个计算、通信和内存 内核。将为每个等级生成类似的饼图。饼图可以是 配置为使用传递的参数显示前 k 个内核 添加到get_gpu_kernel_breakdown函数。此外,该参数可用于调整 需要分析。如果 和 都是 指定,则优先。num_kernelsduration_rationum_kernelsduration_rationum_kernels

../_images/comm_across_ranks.png

上面的条形图显示了 NCCL AllReduce 内核的平均持续时间 在所有级别中。黑线表示最小和最长时间 在每个等级上。

警告

使用 jupyter-lab 时,将 “image_renderer” 参数值设置为 “jupyterlab”,否则图形将不会在 Notebook 中呈现。

有关此功能的详细演练,请参阅 gpu_kernel_breakdown notebook 的 Notebook 中。

通信计算重叠

在分布式训练中,大量时间花在通信上 以及 GPU 之间的同步事件。要实现高 GPU 效率(例如 TFLOPS/GPU),保持 GPU 与计算的超额订阅至关重要 内核。换句话说,不应因未解析的数据而阻塞 GPU 依赖。一种衡量计算被 数据依赖性是计算通信计算重叠。高等 如果通信事件与计算事件重叠,则会观察到 GPU 效率。 缺乏通信和计算重叠会导致 GPU 空闲, 导致效率低下。 总而言之,更高的通信计算重叠是可取的。要计算 对于每个等级的重叠百分比,我们衡量以下比率:

(通信时计算所花费的时间)/(通信所花费的时间)

通信计算重叠可以按以下方式计算:

analyzer = TraceAnalysis(trace_dir = "/path/to/trace/folder")
overlap_df = analyzer.get_comm_comp_overlap()

该函数返回一个包含重叠百分比的数据帧 对于每个等级。

../_images/overlap_df.png

当参数设置为 True 时,get_comm_comp_overlap 函数还会生成一个条形图,表示按排名划分的重叠。visualize

../_images/overlap_plot.png

增强计数器

内存带宽和队列长度计数器

内存带宽计数器测量复制时使用的内存复制带宽 通过内存复制 (memcpy) 和内存集 (memset) 从 H2D、D2H 和 D2D 获取数据 事件。HTA 还会计算每个 CUDA 上未完成操作的数量 流。我们将其称为队列长度。当流上的队列长度 为 1024 或更大,则无法在该流上安排新事件,并且 CPU 将停止,直到 GPU 流上的事件处理完毕。

generate_trace_with_counters API 会输出一个新的跟踪文件,其中包含内存带宽和队列长度 计数器。新的跟踪文件包含指示内存的 track memcpy/memset 操作使用的带宽,并跟踪队列长度 每个流。默认情况下,这些计数器是使用秩 0 生成的 trace 文件,并且新文件的名称中包含后缀。 用户可以选择使用 API 中的参数为多个排名生成计数器。_with_countersranksgenerate_trace_with_counters

analyzer = TraceAnalysis(trace_dir = "/path/to/trace/folder")
analyzer.generate_trace_with_counters()

带有增强计数器的生成的跟踪文件的屏幕截图。

../_images/mem_bandwidth_queue_length.png

HTA 还提供内存复制带宽和队列长度的摘要 counters 以及 profiled 部分的 counter 的时间序列 使用以下 API 的代码:

要查看摘要和时间序列,请使用:

# generate summary
mem_bw_summary = analyzer.get_memory_bw_summary()
queue_len_summary = analyzer.get_queue_length_summary()

# get time series
mem_bw_series = analyzer.get_memory_bw_time_series()
queue_len_series = analyzer.get_queue_length_series()

摘要包含计数、最小值、最大值、平均值、标准差、第 25 个、第 50 个、 和第 75 个百分位数。

../_images/queue_length_summary.png

时间序列仅包含值更改时的点。一旦值为 观察到的时间序列保持不变,直到下一次更新。内存 bandwidth 和 queue length 时间序列函数返回一个字典,其键 是排名,值是该排名的时间序列。默认情况下, 时间序列仅针对排名 0 进行计算。

CUDA 内核启动统计

../_images/cuda_kernel_launch.png

对于在 GPU 上启动的每个事件,在 CPU,例如 、 、 。 这些事件通过跟踪中的通用相关 ID 链接 - 请参阅图 以上。此功能计算 CPU 运行时事件的持续时间,即其对应的 GPU 内核和启动延迟,例如 GPU 内核启动和 CPU 运算符结尾。内核启动信息可以按如下方式生成:CudaLaunchKernelCudaMemcpyAsyncCudaMemsetAsync

analyzer = TraceAnalysis(trace_dir="/path/to/trace/dir")
kernel_info_df = analyzer.get_cuda_kernel_launch_stats()

下面给出了生成的 DataFrame 的屏幕截图。

../_images/cuda_kernel_launch_stats.png

CPU op 的持续时间、GPU 内核和启动延迟允许我们找到 以下内容:

  • 短 GPU 内核 - 持续时间小于相应 CPU 运行时事件。

  • 运行时事件异常值 - 持续时间过长的 CPU 运行时事件。

  • Launch delay outliers (启动延迟异常值) - 计划时间过长的 GPU 内核。

HTA 为上述三个类别中的每一个类别生成分布图。

短 GPU 内核

通常,CPU 端的启动时间范围为 5-20 微秒。在一些 的情况下,GPU 执行时间低于启动时间本身。图表 下面可以帮助我们找到此类实例在代码中出现的频率。

../_images/short_gpu_kernels.png

运行时事件离群值

运行时异常值取决于用于对异常值进行分类的截止值,因此 get_cuda_kernel_launch_stats API 提供用于配置值的参数。runtime_cutoff

../_images/runtime_outliers.png

启动延迟异常值

启动延迟异常值取决于用于对异常值进行分类的截止值。 因此,get_cuda_kernel_launch_stats API 提供了用于配置值的参数。launch_delay_cutoff

../_images/launch_delay_outliers.png

结论

在本教程中,您学习了如何安装和使用 HTA、 一种性能工具,使您能够分析分布式 训练工作流。了解如何使用 HTA 工具执行跟踪 diff 分析,请参阅使用 Holistic Trace Analysis 进行 Trace Diff

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

获取面向初学者和高级开发人员的深入教程

查看教程

资源

查找开发资源并解答您的问题

查看资源