此页面由 Cloud Translation API 翻译。
Switch to English

使用事件探查器优化TensorFlow性能

使用Profiler随附的工具来跟踪TensorFlow模型的性能。查看模型在主机(CPU),设备(GPU)或主机与设备的组合上的性能。

分析可以帮助您了解模型中各种TensorFlow操作(ops)的硬件资源消耗(时间和内存),并解决性能瓶颈,最终使模型执行更快。

本指南将引导您逐步了解如何安装Profiler,可用的各种工具,Profiler收集性能数据的方式不同,以及一些建议的最佳实践以优化模型性能。

如果要在Cloud TPU上分析模型性能,请参考Cloud TPU指南

安装Profiler和GPU必备组件

通过从GitHub存储库下载并运行install_and_run.py脚本来安装Profiler。

要在GPU上进行分析,您必须:

  1. 安装CUDA®Toolkit 10.1或更高版本。 CUDA®Toolkit 10.1仅支持单个GPU配置文件。要配置多个GPU,请参阅配置多个GPU 。确保您安装的CUDA®驱动程序版本对于Linux至少为440.33,对于Windows至少为441.22。
  2. 确保路径上存在CUPTI:
 /sbin/ldconfig -N -v $(sed 's/:/ /g' <<< $LD_LIBRARY_PATH) | \
grep libcupti
 

如果路径上没有CUPTI,请通过运行以下命令将其安装目录添加到$LD_LIBRARY_PATH环境变量中:

 export LD_LIBRARY_PATH=/usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH
 

再次运行上面的ldconfig命令以验证是否找到了CUPTI库。

配置多个GPU

TensorFlow当前仅支持单个主机系统的多个GPU配置文件。当前不支持针对多主机系统的多GPU配置文件。安装CUDA®Toolkit 10.2或更高版本以配置多个GPU。由于TensorFlow仅支持高达10.1的CUDA®Toolkit版本,因此请创建指向libcudart.so.10.1libcupti.so.10.1符号链接。

 sudo ln -s /usr/local/cuda/lib64/libcudart.so.10.2 /usr/local/cuda/lib64/libcudart.so.10.1
sudo ln -s /usr/local/cuda/extras/CUPTI/lib64/libcupti.so.10.2 /usr/local/cuda/extras/CUPTI/lib64/libcupti.so.10.1
 

要分析多工GPU配置,请分别分析各个工。

解决特权问题

在Docker环境或Linux中使用CUDA®Toolkit 10.1运行性能分析时,可能会遇到与CUPTI特权不足( CUPTI_ERROR_INSUFFICIENT_PRIVILEGES )相关的问题。请参阅NVIDIA开发人员文档,以了解有关如何在Linux上解决这些问题的更多信息。

要解决Docker环境中的CUPTI特权问题,请运行

 docker run option '--privileged=true'
 

探查器工具

从TensorBoard中的“ 轮廓”选项卡访问Profiler,该选项卡仅在您捕获了一些模型数据后才会显示。

Profiler提供了一些工具来帮助进行性能分析:

  • 概述页面
  • 输入管道分析仪
  • TensorFlow统计
  • 跟踪查看器
  • GPU内核统计
  • 内存配置文件工具

概述页面

概述页面提供了模型在概要文件运行期间的性能的顶级视图。该页面向您显示了主机和所有设备的汇总概述页面,以及一些改善模型训练性能的建议。您还可以在“主机”下拉列表中选择单个主机。

概述页面显示数据如下:

图片

  • 性能摘要-显示模型性能的高级摘要。性能摘要分为两部分:

    1. 步进时间细分-将平均步进时间细分为花费时间的多个类别:

      • 编译-编译内核所花费的时间
      • 输入-读取输入数据所花费的时间
      • 输出-读取输出数据所花费的时间
      • 内核启动-主机启动内核所花费的时间
      • 主机计算时间
      • 设备到设备的通信时间
      • 设备上计算时间
      • 所有其他,包括Python开销
    2. 设备计算精度-报告使用16位和32位计算的设备计算时间的百分比

  • 步骤时间图-显示所有采样步骤中设备步骤时间的图表(以毫秒为单位)。每个步骤都分为花费时间的多个类别(具有不同的颜色)。红色区域对应于设备处于空闲状态以等待主机输入数据的步骤时间的一部分。绿色区域显示设备实际工作了多少时间

  • 设备上的前10个TensorFlow操作-显示运行时间最长的设备上操作。

    每行显示一个操作员的自身时间(所有操作员所占时间的百分比),累计时间,类别和名称。

  • 运行环境-显示模型运行环境的高级摘要,包括:

    • 使用的主机数
    • 设备类型(GPU / TPU)
    • 设备核心数
  • 后续步骤的建议-报告何时输入模型绑定,并建议可用于查找和解决模型性能瓶颈的工具

输入管道分析仪

当TensorFlow程序从文件中读取数据时,它以流水线方式从TensorFlow图的顶部开始。读取过程分为多个串联的数据处理阶段,一级的输出是下一级的输入。这种读取数据的系统称为输入管道

从文件读取记录的典型管道具有以下阶段:

  1. 文件读取
  2. 文件预处理(可选)
  3. 文件从主机传输到设备

低效的输入管道可能会严重降低您的应用程序速度。当应用程序在输入管道中花费大量时间时,它被视为输入绑定 。使用从输入管道分析器获得的见解来了解输入管道效率低下的地方。

输入管道分析器会立即告诉您您的程序是否受输入限制,并引导您进行设备和主机侧分析,以调试输入管道中任何阶段的性能瓶颈。

有关优化数据输入管道的建议最佳实践,请参阅有关输入管道性能的指南。

输入管道仪表板

要打开输入管道分析器,请选择Profile ,然后从“ 工具”下拉列表中选择input_pipeline_analyzer

图片

仪表板包含三个部分:

  1. 摘要-总结整个输入管道,其中包含有关您的应用程序是否受输入绑定以及(如果有)输入多少的信息
  2. 设备端分析-显示详细的设备端分析结果,包括设备步长时间以及每个步骤等待跨内核输入数据所花费的设备时间范围
  3. 主机端分析-显示主机端的详细分析,包括主机上输入处理时间的细分

输入管道摘要

摘要通过显示等待主机输入所花费的设备时间百分比来报告是否输入了程序。如果您使用已检测的标准输入管道,则该工具将报告大部分输入处理时间在何处。

设备端分析

设备端分析可提供有关在设备上花费的时间而不是主机上花费的时间的信息,以及花费了多少设备时间来等待来自主机的输入数据。

  1. 针对步骤编号绘制的步骤时间-显示所有采样步骤中设备步骤时间的图表(以毫秒为单位)。每个步骤都分为花费时间的多个类别(具有不同的颜色)。红色区域对应于设备处于空闲状态以等待主机输入数据的步骤时间的一部分。绿色区域显示设备实际工作了多少时间
  2. 步进时间统计信息-报告设备步进时间的平均值,标准偏差和范围([最小,最大])

主机端分析

主机端分析将主机上的输入处理时间(花费在tf.data API ops上的时间) tf.data为以下几类:

  • 按需从文件读取数据-在不进行缓存,预取和交错的情况下从文件读取数据所花费的时间
  • 预先从文件中读取数据-读取文件所花费的时间,包括缓存,预取和交织
  • 数据预处理-在预处理操作上花费的时间,例如图像解压缩
  • 排队要传输到设备的数据-在将数据传输到设备之前将数据放入馈入队列所花费的时间

展开输入操作统计信息,以查看各个输入操作及其类别的统计信息(按执行时间细分)。

图片

出现一个源数据表,每个条目包含以下信息:

  1. 输入操作-显示输入操作的TensorFlow操作名称
  2. 计数-显示概要分析期间op执行的实例总数
  3. 总时间(以毫秒为单位)-显示在每个实例上花费的累计时间总和
  4. 总时间百分比-显示操作的总时间占输入处理总时间的一部分
  5. 总自拍时间(以毫秒为单位)-显示在每个实例上花费的自拍时间的累积总和。此处的自身时间用于衡量在函数体内花费的时间,不包括在调用函数中花费的时间。
  6. 总自我时间% 。将总的自我时间显示为输入处理所花费的总时间的一部分
  7. 类别 。显示输入操作的处理类别

TensorFlow统计

TensorFlow Stats工具显示在分析会话期间在主机或设备上执行的每个TensorFlow op(op)的性能。

图片

该工具在两个窗格中显示性能信息:

  • 上部窗格最多显示四个饼图:

    1. 主机上每个op的自执行时间的分布
    2. 主机上每种op类型的自执行时间的分布
    3. 设备上每个操作的自执行时间的分布
    4. 设备上每种操作类型的自执行时间的分布
  • 下部窗格显示一张表,该表报告有关TensorFlow op的数据,其中每个op对应一行,每种数据类型对应一列(通过单击列标题对列进行排序)。单击上部窗格右侧的“导出为CSV”按钮,以将该表中的数据导出为CSV文件。

    注意:

    • 如果任何操作有子操作:

      • 一个操作的“累计”总时间包括在子操作内部花费的时间

      • 一个操作的“自我”总时间不包括在子操作内部花费的时间

    • 如果操作在主机上执行:

      • 操作在设备上导致的总自拍时间百分比为0
      • 包括该操作在内的设备上的总自拍时间的累计百分比为0
    • 如果操作在设备上执行:

      • 此操作在主机上导致的总自拍时间百分比将为0
      • 主机上包括该操作在内的总自拍时间的累计百分比为0

您可以选择在饼图和表格中包括或排除空闲时间。

跟踪查看器

跟踪查看器显示时间线,其中显示:

  • TensorFlow模型执行的操作的持续时间
  • 系统的哪一部分(主机或设备)执行了操作。通常,主机执行输入操作,预处理训练数据并将其传输到设备,而设备执行实际的模型训练

跟踪查看器使您可以确定模型中的性能问题,然后采取步骤解决它们。例如,从较高的层次上,您可以确定输入或模型训练是否花费了大部分时间。深入研究,您可以确定执行时间最长的操作。请注意,每个设备的跟踪查看器被限制为一百万个事件。

跟踪查看器界面

当您打开跟踪查看器时,它将显示您最近的运行:

图片

该屏幕包含以下主要元素:

  1. 时间轴窗格-显示随着时间的推移设备和主机执行的操作
  2. 详细信息窗格-显示在“时间轴”窗格中选择的操作的其他信息

“时间轴”窗格包含以下元素:

  1. 顶栏-包含各种辅助控件
  2. 时间轴-显示相对于轨迹开始的时间
  3. 区段和轨道标签-每个区段包含多个轨道,并且在左侧具有一个三角形,您可以单击以展开和折叠该区段。系统中每个处理元素都有一个区域
  4. 工具选择器-包含用于与轨迹查看器交互的各种工具,例如“缩放”,“平移”,“选择”和“计时”。使用计时工具标记时间间隔。
  5. 事件-这些事件显示执行操作的时间或元事件的持续时间,例如培训步骤
节和轨道

跟踪查看器包含以下部分:

  • 每个设备节点的一个区域 ,标有设备芯片的编号和芯片中的设备节点的编号(例如/device:GPU:0 (pid 0) )。每个设备节点部分均包含以下轨道:
    • 步骤-显示设备上正在运行的培训步骤的持续时间
    • TensorFlow Ops- 。显示在设备上执行的操作
    • XLA行动-显示XLA操作(OPS)如果XLA是所使用的编译器在设备上运行过(各TensorFlow运算被转换成一个或几个XLA OPS的XLA编译器翻译这些XLA OPS成代码,所述设备上运行。)。
  • 一段针对在主机CPU上运行的线程的标记为“主机线程” 。该部分为每个CPU线程包含一个轨道。请注意,您可以忽略部分标签旁边显示的信息。
大事记

时间轴内的事件以不同的颜色显示;颜色本身没有特定含义。

跟踪查看器还可以在TensorFlow程序中显示Python函数调用的跟踪。如果使用tf.profiler.experimental.start() API,则可以在开始分析时使用ProfilerOptions tf.profiler.experimental.start()启用Python跟踪。或者,如果使用采样模式进行性能分析,则可以使用“ 捕获配置文件”对话框中的下拉选项来选择跟踪级别。

图片

GPU内核统计

该工具显示每个GPU加速内核的性能统计信息和原始操作。

图片

该工具在两个窗格中显示信息:

  • 上方窗格显示一个饼图,该饼图显示了总耗时最长的CUDA内核

  • 下部窗格显示一个表,其中包含每个唯一内核操作对的以下数据:

    • 按照内核运行对分组的总GPU持续时间的降序排列
    • 启动的内核的名称
    • 内核使用的GPU寄存器数
    • 共享(静态+动态共享)内存使用的总大小(以字节为单位)
    • 表示为blockDim.x, blockDim.y, blockDim.z的块尺寸
    • 网格尺寸表示为gridDim.x, gridDim.y, gridDim.z
    • 运营商是否有资格使用TensorCores
    • 内核是否包含TensorCore指令
    • 启动此内核的操作的名称
    • 此内核操作对的出现次数
    • 经过的GPU总时间(以微秒为单位)
    • GPU的平均经过时间(以微秒为单位)
    • 经过的最短GPU时间(以微秒为单位)
    • GPU经过的最大时间(以微秒为单位)

内存配置文件工具

内存配置文件工具会在分析间隔期间监视主机或设备的内存使用情况。您可以使用此工具执行以下操作:

  • 通过查明峰值内存使用情况以及为TensorFlow操作分配相应的内存分配,来调试内存不足(OOM)问题。您还可以调试运行多租户推断时可能出现的OOM问题
  • 调试内存碎片问题

内存配置文件工具分三部分显示数据:

  1. 内存配置文件摘要
  2. 内存时间线图
  3. 内存明细表

内存配置文件摘要

本节显示TensorFlow程序的内存配置文件的高级摘要,如下所示:

内存配置文件摘要包含六个字段:

  1. 内存ID-下拉列表,其中列出了所有可用的内存系统(主机和设备)。从下拉列表中选择要查看的内存系统。请注意,主机列为gpu_host_bfc
  2. #Allocation-在分析间隔内进行的内存分配数
  3. #Deallocation-分析间隔中的内存释放数
  4. 内存容量-您选择的内存系统的总容量(以GiB为单位)
  5. 峰值堆使用量-自模型开始运行以来的峰值内存使用量(以GiB为单位)
  6. 峰值内存使用量-分析间隔中的峰值内存使用量(以GiB为单位)。该字段包含以下子字段:
    1. 时间戳-时间线图上出现峰值内存使用量的时间戳
    2. 堆栈保留-堆栈上保留的内存量(以GiB为单位)
    3. 堆分配-堆上分配的内存量(以GiB为单位)
    4. 可用内存-可用内存量(以GiB为单位)。内存容量是堆栈预留,堆分配和可用内存的总和
    5. 碎片-碎片百分比(越低越好)。它是按以下百分比计算的:(1-可用内存最大块的大小/总可用内存)

内存时间线图

本节显示了内存使用情况(以GiBs为单位)以及碎片百分比与时间(以ms为单位)的关系图。

图片

X轴表示分析间隔的时间轴(以毫秒为单位)。左侧的Y轴表示内存使用情况(以GiBs为单位),右侧的Y轴表示碎片百分比。在X轴上的每个时间点,总内存分为三类:堆栈(红色),堆(橙色)和空闲(绿色)。将鼠标悬停在特定的时间戳上可以查看有关此时内存分配/释放事件的详细信息,如下所示:

图片

弹出窗口显示以下信息:

  • timestamp(ms)-所选事件在时间线上的位置
  • 事件-事件类型(分配或取消分配)
  • request_size(GiBs)-请求的内存量。这将是取消分配事件的负数
  • location_size(GiBs)-实际分配的内存量。这将是取消分配事件的负数
  • tf_op-请求分配/取消分配的TensorFlow Op
  • step_id-发生此事件的训练步骤
  • region_type-此分配的内存用于的数据实体类型。可能的值为temp的临时值,为激活和渐变的output值,以及对于权重和常数的persist / dynamic
  • data_type-张量元素类型(例如,uint8表示8位无符号整数)
  • tensor_shape-被分配/取消分配的张量的形状
  • memory_in_use(GiBs)-在此时间点正在使用的总内存

内存故障表

该表显示了在分析间隔中峰值内存使用时的活动内存分配。

图片

每个TensorFlow Op都有一行,并且每一行都有以下列:

  • Op名称-TensorFlow op的名称
  • 分配大小(GiB)-分配给此操作的内存总量
  • 请求的大小(GiB)-此操作请求的总内存量
  • 出现次数-此操作的分配次数
  • 区域类型-此分配的内存用于的数据实体类型。可能的值为temp的临时值,为激活和渐变的output值,以及对于权重和常数的persist / dynamic
  • 数据类型-张量元素类型
  • 形状-分配的张量的形状

收集绩效数据

TensorFlow Profiler收集您的TensorFlow模型的主机活动和GPU跟踪。您可以配置探查器以通过编程模式或采样模式收集性能数据。

分析API

您可以使用以下API执行分析。

 # Profile from batches 10 to 15
tb_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir,
                                             profile_batch='10, 15')

# Train the model and use the TensorBoard Keras callback to collect
# performance profiling data
model.fit(train_data,
          steps_per_epoch=20,
          epochs=5,
          callbacks=[tb_callback])
 
 tf.profiler.experimental.start('logdir')
# Train the model here
tf.profiler.experimental.stop()
 
  • 使用上下文管理器的编程模式
 with tf.profiler.experimental.Profile('logdir'):
    # Train the model here
    pass
 
  • 采样模式-使用tf.profiler.experimental.server.start()来执行按需配置,以在运行TensorFlow模型的情况下启动gRPC服务器。启动gRPC服务器并运行模型后,您可以通过TensorBoard配置文件插件中的“ 捕获配置文件”按钮捕获配置文件。如果尚未运行TensorBoard实例,请使用上面“安装探查器”部分中的脚本启动TensorBoard实例。

    举个例子,

 # Start a gRPC server at port 6009
tf.profiler.experimental.server.start(6009)
# ... TensorFlow program ...
 

使用“ 捕获配置文件”对话框来指定:

  • 配置文件服务URL或TPU名称
  • 分析持续时间
  • 设备,主机和Python函数调用跟踪的级别
  • 如果最初不成功,您希望Profiler重试捕获配置文件多少次

分析自定义训练循环

要在TensorFlow代码中分析自定义训练循环,请使用tf.profiler.experimental.Trace API对训练循环进行tf.profiler.experimental.Trace以标记Profiler的步骤边界。 name参数用作步骤名称的前缀, step_num关键字参数附加在步骤名称中,并且_r关键字参数使此跟踪事件由Profiler处理为步骤事件。

举个例子,

 for step in range(NUM_STEPS):
    with tf.profiler.experimental.Trace('train', step_num=step, _r=1):
        train_data = next(dataset)
        train_step(train_data)
 

这将启用Profiler的基于步骤的性能分析,并使步骤事件显示在跟踪查看器中。

确保在tf.profiler.experimental.Trace上下文中包括数据集迭代器,以对输入管道进行准确的分析。

下面的代码段是反模式:

 for step, train_data in enumerate(dataset):
    with tf.profiler.experimental.Trace('train', step_num=step, _r=1):
        train_step(train_data)
 

分析用例

探查器涵盖了沿四个不同轴的许多用例。目前支持某些组合,将来还会添加其他组合。一些用例是:

  • 本地配置文件与远程配置文件:这是设置配置文件环境的两种常用方法。在本地配置中,在与模型执行相同的机器上调用配置API,例如,具有GPU的本地工作站。在远程分析中,在与执行模型的机器不同的机器上(例如,在Cloud TPU上)调用分析API。
  • 对多个工作人员进行性能分析:使用TensorFlow的分布式培训功能时,您可以配置多台计算机。
  • 硬件平台:Profile CPU,GPU和TPU。

下表是TensorFlow 2.3中各种分析API支持的上述用例的快速概述:

分析API 本地远程多名工人硬件平台
TensorBoard Keras回调 支持的不支持不支持 CPU,GPU
tf.experimental.profiler函数API 支持的不支持不支持 CPU,GPU
上下文管理器API 支持的不支持不支持 CPU,GPU
按需API 不支持支持的有限的支持 CPU,GPU,TPU

最佳模型性能的最佳做法

使用适用于您的TensorFlow模型的以下建议以实现最佳性能。

通常,请在设备上执行所有转换,并确保为平台使用cuDNN和Intel MKL等库的最新兼容版本。

优化输入数据管道

高效的数据输入管道可以通过减少设备空闲时间来极大地提高模型执行的速度。考虑将以下最佳实践详见这里 ,让您的数据输入管道更高效:

  • 预取数据
  • 并行数据提取
  • 并行数据转换
  • 在内存中缓存数据
  • 向量化用户定义的函数
  • 应用转换时减少内存使用

此外,请尝试使用综合数据运行模型,以检查输入管道是否是性能瓶颈。

提高设备性能

  • 增加训练小批量的大小(训练循环的一次迭代中每个设备使用的训练样本数)
  • 使用TF统计信息来了解设备上操作的运行效率
  • 使用tf.function进行计算,还可以选择启用experimental_compile标志
  • 尽量减少步骤之间的主机Python操作并减少回调。每隔几步而不是每一步计算指标
  • 保持设备计算单元繁忙
  • 将数据并行发送到多个设备
  • 优化数据布局以优先使用频道(例如,NHCH比NHWC)。某些GPU(例如NVIDIA®V100)在NHWC数据布局下的性能更好。
  • 考虑使用16位数字表示形式,例如fp16 ,IEEE指定的半精度浮点格式或Brain浮点bfloat16格式
  • 考虑使用Keras混合精度API
  • 在GPU上进行训练时,请使用TensorCore。当精度为fp16且输入/输出尺寸可以被8或16整除时,GPU内核使用TensorCore(对于int8)

额外资源