1. NVIDIA GPUDirect Storage 安装和故障排除指南#
本指南介绍了如何安装、调试和隔离与 GDS 相关的性能和功能问题,适用于系统管理员和开发人员。
2. 简介#
本指南介绍了如何调试和隔离与 NVIDIA® Magnum IO GPUDirect® Storage (GDS) 相关的性能和功能问题,适用于系统管理员和开发人员。
GDS 为 GPU 内存和存储之间的直接内存访问 (DMA) 传输启用直接数据路径,从而避免了通过 CPU 的反弹缓冲区。此直接路径增加了系统带宽,并降低了 CPU 的延迟和利用率负载。
创建此直接路径涉及分布式文件系统,例如 NFSoRDMA、DDN EXAScaler 并行文件系统解决方案(基于 Lustre 文件系统)和 WekaFS,因此 GDS 环境由多个软件和硬件组件组成。本指南解决了与 GDS 安装相关的问题,并帮助您诊断功能和性能问题。对于非 GDS 问题,请联系相应的 OEM 或文件系统供应商以了解和调试问题。
3. 安装 GPUDirect Storage#
本节包括 GDS 安装、卸载、配置信息以及使用实验性存储库。
注意
对于 NVAIE 和 vGPU 环境,请按照各自文档中的步骤操作。
3.1. 安装 GDS 之前#
要在非 DGX 平台上安装 GDS,请完成以下步骤
运行以下命令以检查 IOMMU 的当前状态。
$ dmesg | grep -i iommu
在基于 x86_64 的平台上,如果 IOMMU 为启用状态,请完成步骤 2 以禁用它,否则继续执行步骤 3。
禁用 IOMMU。
注意
根据我们的经验,
iommu=off
在功能和性能方面效果最佳。在某些平台(例如 DGX A100 和 DGX-2)上,支持iommu=pt
。iommu=on
不能保证在功能上或性能上都能正常工作。运行以下命令
$ sudo vi /etc/default/grub b. Add one of the following options to the ``GRUB_CMDLINE_LINUX_DEFAULT`` option. - If you have an **AMD** CPU, add ``amd_iommu=off``. - If you have an **Intel** CPU, add ``intel_iommu=off``. If there are already other options, enter a space to separate the options, for example, ``GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 amd_iommu=off`` c. Run the following commands: $ sudo update-grub $ sudo reboot d. After the system reboots, to verify that the change took effect, run the following command:
$ cat /proc/cmdline It should show the options which have been added to the grub file.
在按照说明操作之前,请阅读“注意”部分。
使用 MLNX_OFED 要求和安装 安装 MLNX_OFED 或 DOCA 要求和安装 安装 DOCA。
注意
只有当您需要启用对 NVMe、NVMf、NFSoRDMA 的支持时,才需要执行此步骤
对于 DGX OS 6.x 或更高版本,不需要执行此步骤。
3.2. 安装 GDS#
GDS 安装支持两种方式
使用软件包管理器,例如 Debian 和 RPM
有关在 DGX 平台上安装的信息,请参阅
有关在非 DGX 平台上安装的信息,请参阅此处。
注意
对于 CUDA 11.5.1 及更高版本,如果您计划使用 Weka FS 或 IBM SpectrumScale,则必须运行
modprobe nvidia_peermem
这将加载支持 PeerDirect 功能的模块。系统重启后必须运行此命令。
为了在每次重启后自动加载模块,请运行以下命令
echo "nvidia-peermem" | sudo tee /etc/modules-load.d/nvidia-peermem.conf
在本文档中,cuda-<x>.<y>
中,x
指的是 CUDA 主要版本,y
指的是次要版本。
3.2.1. 配置 GDS 的文件系统设置#
在继续之前,请参阅本文档中特定于文件系统的部分,了解支持 GDS 所需的必要配置
Lustre-Lnet:配置具有多个 OST 的 LNet 网络以实现最佳对等选择
WekaIO:GDS 配置文件更改以支持 WekaIO 文件系统
IBM Spectrum Scale:GDS 配置以支持 IBM Spectrum Scale
BeeGFS:BeeGFS 客户端 GDS 配置
VAST:设置网络
NVMe:GPU 亲缘性的 RAID 组配置
注意
对于本地文件系统(例如 Ext4/XFS),可以跳过此步骤。
3.2.2. 验证 GDS 安装是否成功#
要验证 GDS 安装是否成功,请运行 gdscheck
$ /usr/local/cuda-<x>.<y>/gds/tools/gdscheck.py -p
注意
gdscheck
命令需要系统上存在 python3。如果由于 python3 不可用而失败,则可以使用 python(即 python2)的安装路径显式调用该命令。例如
$ /usr/bin/python /usr/local/cuda-<x>.<y>/gds/tools/gdscheck.py -p
此命令的输出显示系统上安装的受支持文件系统或设备是否支持 GDS。输出还显示是否在任何 PCI 交换机上启用了 PCIe ACS。
注意
为了获得最佳 GDS 性能,请禁用 PCIe ACS。
示例输出
GDS release version: 1.13.0.7
nvidia_fs version: 2.24 libcufile version: 2.12
Platform: x86_64
============
ENVIRONMENT:
============
=====================
DRIVER CONFIGURATION:
=====================
NVMe P2PDMA : Supported
NVMe : Supported
NVMeOF : Unsupported
SCSI : Unsupported
ScaleFlux CSD : Unsupported
NVMesh : Unsupported
DDN EXAScaler : Supported
IBM Spectrum Scale : Unsupported
NFS : Unsupported
BeeGFS : Unsupported
WekaFS : Supported
Userspace RDMA : Supported
--Mellanox PeerDirect : Enabled
--DmaBuf support : Enabled
--rdma library : Loaded (libcufile_rdma.so)
--rdma devices : Configured
--rdma_device_status : Up: 1 Down: 0
=====================
CUFILE CONFIGURATION:
=====================
properties.use_pci_p2pdma : true
properties.use_compat_mode : true
properties.force_compat_mode : false
properties.gds_rdma_write_support : true
properties.use_poll_mode : false
properties.poll_mode_max_size_kb : 4
properties.max_batch_io_size : 128
properties.max_batch_io_timeout_msecs : 5
properties.max_direct_io_size_kb : 16384
properties.max_device_cache_size_kb : 131072
properties.max_device_pinned_mem_size_kb : 33554432
properties.posix_pool_slab_size_kb : 4 1024 16384
properties.posix_pool_slab_count : 128 64 64
properties.rdma_peer_affinity_policy : RoundRobin
properties.rdma_dynamic_routing : 0
fs.generic.posix_unaligned_writes : false
fs.lustre.posix_gds_min_kb: 0
fs.beegfs.posix_gds_min_kb: 0
fs.weka.rdma_write_support: false
fs.gpfs.gds_write_support: false
fs.gpfs.gds_async_support: true
profile.nvtx : false
profile.cufile_stats : 2
miscellaneous.api_check_aggressive : false
execution.max_io_threads : 0
execution.max_io_queue_depth : 128
execution.parallel_io : false
execution.min_io_threshold_size_kb : 8192
execution.max_request_parallelism : 4
properties.force_odirect_mode : false
properties.prefer_iouring : false
=========
GPU INFO:
=========
GPU index 0 NVIDIA L4 bar:1 bar size (MiB):32768 supports GDS, IOMMU State: Disabled
==============
PLATFORM INFO:
==============
IOMMU: disabled
Nvidia Driver Info Status: Supported(Nvidia Open Driver Installed)
Cuda Driver Version Installed: 12080
Platform: ProLiant DL360 Gen10, Arch: x86_64(Linux 6.8.0-31-generic)
Platform verification succeeded
注意
/usr/local/cuda-<x>.<y>/gds/tools
和 /usr/local/cuda-<x>.<y>/gds/samples
中提供了 README,以显示用法。
3.3. 已安装的 GDS 库和工具#
GPUDirect Storage 用户空间库位于 /usr/local/cuda-<X>.<Y>/targets/x86_64-linux/lib/ 目录中。
注意
GPUDirect Storage 软件包安装在 /usr/local/cuda-X.Y/gds 中,其中 X 是 CUDA 工具包的主要版本,Y 是次要版本。
$ ls -1 /usr/local/cuda-X.Y/targets/x86_64-linux/lib/*cufile*
cufile.h
libcufile.so
libcufile.so.0
libcufile.so.1.0.0
libcufile_rdma.so
libcufile_rdma.so.0
libcufile_rdma.so.1.0.0
GPUDirect Storage 工具和示例位于 /usr/local/cuda-X.Y/gds 目录中。
$ ls -lh /usr/local/cuda-X.Y/gds/
total 20K
-rw-r--r-- 1 root root 8.4K Mar 15 13:01 README
drwxr-xr-x 2 root root 4.0K Mar 19 12:29 samples
drwxr-xr-x 2 root root 4.0K mar 19 10:28 tools
对于此版本,GPUDirect Storage 提供了额外的 libcufile-dev
软件包(cuFile 库开发人员软件包)。这主要用于开发人员环境。本质上,lincufile-dev
软件包包含 cuFile 库的静态版本(libcufile_static.a
,libcufile_rdma_static.a
)和 cufile.h
头文件,使用 cuFile 库 API 的应用程序可能需要这些文件。
3.4. 卸载 GPUDirect Storage#
要从 Ubuntu 和 DGX OS 卸载 GDS
$ sudo apt-get remove --purge "*libcufile*" "*gds-tools*" "*nvidia-fs*"
要从 RHEL 卸载
$ sudo dnf remove "nvidia-gds*"
3.5. GPUDirect Storage 使用的环境变量#
GDS 使用以下环境变量。
CUFILE_ENV 变量 |
描述 |
---|---|
|
DC 目标的完成队列深度。 |
|
控制 cufile 是否检查受支持的文件系统。设置为 1 时,允许使用尚未正式启用 cuFile 的新文件系统进行测试。 |
|
控制 cuFile 库从中读取配置变量的路径。这可以用于容器环境和需要与 |
|
为用户空间 RDMA 目标(WekaFS 和 GPFS)在 RoCEv2 设备 QP 上设置 QOS 级别。 |
|
为用户空间 RDMA 目标(WekaFS 和 GPFS)在 IB 设备 QP 上设置 QOS 级别。 |
|
控制 cuFile 日志信息的路径。指定默认日志路径,即应用程序的当前工作目录。对容器或日志记录很有用。 |
|
控制跟踪级别,并且可以覆盖特定应用程序的跟踪级别,而无需新的配置文件。 |
|
QP 的最小 RNR 值,在此值之后,如果远程端没有发布工作请求,QP 将因 RNR 超时而报错。默认值为 16 (2.56ms)。 |
|
启用 NVTX 跟踪以用于 Nsight 系统。 |
|
为 WekaFS 和 GPFS 的用户空间 RDMA DC 目标控制 DC_KEY。 |
|
数据包在网络上被丢弃之前的最大跳数。防止数据包无限循环。默认值为 64。 |
|
分区密钥索引。 |
|
共享请求队列支持的最大工作请求数。 |
|
每个工作请求支持的最大分散聚集条目数。 |
|
将此环境变量设置为 true 将跳过兼容模式下的拓扑检测。这将减少在具有多个 PCI 设备的系统上兼容模式下出现的高启动延迟。 |
|
覆盖 cufile.json 设置,并强制 I/O 通过兼容模式而不是 GDS 模式。 |
|
这与 |
|
设置为 true 时,如果内核支持,则 IO 首选项将设置为 NVMe 的 PCI p2pdma 路径,而不是传统的 nvidia-fs 路径,否则将使用通过 nvidia-fs 的传统路径。 |
3.6. GPUDirect Storage 使用的 JSON 配置参数#
有关 GDS 使用的 JSON 配置参数的详细信息,请参阅GPUDirect Storage 参数
对于尚未设置 GDS 支持的系统或挂载,请考虑 compat_mode
。要了解有关兼容模式的更多信息,请参阅cuFile 兼容模式。
3.7. 支持动态路由的 GDS 配置文件更改#
为了使动态路由支持多个文件系统和挂载点,请为单个挂载配置全局的每个文件系统 rdma_dev_addr_list
属性,或为每个文件系统挂载表配置 rdma_dev_addr_list
属性。
"fs": {
"lustre": {
// if using a single lustre mount, provide the ip addresses
// here (use : sudo lnetctl net show)
//"rdma_dev_addr_list" : []
// if using multiple lustre mounts, provide ip addresses
// used by respective mount here
//"mount_table" : {
// "/lustre/ai200_01/client" : {
// "rdma_dev_addr_list" : ["172.172.1.40",
"172.172.1.42"]
// },
// "/lustre/ai200_02/client" : {
// "rdma_dev_addr_list" : ["172.172.2.40",
"172.172.2.42"]
//}
},
"nfs": {
//"rdma_dev_addr_list" : []
//"mount_table" : {
// "/mnt/nfsrdma_01/" : {
// "rdma_dev_addr_list" : []
//},
// "/mnt/nfsrdma_02/" : {
// "rdma_dev_addr_list" : []
//}
//}
},
},
3.8. 确定安装了哪个版本的 GDS#
要确定您拥有的 GDS 版本,请运行以下命令
$ gdscheck.py -v
示例输出
GDS release version: 1.0.0.78
nvidia_fs version: 2.7 libcufile version: 2.4
3.9. 用于 DGX 系统 GDS 软件包网络安装的实验性存储库#
可以通过在受支持的 DGX 平台上使用以下步骤启用预览存储库来安装 GDS 1.0.0 和 MLNX_OFED 软件包。
对于 Ubuntu 18.04/20.04 发行版
可以通过网络使用预览网络存储库安装 GDS 1.0.0、NVSM 和 MLNX_OFED 软件包。
对于 Ubuntu 20.04 发行版
$ sudo apt-key adv --fetch-keys https://repo.download.nvidia.com/baseos/GPG-KEY-dgx-cosmos-support
$ sudo add-apt-repository "deb https://repo.download.nvidia.com/baseos/ubuntu/focal/x86_64/ focal-updates preview"
$ sudo apt update
4. API 错误#
本节提供有关使用 GDS 时可能遇到的常见 API 错误的信息。
4.1. CU_FILE_DRIVER_NOT_INITIALIZED#
如果未调用 cuFileDriverOpen
API,则在隐式调用驱动程序初始化时遇到的错误将报告为在调用 cuFileBufRegister
或 cuFileHandleRegister
时遇到的 cuFile 错误。
4.2. CU_FILE_DEVICE_NOT_SUPPORTED#
GDS 仅在支持计算模式的 NVIDIA 图形处理器 (GPU) Tesla® 或 Quadro® 型号以及计算主要能力大于或等于 6 的型号上受支持。
注意
这包括 V100 和 T4 卡。
4.3. CU_FILE_IO_NOT_SUPPORTED#
如果文件描述符来自本地文件系统,或者来自未准备好 GDS 的挂载,则 API 返回 CU_FILE_IO_NOT_SUPPORTED
错误。
有关受支持文件系统的列表,请参阅安装 GDS 之前。
此错误的常见原因包括
文件描述符属于不受支持的文件系统。
指定的
fd
不是常规 UNIX 文件。在
fd
上设置了加密和压缩、合规性设置的任意组合。例如,
FS_COMPR_FL | FS_ENCRYPT_FL | FS_APPEND_FL | FS_IMMUTABLE_FL
。注意
当
compat_mode
设置为true
时,允许使用这些设置。在
fd
的打开调用中指定了不受支持的文件模式的任意组合。例如,O_APPEND | O_NOCTTY | O_NONBLOCK | O_DIRECTORY | O_NOFOLLOW | O_TMPFILE
4.4. CU_FILE_CUDA_MEMORY_TYPE_INVALID#
cudaMallocManaged
内存的物理内存是在首次使用时动态分配的。目前,它不提供公开物理内存或基址寄存器 (BAR) 内存以供 GDS 使用的机制。但是,当内存用作 cuFileWrite
和 cuFileRead
的未注册缓冲区时,GDS 间接支持 cudaMallocManaged
内存。
5. 基本故障排除#
5.1. GDS 库的日志文件#
cufile.log
文件在应用程序二进制文件所在的同一位置创建。当前,最大日志文件大小为 32MB。如果日志文件大小增加到大于 32MB,则日志文件将被截断,并且日志记录将在同一文件上恢复。
5.2. 为每个应用程序启用不同的 cufile.log 文件#
您可以为每个应用程序启用不同的 cufile.log
文件。
有几个相关的情况
如果默认 /etc/cufile.json 文件中的
logging:dir
属性未设置,则默认情况下,cufile.log
文件在应用程序的当前工作目录中生成。如果在默认
/etc/cufile.json
文件中设置了logging:dir
属性,则日志文件将在指定的目录路径中创建。
注意
对于多个应用程序使用 libcufile.so
库的场景,通常不建议这样做。
例如
"logging": {
// log directory, if not enabled
// will create log file under current working
// directory
"dir": "/opt/gdslogs/",
}
cufile.log
将创建为 /opt/gdslogs/cufile.log
文件。
如果应用程序需要为不同的应用程序启用不同的 cufile.log
,则应用程序可以通过执行以下步骤来覆盖默认 JSON 路径
导出 CUFILE_ENV_PATH_JSON=”/opt/myapp/cufile.json”。
编辑 /opt/myapp/cufile.json 文件。
"logging": { // log directory, if not enabled // will create log file under current working // directory "dir": "/opt/myapp", }
运行应用程序。
要检查日志,请运行
$ ls -l /opt/myapp/cufile.log
5.3. 启用跟踪 GDS 库 API 调用#
有不同的日志记录级别,可以在 /etc/cufile.json
文件中启用。
默认情况下,日志记录级别设置为 ERROR
。随着我们增加详细级别(如 INFO
、DEBUG
和 TRACE
),日志记录将对性能产生影响,应仅在调试现场问题时启用。
配置跟踪并运行以下命令
"logging": {
// log directory, if not enabled
// will create log file under local directory
//"dir": "/home/<xxxx>",
// ERROR|WARN|INFO|DEBUG|TRACE (in decreasing order of priority)
"level": "ERROR"
},
5.4. cuFileHandleRegister 错误#
如果在发出 IO 时在 cufile.log
文件中看到 cuFileHandleRegister
错误
"cuFileHandleRegister error: GPUDirect Storage not supported on current file."
以下是可能发生此错误的一些原因
GDS 不支持该文件系统。
有关详细信息,请参阅CU_FILE_DEVICE_NOT_SUPPORTED。
DIRECT_IO
功能不受文件所在挂载点的支持。
有关更多信息,请在 /etc/cufile.json
文件中启用跟踪。
5.5. 排除返回 cuFile 错误的应用程序的故障#
要排除 cuFile 错误,请执行以下操作
有关 API 返回的错误的更多信息,请参阅
cufile.h
文件。如果 IO 已提交到 GDS 驱动程序,请检查 GDS 统计信息中是否有任何错误。
如果 IO 失败,则错误统计信息应提供有关错误类型的信息。
有关更多信息,请参阅查找 GDS 驱动程序统计信息。
启用 GDS 库跟踪并监控
cufile.log
文件。启用 GDS 驱动程序调试
$ echo 1 >/sys/module/nvidia_fs/parameters/dbg_enabled
启用驱动程序调试日志后,您可能会获得有关错误的更多信息。
5.6. cuFile-* 错误,GPUDirect Storage 统计信息中无活动#
如果 GDS 统计信息中存在 cuFile 错误,则表示 API 在 GDS 库中失败。您可以通过在 /etc/cufile.json 文件中设置适当的日志记录级别来启用跟踪,以获取有关 cufile.log
中故障的更多信息。
5.7. CUDA 运行时和驱动程序不匹配,错误代码为 35#
CUDA 文档中的错误代码 35 指向 cudaErrorInsufficientDriver
,这表示已安装的 NVIDIA CUDA 驱动程序比 CUDA 运行时库旧。这是不受支持的配置。要使应用程序运行,您必须更新 NVIDIA 显示驱动程序。
注意
cuFile 工具依赖于 CUDA 运行时 10.1 及更高版本。您必须确保安装的 CUDA 运行时与安装的 CUDA 驱动程序兼容,并且是推荐的版本。
5.8. 运行 cuFile-* API 时出现 CUDA API 错误#
GDS 库使用 CUDA 驱动程序 API。
如果您观察到 CUDA API 错误,您将观察到错误代码。有关更多信息,请参阅CUDA 库文档中的错误代码。
5.9. 查找 GDS 驱动程序统计信息#
要查找 GDS 驱动程序统计信息,请运行以下命令
$ cat /proc/driver/nvidia-fs/stats
GDS 驱动程序内核统计信息 READ
/ WRITE
适用于除 Weka 之外的所有文件系统。对于 Weka 文件系统统计信息,有关 READ
/ WRITE
的更多信息,请参阅WekaIO 文件系统的故障排除和常见问题解答。
5.10. 跟踪通过 GDS 驱动程序的 IO 活动#
在 GDS 驱动程序统计信息中,“ops”行显示活动 IO 操作。Read
和 Write
字段显示当前正在进行的活动操作。此信息应提供有关内核中所有应用程序正在进行的 IO 总数的概念。如果用户空间中存在瓶颈,则活动 IO 的数量将少于提交 IO 的线程数。此外,要获得有关 Read
和 Write
带宽数字的更多详细信息,请查找 Read
/Write
行中的计数器。
5.11. GDS 统计信息中的读取/写入带宽和延迟数字#
测量的延迟从提交 IO 时开始,到 GDS 内核驱动程序收到 IO 完成时结束。不报告用户空间延迟。这应提供有关用户空间是否受瓶颈限制或 IO 是否受后端磁盘/光纤通道瓶颈限制的概念。
注意
WekaIO 文件系统读取不通过 nvidia-fs 驱动程序,因此通过此接口,Read
/Write
带宽统计信息不适用于 WekaIO 文件系统。
有关更多信息,请参阅WekaIO 文件系统的故障排除和常见问题解答。
5.12. 跟踪 GPU 缓冲区的注册和注销#
在 GDS 驱动程序统计信息中,查找 BAR1-map 统计信息行中的活动字段。
通过 cuFileBufRegister
和 cuFileBufDeregister
固定和取消固定 GPU 内存是一项开销很大的操作。如果您注意到 nvidia-fs 统计信息中有大量的 registrations(n)
和 deregistration(free)
,则可能会损害性能。有关使用 cuFileBufRegister
API 的更多信息,请参阅GPUDirect Storage 最佳实践指南。
5.13. 为用户空间文件系统启用特定于 RDMA 的日志记录#
为了排除用户空间文件系统的 RDMA 相关问题,请确保在运行应用程序之前将 CUFILE_LOGGING_LEVEL
环境变量设置为 INFO
、DEBUG
或 TRACE
。但是,为了使此操作生效,cufile.json
日志记录级别也应设置为 TRACE/DEBUG/INFO
级别。
例如
$ export CUFILE_LOGGING_LEVEL=INFO
This is an example to set log level to INFO via the environment variable.
$ cat /etc/cufile.json
....
"logging": {
// log directory, if not enabled will create log file
// under current working directory
//"dir": "/home/<xxxx>",
// ERROR|WARN|INFO|DEBUG|TRACE (in decreasing order of priority)
"level": "DEBUG"
},
....
This is an example on how to set log level to DEBUG via cufile.json.
5.14. 安装后出现 CUDA_ERROR_SYSTEM_NOT_READY#
在具有 NVSwitch 的系统上,如果您注意到报告了 CUDA_ERROR_SYSTEM_NOT_READY 错误,请确保安装与 CUDA 驱动程序相同版本的 Fabric Manager。
例如,如果您使用
$ sudo apt install nvidia-driver-460-server -y
然后使用
$ apt-get install nvidia-fabricmanager-460
确保使用以下命令重启 Fabric Manager 服务
$ sudo service nvidia-fabricmanager start
5.15. 为 RAID 卷添加 udev 规则#
要为 RAID 卷添加 udev 规则
以 sudo 用户身份,更改 /lib/udev/rules.d/63-md-raid-arrays.rules
中的以下行
IMPORT{program}="/usr/sbin/mdadm --detail --export $devnode"
重启节点或重启 mdadm
。
5.16. 当您在 NVME 驱动器上观察到“写入不完整”时#
在 GDS 模式写入期间,您可能会收到类似于以下的错误消息
Tid: 0 incomplete Write, done = 0 issued = 1048576
P2P 模式下的 GPUDirect Storage 不支持 NVMe 端到端数据保护功能。要在 P2P 模式下支持 GDS,NVMe 必须使用保护信息格式化 - Metadata Size
设置为零字节。
确认驱动器已启用数据完整性模式
$ sudo nvme id-ns /dev/nvme0n1 -H
-
LBA Format 0 : Metadata Size: 0 bytes - Data Size: 512 bytes - Relative Performance: 0x1 Better
LBA Format 1 : Metadata Size: 8 bytes - Data Size: 512 bytes - Relative Performance: 0x3 Degraded (in use)
LBA Format 2 : Metadata Size: 0 bytes - Data Size: 4096 bytes - Relative Performance: 0 Best
LBA Format 3 : Metadata Size: 8 bytes - Data Size: 4096 bytes - Relative Performance: 0x2 Good
LBA Format 4 : Metadata Size: 64 bytes - Data Size: 4096 bytes - Relative Performance: 0x3 Degraded
请注意,在前面的示例中,驱动器 (nvme0n1) 的元数据大小设置为非零。
您可以将 LBA 格式设置为 0 或 2 以禁用驱动器上的保护功能
$ sudo nvme format /dev/nvme0n1 -l 2
$ sudo nvme id-ns /dev/nvme0n1 -H
-
LBA Format 0 : Metadata Size: 0 bytes - Data Size: 512 bytes - Relative Performance: 0x1 Better
LBA Format 1 : Metadata Size: 8 bytes - Data Size: 512 bytes - Relative Performance: 0x3 Degraded
LBA Format 2 : Metadata Size: 0 bytes - Data Size: 4096 bytes - Relative Performance: 0 Best (in use)
LBA Format 3 : Metadata Size: 8 bytes - Data Size: 4096 bytes - Relative Performance: 0x2 Good
LBA Format 4 : Metadata Size: 64 bytes - Data Size: 4096 bytes - Relative Performance: 0x3 Degraded
5.17. CUFILE 异步 I/O 失败#
基于流的异步 I/O 失败可能有多种原因。这将记录在 cufile.log
中。常见原因之一可能是未启用内部线程池。有关如何启用它的信息,请参阅 cufile.json
“execution”部分。
6. 高级故障排除#
本节提供有关排除一些高级问题的信息。
6.1. 解决无响应的挂起 cuFile* API#
要解决挂起的 cuFile API
检查
dmesg
中是否有任何内核崩溃/警告$ dmesg > warnings.txt. less warnings.txt
检查应用程序进程是否处于
D
(不可中断)状态。如果进程处于
D
状态通过运行以下命令获取进程的 PID
$ ps axf | grep ' D'
以 root 用户身份,获取
D
状态进程的回溯$ su root $ cat /proc/<pid>/stack
验证线程是否卡在内核中或用户空间中。有关更多信息,请查看
D
状态线程的回溯。检查是否有任何线程显示 CPU 使用率过高。
htop
和mpstat
工具应显示每个内核的 CPU 使用率。获取 CPU 使用位置的调用图。以下代码段应缩小线程是挂起在用户空间还是内核中的范围
$ perf top -g
6.2. 向客户支持发送相关数据#
本节介绍如何使用 NVSM 或 GDS 日志收集工具解决包含堆栈跟踪的内核崩溃问题。
DGX 操作系统
适用于启用预览网络仓库并安装了 NVSM 的 DGX BaseOS
$ sudo apt-get install nvsm
$ sudo nvsm dump health
有关运行 NVSM 命令的更多详细信息,请参阅 NVIDIA 系统管理用户指南。
非 DGX
GDS 用户可以运行 GDS 日志收集工具 gds_log_collection.py
,从系统中收集相关的调试信息,以便在出现 GDS IO 问题时使用。
以下突出显示了此工具捕获的一些重要信息
dmesg 输出和相关的内核日志文件。
系统映射文件和 vmlinux 镜像
相关模块的 modinfo 输出
/proc/cmdline
输出IB 设备信息,如 ibdev2net 和 ibstatus
操作系统发行版信息
Cpuinfo、meminfo
nvidia-fs 统计信息
每个进程的信息,如
cufile.log
、cufile.json
、gds_stats
、堆栈指针任何用户指定的文件
要使用日志收集工具
$ sudo /usr/local/cuda/gds//tools/gdstools/gds_log_collection.py -h
此工具用于从系统中收集与调试相关的日志。
它收集日志,例如操作系统和内核信息、nvidia-fs 统计信息、dmesg 日志、系统日志、系统映射文件以及每个进程的日志,例如 cufile.json
、cufile.log
、gdsstats、进程堆栈等等。
用法
./gds_log_collection.py [选项]
选项
-h
帮助
-f file1,file2,..
(注意:‘,’ 之间不应有空格)
这些文件可以是除正在收集的文件之外的任何相关文件(例如崩溃文件)。
用法示例
sudo ./gds_log_colection.py
- 收集所有相关日志。
sudo ./gds_log_colection.py -f file1,file2
- 收集所有相关文件以及用户指定的文件。
6.3. 解决 EIO 和堆栈跟踪警告导致的 IO 故障#
您可能会看到 EIO 导致的 IO 故障,以及包含 nvfs_mgroup_check_and_set
函数的堆栈跟踪警告。
这可能意味着 EXAScaler 文件系统没有遵守 O_DIRECT
,而是回退到页缓存模式。GDS 在驱动程序中跟踪此信息并返回 EIO。
注意
警告 堆栈跟踪仅在内核模块的生命周期内观察到一次。您将收到 Error: Input/Output (EIO)
错误,但跟踪消息仅打印一次。如果您持续遇到此问题,请联系支持部门。
6.4. 控制 GPU BAR 内存使用量#
要显示每个 GPU 可用的 BAR 内存量,请运行以下命令
$ /usr/local/cuda-x.y/gds/tools/gdscheck
查看输出,例如
GPU INFO:
GPU Index: 0 bar:1 bar size (MB):32768
GPU Index: 1 bar:1 bar size (MB):32768
GDS 在以下情况下使用 BAR 内存
当进程调用
cuFileBufRegister
时。当 GDS 在内部使用缓存为每个 GPU 分配反弹缓冲区时。
注意
缓存和 BAR 内存使用量没有每个 GPU 的配置。
每个进程都可以通过 /etc/cufile.json
文件中的可配置属性来控制 BAR 内存的使用。
"properties": {
// device memory size for reserving bounce buffers for the entire GPU (in KB)
"max_device_cache_size" : 131072,
// limit on maximum memory that can be pinned for a given process (in KB)
"max_device_pinned_mem_size" : 33554432
}
.. note::
This configuration is per process, and the configuration is set across all GPUs.
6.5. 确定要预留的缓存量#
默认情况下,在可配置的 max_device_cache_size
属性中设置了 128 MB 的缓存。但是,这并不意味着 GDS 预先为每个 GPU 分配了 128 MB 的内存。内存分配是根据需要动态完成的。分配完成后,不会清除缓存。
默认情况下,由于设置了 128 MB,缓存最多可以增长到 128 MB。设置缓存是特定于应用程序的,并且取决于工作负载。请参阅 GPUDirect Storage 最佳实践指南,以了解缓存的需求以及如何根据指南中的指导设置限制。
6.6. 监控 BAR 内存使用量#
没有办法监控每个进程的 BAR 内存使用量。但是,GDS 统计信息会跟踪所有进程的全局 BAR 使用量。有关更多信息,请参阅 GPU 为 B:D:F 0000:34:00.0
的 /proc/driver/nvidia_fs/stats
中的以下统计信息输出
GPU 0000:34:00.0 uuid:12a86a5e-3002-108f-ee49-4b51266cdc07 : Registered_MB=32 Cache_MB=10
Registered_MB
跟踪应用程序显式使用 cuFileBufRegister
API 时使用的 BAR 内存量。
Cache_MB
跟踪 GDS 用于内部缓存的 BAR 内存使用量。
6.7. 解决 ENOMEM 错误代码#
-12
ENOMEM 错误代码。
每个 GPU 都保留了一些 BAR 内存。cuFileBufRegister
函数使 GPU 虚拟内存范围下的页面可供第三方设备访问。此过程通过使用 nvidia_p2p_get_pages
API 将 GPU 设备内存固定在 BAR 空间中来完成。如果应用程序尝试固定的内存超出可用的 BAR 空间,则 nvidia_p2p_get_pages
API 将返回 -12
(ENOMEM) 错误代码。
为了避免 BAR 内存耗尽,开发人员应使用此输出来管理应用程序固定的内存量。管理员可以使用此输出来调查如何限制不同应用程序的固定内存。
6.8. GDS 和兼容模式#
要确定 GDS 兼容模式,请完成以下操作
在 /etc/cufile.json 文件中,验证
allow_compat_mode
是否设置为true
。gdscheck -p
显示allow_compat_mode
属性是否设置为true
。检查
cufile.log
文件中是否有cufile IO mode: POSIX
消息。此消息位于热 IO 路径中,在其中记录每个实例会显著影响性能,因此仅当
/etc/cufile.json
文件中的logging:level
显式设置为TRACE
模式时,才会记录该消息。
6.9. 启用兼容模式#
应用程序开发人员可以使用兼容模式在以下条件下测试启用 cuFile 的库的应用程序
当特定文件系统不支持 GDS 时。
管理员未在系统中启用
nvidia-fs.ko
驱动程序。
要启用兼容模式
移除
nvidia-fs
内核驱动程序$ rmmod nvidia-fs
在 /etc/cufile.json 文件中,将
compat-mode
设置为true
。将
CUFILE_FORCE_COMPAT_MODE
环境变量设置为 true。
现在,通过 cuFileRead
/cuFileWrite
的 IO 将回退到 CPU 路径。
6.10. 跟踪启用兼容模式后的 IO#
当 GDS 在兼容模式下使用,并且在 /etc/cufile.json
文件中启用了 cufile_stats
时,您可以使用 gds_stats
或其他标准 Linux 工具(例如 strace、iostat、iotop、SAR、ftrace 和 perf)。您还可以使用 BPF 编译器集合工具来跟踪和监控 IO。
启用兼容模式后,在内部,cuFileRead
和 cuFileWrite
分别使用 POSIX pread 和 pwrite 系统调用。
6.11. 绕过 GPUDirect Storage#
在某些情况下,您可以绕过 GDS。
有一些可调参数,GDS IO 和 POSIX IO 可以同时通过。以下是在无需移除 GDS 驱动程序的情况下可以绕过 GDS 的情况
在受支持的文件系统和块设备上。
在
/etc/cufile.json
文件中,如果posix_unaligned_writes
配置属性设置为true
,则未对齐的写入将回退到兼容模式,并且不会通过 GDS。有关受支持文件系统的列表,请参阅 安装 GDS 前的准备工作。在 EXAScaler 文件系统上
在 /etc/cufile.json 文件中,如果
posix_gds_min_kb config
属性设置为某个值(以 KB 为单位),则大小小于或等于设置值的 IO 将回退到 POSIX 模式。例如,如果posix_gds_min_kb
设置为 8KB,则大小小于或等于 8KB 的 IO 将回退到 POSIX 模式。在 WekaIO 文件系统上
注意
目前,
cuFileWrite
将始终回退到 POSIX 模式。
在 /etc/cufile.json
文件中,如果 allow-compat-mode config
属性设置为 true
如果无法建立 RDMA 连接和/或内存注册,
cuFileRead
将回退到 POSIX 模式。cuFileRead
无法为非 4K 对齐的 GPU VA 地址分配内部反弹缓冲区。
有关更多信息,请参阅 GPUDirect Storage 最佳实践指南。
6.12. GDS 不适用于挂载#
在以下情况下,GDS 将不用于挂载
当系统上未加载必要的 GDS 驱动程序时。
与该挂载点关联的文件系统不受 GDS 支持。
挂载点在 /etc/cufile.json 文件中被列入拒绝列表。
6.13. 在同一文件上同时运行 GPUDirect Storage IO 和 POSIX IO#
由于文件在 O_DIRECT
模式下为 GDS 打开,因此应用程序应避免将 O_DIRECT
和普通 I/O 混合用于同一文件以及同一文件中的重叠字节区域。
即使文件系统在这种情况下正确处理了数据一致性问题,总体 I/O 吞吐量也可能比单独使用任一模式要慢。同样,应用程序应避免将文件的 mmap(2)
与同一文件的直接 I/O 混合使用。有关其他 O_DIRECT
限制的信息,请参阅特定于文件系统的文档。
6.14. 使用 GPUDirect Storage 运行数据验证测试#
GDS 有一个内部数据验证实用程序 gdsio_verify
,用于测试读取和写入的数据完整性。运行 gdsio_verify -h
获取详细的用法信息。
例如
$ /usr/local/cuda-11.2/gds/tools/gds_verify -f /mnt/ai200/fio-seq-writes-1 -d 0 -o 0 -s 1G -n 1 -m 1
示例输出
gpu index :0,file :/mnt/ai200/fio-seq-writes-1, RING buffer size :0,
gpu buffer alignment :0, gpu buffer offset :0, file offset :0,
io_requested :1073741824, bufregister :true, sync :1, nr ios :1,
fsync :0,
address = 0x560d32c17000
Data Verification Success
注意
此测试完成通过 GDS 的读取和写入的数据验证。
7. 性能故障排除#
本节介绍与性能相关的问题。
7.1. 使用 GDS 运行性能基准测试#
您可以使用 GDS 运行性能基准测试,并将结果与 CPU 数字进行比较。
GDS 有一个自研的基准测试实用程序 /usr/local/cuda-x.y/gds/tools/gdsio
,可帮助您将 GDS IO 吞吐量数字与 CPU IO 吞吐量进行比较。运行 gdsio -h
获取详细的用法信息。
以下是一些示例
GDS:存储 –> GPU 内存
$ /usr/local/cuda-x.y/tools/gdsio -f /mnt/ai200/fio-seq-writes-1 -d 0 -w 4 -s 10G -i 1M -I 0 -x 0
存储 –> CPU 内存
$ /usr/local/cuda-x.y/tools/gdsio -f /mnt/ai200/fio-seq-writes-1 -d 0 -w 4 -s 10G -i 1M -I 0 -x 1
存储 –> CPU 内存 –> GPU 内存
$ /usr/local/cuda-x.y/tool/gdsio -f /mnt/ai200/fio-seq-writes-1 -d 0 -w 4 -s 10G -i 1M -I 0 -x 2
使用批处理模式的存储 –> GPU 内存
$ /usr/local/cuda-x.y/tool/gdsio -f /mnt/ai200/fio-seq-read-1 -d 0 -w 4 -s 10G -i 1M -I 0 -x 6
使用异步流模式的存储 –> GPU 内存
$ /usr/local/cuda-x.y/tool/gdsio -f /mnt/ai200/fio-seq-read-1 -d 0 -w 4 -s 10G -i 1M -I 0 -x 5
7.2. 跟踪 GPUDirect Storage 是否正在使用内部缓存#
您可以确定 GDS 是否正在使用内部缓存。
先决条件:在开始之前,请阅读 GPUDirect Storage 最佳实践指南。
GDS 统计信息具有每个 GPU 的统计信息,并显示 GPU 总线设备功能 (BDF) 信息的每一部分。如果 GPU 上的 cache_MB
字段处于活动状态,则 GDS 正在内部使用缓存来完成 IO。
当以下条件之一为真时,GDS 可能会使用内部缓存
在
cuFileRead
/cuFileWrite
中发出的file_offset
未 4K 对齐。cuFileRead
/cuFileWrite
调用中的大小未 4K 对齐。在
cuFileRead
/cuFileWrite
中发出的devPtr_base
未 4K 对齐。在
cuFileRead
/cuFileWrite
中发出的devPtr_base+devPtr_offset
未 4K 对齐。
7.3. 跟踪 IO 何时跨越 PCIe 根联合体并影响性能#
您可以跟踪 IO 何时跨越 PCIe 根联合体并影响性能。
有关更多信息,请参阅 检查内核文件系统和存储驱动程序的对等亲缘性统计信息。
7.4. 使用 GPUDirect 统计信息监控 CPU 活动#
虽然您不能使用 GDS 统计信息来监控 CPU 活动,但您可以使用以下 Linux 工具来完成此任务
htop
perf
mpstat
7.5. 使用 cuFile-* API 监控性能和跟踪#
您可以使用 cuFile-* API 监控性能和跟踪。
您可以使用 FTrace、Perf 或 BCC-BPF 工具来监控性能和跟踪。确保您拥有可用于使用标准 Linux IO 工具跟踪和监控性能的符号。
7.6. 示例:使用 Linux 跟踪工具#
cuFileBufRegister
函数使 GPU 虚拟内存范围下的页面可供第三方设备访问。此过程通过将 GPU 设备内存固定在 BAR 空间中来完成,这是一个开销很大的操作,可能需要几毫秒。
您可以使用 BCC/BPF 工具来跟踪 cuFileBufRegister
API,了解 Linux 内核中正在发生的事情,并了解为什么此过程开销很大。
场景
您正在运行一个包含 8 个线程的工作负载,其中每个线程都在发出
cuFileBufRegister
以固定到 GPU 内存。$ ./gdsio -f /mnt/ai200/seq-writes-1 -d 0 -w 8 -s 10G -i 1M -I 0 -x 0
当 IO 正在进行时,使用跟踪工具来了解
cuFileBufRegister
正在发生什么$ /usr/share/bcc/tools# ./funccount -Ti 1 nvfs_mgroup_pin_shadow_pages
查看示例输出
15:04:56 FUNC COUNT nvfs_mgroup_pin_shadow_pages 8
如您所见,
nvfs_mgroup_pin_shadow_pages
函数已被调用 8 次,每个线程一次。要查看该函数的延迟,请运行
$ /usr/share/bcc/tools# ./funclatency -i 1 nvfs_mgroup_pin_shadow_pages
查看输出
Tracing 1 functions for "nvfs_mgroup_pin_shadow_pages"... Hit Ctrl-C to end. nsecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 0 | | 64 -> 127 : 0 | | 128 -> 255 : 0 | | 256 -> 511 : 0 | | 512 -> 1023 : 0 | | 1024 -> 2047 : 0 | | 2048 -> 4095 : 0 | | 4096 -> 8191 : 0 | | 8192 -> 16383 : 1 |***** | 16384 -> 32767 : 7 |****************************************|
七次调用
nvfs_mgroup_pin_shadow_pages
函数大约花费了 16-32 微秒。这可能来自用于固定影子页面的 Linux 内核get_user_pages_fast
。cuFileBufRegister
调用nvidia_p2p_get_pages
NVIDIA 驱动程序函数,以将 GPU 设备内存固定在 BAR 空间中。此信息通过运行$ perf top -g
并获取cuFileBufRegister
的调用图来获得。
以下示例说明了 nvidia_p2p_get_pages
的开销
$ /usr/share/bcc/tools# ./funclatency -Ti 1 nvidia_p2p_get_pages
15:45:19
nsecs : count distribution
0 -> 1 : 0 | |
2 -> 3 : 0 | |
4 -> 7 : 0 | |
8 -> 15 : 0 | |
16 -> 31 : 0 | |
32 -> 63 : 0 | |
64 -> 127 : 0 | |
128 -> 255 : 0 | |
256 -> 511 : 0 | |
512 -> 1023 : 0 | |
1024 -> 2047 : 0 | |
2048 -> 4095 : 0 | |
4096 -> 8191 : 0 | |
8192 -> 16383 : 0 | |
16384 -> 32767 : 0 | |
32768 -> 65535 : 0 | |
65536 -> 131071 : 0 | |
131072 -> 262143 : 0 | |
262144 -> 524287 : 2 |************* |
524288 -> 1048575 : 6 |****************************************|
7.7. 跟踪 cuFile* API#
您可以使用 nvprof/NVIDIA Nsight 来跟踪 cuFile
* API。
NVTX 静态跟踪点可用于 libcufile.so
库中的公共接口。启用这些静态跟踪点后,您可以像查看任何其他 CUDA 符号一样在 NVIDIA Nsight 中查看这些跟踪。
您可以使用 /etc/cufile.json
中的 JSON 配置启用 NVTX 跟踪
"profile": {
// nvtx profiling on(true)/off(false)
"nvtx": true,
},
7.8. 使用动态路由提高性能#
在 GPU 和存储 NIC 之间的 IO 传输涉及跨 PCIe 主机桥的 PCIe 流量的平台上,GPUDirect Storage IO 可能看不到很高的吞吐量,尤其是在写入时。此外,某些芯片组可能仅支持主机桥流量的 P2P 读取流量。在这种情况下,可以启用动态路由功能来调试和识别哪种路由策略被认为最适合此类平台。这可以通过使用 gdsio
工具的单 GPU 写入测试来说明,其中有一个存储 NIC 和 10 个 GPU,并且 GPU 之间启用了 NVLINK 访问。启用动态路由后,即使 GPU 和 NIC 可能位于不同的插槽上,GDS 仍然可以实现最大可能的写入吞吐量。
$ cat /etc/cufile.json | grep rdma_dev
"rdma_dev_addr_list": [ "192.168.0.19" ],
动态路由关闭
$ cat /etc/cufile.json | grep routing
"rdma_dynamic_routing": false
$ for i in 0 1 2 3 4 5 6 7 8 9 10;
do
./gdsio -f /mnt/nfs/file1 -d $i -n 0 -w 4 -s 1G -i 1M -x 0 -I 1 -p -T 15 ;
done
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 45792256/4194304(KiB) IOSize: 1024(KiB) Throughput: 2.873560 GiB/sec, Avg_Latency: 1359.280174 usecs ops: 44719 total_time 15.197491 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 45603840/4194304(KiB) IOSize: 1024(KiB) Throughput: 2.867613 GiB/sec, Avg_Latency: 1363.891220 usecs ops: 44535 total_time 15.166344 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 42013696/4194304(KiB) IOSize: 1024(KiB) Throughput: 2.848411 GiB/sec, Avg_Latency: 1373.154082 usecs ops: 41029 total_time 14.066573 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 43517952/4194304(KiB) IOSize: 1024(KiB) Throughput: 2.880763 GiB/sec, Avg_Latency: 1358.207427 usecs ops: 42498 total_time 14.406582 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 34889728/4194304(KiB) IOSize: 1024(KiB) Throughput: 2.341907 GiB/sec, Avg_Latency: 1669.108902 usecs ops: 34072 total_time 14.207836 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 36955136/4194304(KiB) IOSize: 1024(KiB) Throughput: 2.325239 GiB/sec, Avg_Latency: 1680.001220 usecs ops: 36089 total_time 15.156790 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 37075968/4194304(KiB) IOSize: 1024(KiB) Throughput: 2.351491 GiB/sec, Avg_Latency: 1661.198487 usecs ops: 36207 total_time 15.036584 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 35066880/4194304(KiB) IOSize: 1024(KiB) Throughput: 2.235654 GiB/sec, Avg_Latency: 1748.638950 usecs ops: 34245 total_time 14.958656 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 134095872/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.940253 GiB/sec, Avg_Latency: 436.982682 usecs ops: 130953 total_time 14.304269 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 135974912/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.932070 GiB/sec, Avg_Latency: 437.334849 usecs ops: 132788 total_time 14.517998 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 174486528/4194304(KiB) IOSize: 1024(KiB) Throughput: 11.238476 GiB/sec, Avg_Latency: 347.603610 usecs ops: 170397 total_time 14.806573 secs
动态路由开启(启用 nvlinks)
$ cat /etc/cufile.json | grep routing
"rdma_dynamic_routing": true
"rdma_dynamic_routing_order": [ "GPU_MEM_NVLINKS"]
$ for i in 0 1 2 3 4 5 6 7 8 9 10;
do
./gdsio -f /mnt/nfs/file1 -d $i -n 0 -w 4 -s 1G -i 1M -x 0 -I 1 -p -T 15 ;
done
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 134479872/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.885214 GiB/sec, Avg_Latency: 437.942083 usecs ops: 131328 total_time 14.434092 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 138331136/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.891407 GiB/sec, Avg_Latency: 437.668104 usecs ops: 135089 total_time 14.837118 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 133800960/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.897250 GiB/sec, Avg_Latency: 437.305565 usecs ops: 130665 total_time 14.341795 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 133990400/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.888714 GiB/sec, Avg_Latency: 437.751327 usecs ops: 130850 total_time 14.375893 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 141934592/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.905190 GiB/sec, Avg_Latency: 437.032919 usecs ops: 138608 total_time 15.200055 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 133379072/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.892493 GiB/sec, Avg_Latency: 437.488259 usecs ops: 130253 total_time 14.304222 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 142271488/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.892426 GiB/sec, Avg_Latency: 437.660016 usecs ops: 138937 total_time 15.258004 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 134951936/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.890496 GiB/sec, Avg_Latency: 437.661177 usecs ops: 131789 total_time 14.476154 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 132667392/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.930203 GiB/sec, Avg_Latency: 437.420830 usecs ops: 129558 total_time 14.167817 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 137982976/4194304(KiB) IOSize: 1024(KiB) Throughput: 8.936189 GiB/sec, Avg_Latency: 437.123356 usecs ops: 134749 total_time 14.725608 secs
url index :0, urlname :192.168.0.2 urlport :18515
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 170469376/4194304(KiB) IOSize: 1024(KiB) Throughput: 11.231479 GiB/sec, Avg_Latency: 347.818052 usecs ops: 166474 total_time 14.474698 secs
8. IO 活动故障排除#
本节介绍与 IO 活动以及与 Linux 其余部分的交互相关的问题。
8.1. 管理页缓存和磁盘中数据的一致性#
使用 GDS 时,文件通常以 O_DIRECT
模式打开。当 IO 完成时,在 DIRECT IO 的上下文中,它会绕过页缓存。
从 CUDA 工具包 12.2(GDS 版本 1.7.x)开始,文件也可以以非 O_DIRECT 模式打开。即使在这种情况下,只要库软件认为合适,它也会遵循启用 GDS 的 O_DIRECT 路径。这默认情况下可以保持数据一致性。
在 EXAScaler 文件系统上
对于读取,IO 会绕过页缓存并直接从后端存储获取数据。
当发出写入时,
nvidia-fs
驱动程序将尝试刷新页缓存中偏移量-长度范围内的数据,然后再向 VFS 子系统发出写入。跟踪此信息的统计信息是
pg_cache
pg_cache_fail
pg_cache_eio
在 WekaIO 文件系统上
对于读取,IO 会绕过页缓存并直接从后端存储获取数据。
9. EXAScaler 文件系统 LNet 故障排除#
本节介绍如何排查 EXAScaler 文件系统的问题。
9.1. 确定 EXAScaler 文件系统客户端模块版本#
要检查 EXAScaler 文件系统客户端版本,请在安装 EXAScaler 文件系统后检查 dmesg。
注意
EXAScaler 服务器版本应为 EXA-5.2。
下表提供了已使用 DDN AI200 和 DDN AI400 系统测试过的客户端内核模块版本列表
DDN 客户端版本 |
内核版本 |
MLNX_OFED 版本 |
---|---|---|
2.12.3_ddn28 |
4.15.0 |
MLNX_OFED 4.7 |
2.12.3_ddn29 |
4.15.0 |
MLNX_OFED 4.7 |
2.12.3_ddn39 |
4.15.0 |
MLNX_OFED 5.1 |
2.12.5_ddn4 |
5.4.0 |
MLNX_OFED 5.1 |
2.12.6_ddn19 |
5.4.0 |
MLNX_OFED 5.3 |
要验证客户端版本,请运行以下命令
$ sudo lctl get_param version
示例输出
Lustre version: 2.12.3_ddn39
9.2. 检查客户端上的 LNet 网络设置#
要检查客户端上的 LNet 网络设置
运行以下命令。
$ sudo lnetctl net show:
查看输出,例如
net: - net type: lo
9.3. 检查对等节点的健康状况#
Lnet 健康值 1000 是网络接口可以报告的最佳值。任何小于 1000 的值都表示接口以降级模式运行,并且遇到了一些错误。
运行以下命令;
$ sudo lnetctl net show -v 3 | grep health
查看输出,例如
health stats: health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000
9.4. 检查多路导轨支持#
要验证是否支持多路导轨
运行以下命令
$ sudo lnetctl peer show | grep -i Multi-Rail:
查看输出,例如
Multi-Rail: True
9.5. 检查 GDS 对等亲缘性#
对于对等亲缘性,您需要检查预期的接口是否正被用于关联的 GPU。
下面的代码片段描述了一个在特定 GPU 上运行负载的测试。该测试验证执行发送和接收的接口是否是最近的接口,并且是否正确映射到 GPU。有关用于检查对等亲缘性的指标的更多信息,请参阅重置 nvidia-fs 统计信息 和 检查对等亲缘性统计信息以了解内核文件系统和存储驱动程序。
您可以为工具部分运行 gdsio
测试并监控 LNET 统计信息。有关更多信息,请参阅自述文件。在 gdsio
测试中,已在 GPU 0 上完成写入测试。NVIDIA DGX-2 平台上 GPU 0 的预期 NIC 接口是 ib0。lnetctl net
显示统计信息之前已捕获,并且在 gdsio
测试之后,您可以看到 RPC 发送和接收发生在 IB0 上。
运行
gdsio
测试。查看输出,例如
$ sudo lustre_rmmod $ sudo mount -t lustre 192.168.1.61@o2ib,192.168.1.62@o2ib:/ai200 /mnt/ai200/ $ sudo lnetctl net show -v 3 | grep health health stats: health value: 0 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 health stats: health value: 1000 $ sudo lnetctl net show -v 3 | grep -B 2 -i 'send_count\|recv_count' status: up statistics: send_count: 0 recv_count: 0 -- 0: ib0 statistics: send_count: 3 recv_count: 3 -- 0: ib2 statistics: send_count: 3 recv_count: 3 -- 0: ib3 statistics: send_count: 2 recv_count: 2 -- 0: ib4 statistics: send_count: 13 recv_count: 13 -- 0: ib5 statistics: send_count: 12 recv_count: 12 -- 0: ib6 statistics: send_count: 12 recv_count: 12 -- 0: ib7 statistics: send_count: 11 recv_count: 11 $ echo 1 > /sys/module/nvidia_fs/parameters/peer_stats_enabled $ /usr/local/cuda-x.y/tools/gdsio -f /mnt/ai200/test -d 0 -n 0 -w 1 -s 1G -i 4K -x 0 -I 1 IoType: WRITE XferType: GPUD Threads: 1 DataSetSize: 1073741824/1073741824 IOSize: 4(KB),Throughput: 0.004727 GB/sec, Avg_Latency: 807.026154 usecs ops: 262144 total_time 211562847.000000 usecs $ sudo lnetctl net show -v 3 | grep -B 2 -i 'send_count\|recv_count' status: up statistics: send_count: 0 recv_count: 0 -- 0: ib0 statistics: send_count: 262149 recv_count: 524293 -- 0: ib2 statistics: send_count: 6 recv_count: 6 -- 0: ib3 statistics: send_count: 6 recv_count: 6 -- 0: ib4 statistics: send_count: 33 recv_count: 33 -- 0: ib5 statistics: send_count: 32 recv_count: 32 -- 0: ib6 statistics: send_count: 32 recv_count: 32 -- 0: ib7 statistics: send_count: 32 recv_count: 32 $ cat /proc/driver/nvidia-fs/peer_affinity GPU P2P DMA distribution based on pci-distance (last column indicates p2p via root complex) GPU :0000:be:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:3b:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e7:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e5:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e0:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:57:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:39:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:36:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e2:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:59:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:b7:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:b9:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:bc:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:34:00.0 :0 0 23872512 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:5e:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:5c:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9.6. 检查 LNet 级别错误#
这些错误会影响各个 NIC 的健康状况,并影响 EXAScaler 文件系统如何选择最佳对等节点,从而影响 GDS 性能。
注意
要运行这些命令,您必须具有 sudo 权限。
运行以下命令
$ cat /proc/driver/nvidia-fs/peer_affinity
查看输出,例如
GPU P2P DMA distribution based on pci-distance (last column indicates p2p via root complex) GPU :0000:be:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:3b:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e7:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e5:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e0:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:57:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1276417 (Note : if peer traffic goes over Root-Port, one of the reasons might be that health of nearest NIC might be affected) GPU :0000:39:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:36:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e2:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:59:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:b7:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:b9:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:bc:00.0 :0 0 7056141 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:34:00.0 :0 0 8356175 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:5e:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:5c:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 $ sudo lnetctl stats show statistics: msgs_alloc: 1 msgs_max: 126 rst_alloc: 25 errors: 0 send_count: 243901 resend_count: 1 response_timeout_count: 1935 local_interrupt_count: 0 local_dropped_count: 208 local_aborted_count: 0 local_no_route_count: 0 local_timeout_count: 1730 local_error_count: 0 remote_dropped_count: 0 remote_error_count: 0 remote_timeout_count: 0 network_timeout_count: 0 recv_count: 564436 route_count: 0 drop_count: 0 send_length: 336176013248 recv_length: 95073248 route_length: 0 drop_length: 0 lnetctl net show -v 4 net: - net type: o2ib local NI(s): - nid: 192.168.1.71@o2ib status: up interfaces: 0: ib0 statistics: send_count: 171621 recv_count: 459717 drop_count: 0 sent_stats: put: 119492 get: 52129 reply: 0 ack: 0 hello: 0 received_stats: put: 119492 get: 0 reply: 340225 ack: 0 hello: 0 dropped_stats: put: 0 get: 0 reply: 0 ack: 0 hello: 0 health stats: health value: 1000 interrupts: 0 dropped: 0 aborted: 0 no route: 0 timeouts: 0 error: 0 tunables: peer_timeout: 180 peer_credits: 32 peer_buffer_credits: 0 credits: 256 peercredits_hiw: 16 map_on_demand: 1 concurrent_sends: 64 fmr_pool_size: 512 fmr_flush_trigger: 384 fmr_cache: 1 ntx: 512 conns_per_peer: 1 lnd tunables: dev cpt: 0 tcp bonding: 0 CPT: "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]" - nid: 192.168.2.71@o2ib status: up interfaces: 0: ib1 statistics: send_count: 79 recv_count: 79 drop_count: 0 sent_stats: put: 78 get: 1 reply: 0 ack: 0 hello: 0 received_stats: put: 78 get: 0 reply: 1 ack: 0 hello: 0 dropped_stats: put: 0 get: 0 reply: 0 ack: 0 hello: 0 health stats: health value: 979 interrupts: 0 dropped: 0 aborted: 0 no route: 0 timeouts: 1 error: 0 tunables: peer_timeout: 180 peer_credits: 32 peer_buffer_credits: 0 credits: 256 peercredits_hiw: 16 map_on_demand: 1 concurrent_sends: 64 fmr_pool_size: 512 fmr_flush_trigger: 384 fmr_cache: 1 ntx: 512 conns_per_peer: 1 lnd tunables: dev cpt: 0 tcp bonding: 0 CPT: "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]" - nid: 192.168.2.72@o2ib status: up interfaces: 0: ib3 statistics: send_count: 52154 recv_count: 52154 drop_count: 0 sent_stats: put: 25 get: 52129 reply: 0 ack: 0 hello: 0 received_stats: put: 25 get: 52129 reply: 0 ack: 0 hello: 0 dropped_stats: put: 0 get: 0 reply: 0 ack: 0 hello: 0 health stats: health value: 66 interrupts: 0 dropped: 208 aborted: 0 no route: 0 timeouts: 1735 error: 0 tunables: peer_timeout: 180 peer_credits: 32 peer_buffer_credits: 0 credits: 256 peercredits_hiw: 16 map_on_demand: 1 concurrent_sends: 64 fmr_pool_size: 512 fmr_flush_trigger: 384 fmr_cache: 1 ntx: 512 conns_per_peer: 1 lnd tunables: dev cpt: 0 tcp bonding: 0 CPT: "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]"
如果您看到递增的错误统计信息,请捕获网络日志记录并提供此信息以进行调试
$ lctl set_param debug=+net
# reproduce the problem
$ lctl dk > logfile.dk
9.7. 解决 LNet NID 因超时导致的健康状况下降问题#
对于 DGX 等具有多个接口的大型机器,如果 Linux 路由设置不正确,可能会出现连接故障和其他意外行为。
用于解决本地连接超时的典型网络设置是
sysctl -w net.ipv4.conf.all.accept_local=1
还有用于解决 LNet 网络问题的通用指针。有关更多信息,请参阅 MR 集群设置。
9.8. 配置具有多个 OST 的 LNet 网络以实现最佳对等节点选择#
当有多个 OST(对象存储目标),并且每个 OST 都是双接口时,您需要在客户端配置的每个 LNet 上都拥有一个接口。
例如,客户端侧有以下两个 LNet 子网
o2ib
o2ib1
服务器只有一个 Lnet 子网,o2ib
。在这种情况下,路由不是最佳的,因为您将 IB 选择逻辑限制为一组设备,这些设备可能不是离 GPU 最近的设备。除了连接到 OST2 的 LNet 之外,没有其他方法可以访问 OST2。
流向此 OST 的流量永远不是最佳的,并且此配置可能会影响整体吞吐量和延迟。但是,如果您将服务器配置为使用两个网络 o2ib0
和 o2ib1
,则可以通过这两个网络访问 OST1 和 OST2。当选择算法运行时,它将确定最佳路径是例如通过 o2ib1
的 OST2。
要配置客户端 LNET,请运行以下命令
$ sudo lnetctl net show
查看输出,例如
net: - net type: lo local NI(s): - nid: 0@lo status: up - net type: o2ib local NI(s): - nid: 192.168.1.71@o2ib status: up interfaces: 0: ib0 - nid: 192.168.1.72@o2ib status: up interfaces: 0: ib2 - nid: 192.168.1.73@o2ib status: up interfaces: 0: ib4 - nid: 192.168.1.74@o2ib status: up interfaces: 0: ib6 - net type: o2ib1 local NI(s): - nid: 192.168.2.71@o2ib1 status: up interfaces: 0: ib1 - nid: 192.168.2.72@o2ib1 status: up interfaces: 0: ib3 - nid: 192.168.2.73@o2ib1 status: up interfaces: 0: ib5 - nid: 192.168.2.74@o2ib1 status: up interfaces: 0: ib7
对于最佳配置,LNet 对等节点应显示两个 LNet 子网。
在这种情况下,主要 nid
只有一个 o2ib
$ sudo lnetctl peer show
示例输出
peer:
- primary nid: 192.168.1.62@o2ib
Multi-Rail: True
peer ni:
- nid: 192.168.1.62@o2ib
state: NA
- nid: 192.168.2.62@o2ib1
state: NA
- primary nid: 192.168.1.61@o2ib
Multi-Rail: True
peer ni:
- nid: 192.168.1.61@o2ib
state: NA
- nid: 192.168.2.61@o2ib1
state: NA
从服务器端,这是一个次优 LNet 配置的示例
[root@ai200-090a-vm01 ~]# lnetctl net show
net:
- net type: lo
local NI(s):
- nid: 0@lo
status: up
- net type: o2ib (o2ib1 is not present)
local NI(s):
- nid: 192.168.1.62@o2ib
status: up
interfaces:
0: ib0
- nid: 192.168.2.62@o2ib
status: up
interfaces:
0: ib1
这是一个非最佳情况的 IB 配置示例,其中文件被条带化到两个 OST 上,并且存在顺序读取
$ ibdev2netdev -v
0000:b8:00.1 mlx5_13 (MT4123 - MCX653106A-ECAT) ConnectX-6 VPI adapter card, 100Gb/s (HDR100, EDR IB and 100GbE), dual-port QSFP56 fw 20.26.4012 port 1 (ACTIVE) ==> ib4 (Up) (o2ib)
ib4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 2044
inet 192.168.1.73 netmask 255.255.255.0 broadcast 192.168.1.255
0000:bd:00.1 mlx5_15 (MT4123 - MCX653106A-ECAT) ConnectX-6 VPI adapter card, 100Gb/s (HDR100, EDR IB and 100GbE), dual-port QSFP56 fw 20.26.4012 port 1 (ACTIVE) ==> ib5 (Up) (o2ib1)
ib5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 2044
inet 192.168.2.73 netmask 255.255.255.0 broadcast 192.168.2.255
$ cat /proc/driver/nvidia-fs/peer_distance | grep 0000:be:00.0 | grep network
0000:be:00.0 0000:58:00.1 138 0 network
0000:be:00.0 0000:58:00.0 138 0 network
0000:be:00.0 0000:86:00.1 134 0 network
0000:be:00.0 0000:35:00.0 138 0 network
0000:be:00.0 0000:5d:00.0 138 0 network
0000:be:00.0 0000:bd:00.0 3 0 network
0000:be:00.0 0000:b8:00.1 7 30210269 network (ib4) (chosen peer)
0000:be:00.0 0000:06:00.0 134 0 network
0000:be:00.0 0000:0c:00.1 134 0 network
0000:be:00.0 0000:e6:00.0 138 0 network
0000:be:00.0 0000:3a:00.1 138 0 network
0000:be:00.0 0000:e1:00.0 138 0 network
0000:be:00.0 0000:bd:00.1 3 4082933 network (ib5) (best peer)
0000:be:00.0 0000:e6:00.1 138 0 network
0000:be:00.0 0000:86:00.0 134 0 network
0000:be:00.0 0000:35:00.1 138 0 network
0000:be:00.0 0000:e1:00.1 138 0 network
0000:be:00.0 0000:0c:00.0 134 0 network
0000:be:00.0 0000:b8:00.0 7 0 network
0000:be:00.0 0000:5d:00.1 138 0 network
0000:be:00.0 0000:3a:00.0 138 0 network
这是一个最佳 LNet 配置的示例
[root@ai200-090a-vm00 ~]# lnetctl net show
net:
- net type: lo
local NI(s):
- nid: 0@lo
status: up
- net type: o2ib
local NI(s):
- nid: 192.168.1.61@o2ib
status: up
interfaces:
0: ib0
- net type: o2ib1
local NI(s):
- nid: 192.168.2.61@o2ib1
status: up
interfaces:
0: ib1
10. 了解 EXAScaler 文件系统性能#
根据主机通道适配器 (HCA)(通常称为 NIC)的类型,可以调整 LNet 的 mod 参数。您选择的 NIC 应处于正常和健康状态。
要通过挂载和运行一些基本测试来验证健康状况,请使用 lnetctl
健康统计信息,并运行以下命令
$ cat /etc/modprobe.d/lustre.conf
示例输出
options libcfs cpu_npartitions=24 cpu_pattern=""
options lnet networks="o2ib0(ib1,ib2,ib3,ib4,ib6,ib7,ib8,ib9)"
options ko2iblnd peer_credits=32 concurrent_sends=64 peer_credits_hiw=16 map_on_demand=0
10.1. osc 调优性能参数#
以下是有关调优文件系统参数的信息。
注意
要最大化吞吐量,您可以根据网络调优以下 EXAScaler 文件系统客户端参数。
运行以下命令
$ lctl get_param osc.*.max* osc.*.checksums
查看输出,例如
$ lctl get_param osc.*.max* osc.*.checksums
osc.ai400-OST0024-osc-ffff916f6533a000.max_pages_per_rpc=4096
osc.ai400-OST0024-osc-ffff916f6533a000.max_dirty_mb=512
osc.ai400-OST0024-osc-ffff916f6533a000.max_rpcs_in_flight=32
osc.ai400-OST0024-osc-ffff916f6533a000.checksums=0
要检查 llite 参数,请运行 $ lctl get_param llite.*.*
。
10.2. osc、mdc 和 stripesize 的其他命令#
如果正确设置了调优参数,您可以使用这些参数进行观察。
要获取 EXAScaler 文件系统客户端侧的总体统计信息,请运行以下命令
$ lctl get_param osc.*.import
注意
该命令包括
rpc
信息。查看输出,例如
$ watch -d 'lctl get_param osc.*.import | grep -B 1 inflight' rpcs: inflight: 5 rpcs: inflight: 33
要获取 EXAScaler 文件系统客户端中每个 rpc 可以传输的最大页数,请运行以下命令
$ lctl get_param osc.*.max_pages_per_rpc
要从 EXAScaler 文件系统客户端获取总体 RPC 统计信息,请运行以下命令
$ lctl set_param osc.*.rpc_stats=clear (to reset osc stats) $ lctl get_param osc.*.rpc_stats
查看输出,例如
osc.ai200-OST0000-osc-ffff8e0b47c73800.rpc_stats= snapshot_time: 1589919461.185215594 (secs.nsecs) read RPCs in flight: 0 write RPCs in flight: 0 pending write pages: 0 pending read pages: 0 read write pages per rpc rpcs % cum % | rpcs % cum % 1: 14222350 77 77 | 0 0 0 2: 0 0 77 | 0 0 0 4: 0 0 77 | 0 0 0 8: 0 0 77 | 0 0 0 16: 0 0 77 | 0 0 0 32: 0 0 77 | 0 0 0 64: 0 0 77 | 0 0 0 128: 0 0 77 | 0 0 0 256: 4130365 22 100 | 0 0 0 read write rpcs in flight rpcs % cum % | rpcs % cum % 0: 0 0 0 | 0 0 0 1: 3236263 17 17 | 0 0 0 2: 117001 0 18 | 0 0 0 3: 168119 0 19 | 0 0 0 4: 153295 0 20 | 0 0 0 5: 91598 0 20 | 0 0 0 6: 42476 0 20 | 0 0 0 7: 17578 0 20 | 0 0 0 8: 9454 0 20 | 0 0 0 9: 7611 0 20 | 0 0 0 10: 7772 0 20 | 0 0 0 11: 8914 0 21 | 0 0 0 12: 9350 0 21 | 0 0 0 13: 8559 0 21 | 0 0 0 14: 8734 0 21 | 0 0 0 15: 10784 0 21 | 0 0 0 16: 11386 0 21 | 0 0 0 17: 13148 0 21 | 0 0 0 18: 15473 0 21 | 0 0 0 19: 17619 0 21 | 0 0 0 20: 18851 0 21 | 0 0 0 21: 21853 0 21 | 0 0 0 22: 21236 0 21 | 0 0 0 23: 21588 0 22 | 0 0 0 24: 23859 0 22 | 0 0 0 25: 24049 0 22 | 0 0 0 26: 26232 0 22 | 0 0 0 27: 29853 0 22 | 0 0 0 28: 31992 0 22 | 0 0 0 29: 43626 0 22 | 0 0 0 30: 116116 0 23 | 0 0 0 31: 14018326 76 100 | 0 0 0
要获取与客户端元数据操作相关的统计信息,请运行以下命令
注意
元数据客户端 (MDC) 是元数据服务器 (MDS) 的客户端对应部分。
$ lctl get_param mdc.*.md_stats
要获取 EXAScaler 文件系统上文件的条带布局,请运行以下命令
$ lfs getstripe /mnt/ai200
10.3. 获取配置的基于对象的磁盘数量#
要获取配置的基于对象的磁盘数量
运行以下命令
$ lctl get_param lov.*.target_obd
查看输出,例如
0: ai200-OST0000_UUID ACTIVE 1: ai200-OST0001_UUID ACTIVE
10.5. 获取元数据统计信息#
要获取元数据统计信息
运行以下命令
$ lctl get_param lmv.*.md_stats
查看输出,例如
snapshot_time 1571271931.653827773 secs.nsecs close 8 samples [reqs] create 1 samples [reqs] getattr 1 samples [reqs] intent_lock 81 samples[reqs] read_page 3 samples [reqs] revalidate_lock 1 samples [reqs]
10.6. 检查现有挂载#
要检查 EXAScaler 文件系统中是否存在现有挂载
运行以下命令
$ mount | grep lustre
查看输出,例如
192.168.1.61@o2ib,192.168.1.62@o2ib1:/ai200 on /mnt/ai200 type lustre (rw,flock,lazystatfs)
10.7. 卸载 EXAScaler 文件系统集群#
要卸载 EXAScaler 文件系统集群,请运行以下命令
$ sudo umount /mnt/ai200
10.8. 获取 EXAScaler 文件系统统计信息摘要#
您可以获取 EXAScaler 文件系统的统计信息摘要。
有关更多信息,请参阅 Lustre 监控和统计信息指南。
10.9. 在轮询模式下使用 GPUDirect 存储#
本节介绍如何将 GDS 与条带计数大于 1 的 EXAScaler 文件系统文件在轮询模式下一起使用。
当前,如果启用轮询模式,则 cuFileReads
或 cuFileWrites
可能会返回少于请求字节数的字节。此行为符合 POSIX 标准,并且在使用条带计数大于其布局中计数的文件的时观察到。如果发生此行为,我们建议应用程序检查返回的字节并继续,直到所有数据都被消耗。您还可以将相应的 properties.poll_mode_max_size_kb,(例如 1024(KB))
值设置为目录中可能的最低条带大小。这确保了超过此限制的 IO 大小不会被轮询。
要检查 EXAScaler 文件系统文件布局,请运行以下命令。
$ lfs getstripe <file-path>
查看输出,例如
lfs getstripe /mnt/ai200/single_stripe/md1.0.0 /mnt/ai200/single_stripe/md1.0.0 lmm_stripe_count: 1 lmm_stripe_size: 1048576 lmm_pattern: raid0 lmm_layout_gen: 0 lmm_stripe_offset: 0 obdidx objid objid group 0 6146 0x1802 0
11. WekaIO 文件系统的故障排除和常见问题解答#
本节提供有关 WekaIO 文件系统的故障排除和常见问题解答信息。
11.1. 下载 WekaIO 客户端软件包#
要下载 WekaIO 客户端软件包,请运行以下命令
$ curl http://<IP of one of the WekaIO hosts' IB interface>:14000/dist/v1/install | sh
例如,$ curl http://172.16.8.1:14000/dist/v1/install | sh
。
11.2. 确定 WekaIO 版本是否已准备好用于 GDS#
要确定 WekaIO 版本是否已准备好用于 GDS
运行以下命令
$ weka version
查看输出,例如
* 3.6.2.5-rdma-beta
注意
当前,唯一支持 GDS 的 WekaIO FS 版本是
* 3.6.2.5-rdma-beta
11.3. 挂载 WekaIO 文件系统集群#
WekaIO 文件系统可以采用参数来为用户空间进程保留固定数量的核心。
要挂载
server_ip 172.16.8.1
并使用两个专用核心,请运行以下命令$ mkdir -p /mnt/weka $ sudo mount -t wekafs -o num_cores=2 -o net=ib0,net=ib1,net=ib2,net=ib3,net=ib4,net=ib5,net=ib6,net=ib7 172.16.8.1/fs01 /mnt/weka
查看输出,例如
Mounting 172.16.8.1/fs01 on /mnt/weka Creating weka container Starting container Waiting for container to join cluster Container "client" is ready (pid = 47740) Calling the mount command Mount completed successfully
11.4. 解决挂载失败问题#
在挂载选项中使用 IB 接口之前,请验证是否为
net=<interface>
设置了接口$ sudo mount -t wekafs -o num_cores=2 -o net=ib0,net=ib1,net=ib2,net=ib3,net=ib4,net=ib5,net=ib6,net=ib7 172.16.8.1/fs01 /mnt/weka
查看输出,例如
Mounting 172.16.8.1/fs01 on /mnt/weka Creating weka container Starting container Waiting for container to join cluster error: Container "client" has run into an error: Resources assignment failed: IB/MLNX network devices should have pre-configured IPs and ib4 has none
从挂载选项中删除没有网络连接的接口。
$ ibdev2netdev mlx5_0 port 1 ==> ib0 (Up) mlx5_1 port 1 ==> ib1 (Up) mlx5_2 port 1 ==> ib2 (Up) mlx5_3 port 1 ==> ib3 (Up) mlx5_4 port 1 ==> ib4 (Down) mlx5_5 port 1 ==> ib5 (Down) mlx5_6 port 1 ==> ib6 (Up) mlx5_7 port 1 ==> ib7 (Up) mlx5_8 port 1 ==> ib8 (Up) mlx5_9 port 1 ==> ib9 (Up)
11.5. 解决 WekaIO 双核 100% 使用率问题#
如果您有两个核心,并且遇到 100% CPU 使用率
运行以下命令。
$ top
查看输出,例如
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 54816 root 20 0 11.639g 1.452g 392440 R 94.4 0.1 781:06.06 wekanode 54825 root 20 0 11.639g 1.452g 392440 R 94.4 0.1 782:00.32 wekanode
当指定
num_cores=2
参数时,两个核心用于 WekaIO FE 网络的用户模式轮询驱动程序。此过程提高了延迟和性能。有关更多信息,请参阅 WekaIO 文档。
11.6. 检查 Weka 文件系统中是否存在现有挂载#
要检查 WekaIO 文件系统中是否存在现有挂载
运行以下命令
$ mount | grep wekafs
查看输出,例如
172.16.8.1/fs01 on /mnt/weka type wekafs ( rw,relatime,writecache,inode_bits=auto,dentry_max_age_positive=1000, dentry_max_age_negative=0)
11.7. 检查 WekaIO 文件系统状态摘要#
要检查 WekaIO 文件系统状态摘要。
运行以下命令
$ weka status
查看输出,例如
WekaIO v3.6.2.5-rdma-beta (CLI build 3.6.2.5-rdma-beta) cluster: Nvidia (e4a4e227-41d0-47e5-aa70-b50688b31f40) status: OK (12 backends UP, 72 drives UP) protection: 8+2 hot spare: 2 failure domains (62.84 TiB) drive storage: 62.84 TiB total, 819.19 MiB unprovisioned cloud: connected license: Unlicensed io status: STARTED 1 day ago (1584 buckets UP, 228 io-nodes UP) link layer: InfiniBand clients: 1 connected reads: 61.54 GiB/s (63019 IO/s) writes: 0 B/s (0 IO/s) operations: 63019 ops/s alerts: 3 active alerts, use `Wekaalerts` to list them
11.8. 显示 WekaIO 文件系统统计信息摘要#
要显示 WekaIO 文件系统状态摘要
运行以下命令。
$ cat /proc/wekafs/stat
查看输出,例如
IO type: UM Average UM Longest KM Average KM Longest IO count -------------------------------------------------------------------------------------------------------------------------------- total: 812 us 563448 us 9398 ns 10125660 ns 718319292 (63260 IOPS, 0 MB/sec) lookup: 117 us 3105 us 6485 ns 436709 ns 4079 (12041) readdir: 0 us 0 us 0 ns 0 ns 0 mknod: 231 us 453 us 3970 ns 6337 ns 96 open: 0 us 0 us 0 ns 0 ns 0 (3232) release: 0 us 0 us 0 ns 0 ns 0 (2720) read: 0 us 0 us 0 ns 0 ns 0 write: 18957 us 563448 us 495291 ns 920127 ns 983137 (983041) getattr: 10 us 10 us 6771 ns 6771 ns 1 (9271) setattr: 245 us 424 us 4991 ns 48222 ns 96 rmdir: 0 us 0 us 0 ns 0 ns 0 unlink: 0 us 0 us 0 ns 0 ns 0 rename: 0 us 0 us 0 ns 0 ns 0 symlink: 0 us 0 us 0 ns 0 ns 0 readlink: 0 us 0 us 0 ns 0 ns 0 hardlink: 0 us 0 us 0 ns 0 ns 0 statfs: 4664 us 5072 us 38947 ns 59618 ns 7 SG_release: 0 us 0 us 0 ns 0 ns 0 SG_allocate: 1042 us 7118 us 2161 ns 110282 ns 983072 falloc: 349 us 472 us 4184 ns 10239 ns 96 atomic_open: 0 us 0 us 0 ns 0 ns 0 flock: 0 us 0 us 0 ns 0 ns 0 backcomm: 0 us 0 us 0 ns 0 ns 0 getroot: 19701 us 19701 us 57853 ns 57853 ns 1 trace: 0 us 0 us 0 ns 0 ns 0 jumbo alloc: 0 us 0 us 0 ns 0 ns 0 jumbo release: 0 us 0 us 0 ns 0 ns 0 jumbo write: 0 us 0 us 0 ns 0 ns 0 jumbo read: 0 us 0 us 0 ns 0 ns 0 keepalive: 46 us 1639968 us 1462 ns 38996 ns 184255 ioctl: 787 us 50631 us 8732 ns 10125660 ns 717328710 setxattr: 0 us 0 us 0 ns 0 ns 0 getxattr: 0 us 0 us 0 ns 0 ns 0 listxattr: 0 us 0 us 0 ns 0 ns 0 removexattr: 0 us 0 us 0 ns 0 ns 0 setfileaccess: 130 us 3437 us 6440 ns 71036 ns 3072 unmount: 0 us 0 us 0 ns 0 ns 0
11.9. 为什么 WekaIO 写入通过 POSIX#
对于 WekaIO 文件系统,GDS 支持基于 RDMA 的读取和写入。您可以使用 fs:weka:rdma_write_support
JSON 属性在支持的 Weka 文件系统上启用写入。默认情况下,此选项处于禁用状态。如果此选项设置为 false,则写入将在内部通过系统内存暂存,并且 cuFile 库将在内部使用 pwrite POSIX 调用进行写入。
11.10. 检查 nvidia-fs.ko 对内存对等直连的支持#
要检查 nvidia-fs.ko
对内存对等直连的支持
运行以下命令
$ lsmod | grep nvidia_fs | grep ib_core && echo "Ready for Memory Peer Direct"
查看输出,例如
ib_core 319488 16 rdma_cm,ib_ipoib,mlx4_ib,ib_srp,iw_cm,nvidia_fs,ib_iser,ib_umad, rdma_ucm,ib_uverbs,mlx5_ib,ib_cm,ib_ucm "Ready for Memory Peer Direct"
11.11. 检查内存对等直连统计信息#
要检查内存对等统计信息
运行以下脚本,该脚本显示内存对等直连统计信息的计数器
list=`ls /sys/kernel/mm/memory_peers/nvidia-fs/`. for stat in $list . do echo "$stat value: " $(cat /sys/kernel/mm/memory_peers/nvidia-fs/$stat). done
查看输出。
num_alloc_mrs value: 1288 num_dealloc_mrs value: 1288 num_dereg_bytes value: 1350565888 num_dereg_pages value: 329728 num_free_callbacks value: 0 num_reg_bytes value: 1350565888 num_reg_pages value: 329728 version value: 1.0
11.12. 检查 WekaIO 文件系统的相关 nvidia-fs 统计信息#
要检查 WekaIO 文件系统的相关 nvida-fs
统计信息
运行以下命令
$ cat /proc/driver/nvidia-fs/stats | egrep -v 'Reads|Writes|Ops|Error'
查看输出,例如
GDS Version: 1.0.0.80 NVFS statistics(ver: 4.0) NVFS Driver(version: 2.7.49) Active Shadow-Buffer (MB): 256 Active Process: 1 Mmap : n=2088 ok=2088 err=0 munmap=1832 Bar1-map : n=2088 ok=2088 err=0 free=1826 callbacks=6 active=256 GPU 0000:34:00.0 uuid:12a86a5e-3002-108f-ee49-4b51266cdc07 : Registered_MB=32 Cache_MB=0 max_pinned_MB=1977 GPU 0000:e5:00.0 uuid:4c2c6b1c-27ac-8bed-8e88-9e59a5e348b5 : Registered_MB=32 Cache_MB=0 max_pinned_MB=32 GPU 0000:b7:00.0 uuid:b224ba5e-96d2-f793-3dfd-9caf6d4c31d8 : Registered_MB=32 Cache_MB=0 max_pinned_MB=32 GPU 0000:39:00.0 uuid:e8fac7f5-d85d-7353-8d76-330628508052 : Registered_MB=32 Cache_MB=0 max_pinned_MB=32 GPU 0000:5c:00.0 uuid:2b13ed25-f0ab-aedb-1f5c-326745b85176 : Registered_MB=32 Cache_MB=0 max_pinned_MB=32 GPU 0000:e0:00.0 uuid:df46743a-9b22-30ce-6ea0-62562efaf0a2 : Registered_MB=32 Cache_MB=0 max_pinned_MB=32 GPU 0000:bc:00.0 uuid:c4136168-2a1d-1f3f-534c-7dd725fedbff : Registered_MB=32 Cache_MB=0 max_pinned_MB=32 GPU 0000:57:00.0 uuid:54e472f2-e4ee-18dc-f2a1-3595fa8f3d33 : Registered_MB=32 Cache_MB=0 max_pinned_MB=32
注意
读取、写入、操作和错误计数器无法通过此接口用于 WekaIO 文件系统,因此该值将为零。有关使用 Weka 状态进行读取和写入的信息,请参阅 显示 WekaIO 文件系统统计信息摘要。
11.13. 进行基本 WekaIO 文件系统测试#
要进行基本 WekaIO 文件系统测试
运行以下命令
$ /usr/local/cuda-x.y/tools/gdsio_verify -f /mnt/weka/gdstest/tests/reg1G -n 1 -m 0 -s 1024 -o 0 -d 0 -t 0 -S -g 4K
查看输出,例如
gpu index :0,file :/mnt/weka/gdstest/tests/reg1G, RING buffer size :0, gpu buffer alignment :4096, gpu buffer offset :0, file offset :0, io_requested :1024, bufregister :false, sync :0, nr ios :1,fsync :0, address = 0x564ffc5e76c0 Data Verification Success
11.14. 卸载 WekaIO 文件系统集群#
要卸载 WekaIO 文件系统集群
运行以下命令。
$ sudo umount /mnt/weka
查看输出,例如
Unmounting /mnt/weka Calling the umount command umount successful, stopping and deleting client container Umount completed successfully
11.15. 验证 WekaIO 文件系统的已安装库#
下表总结了用于验证 WekaIO 文件系统的已安装库的任务和命令输出。
任务 |
输出 |
---|---|
检查 WekaIO 版本。 |
$ weka status
WekaIO v3.6.2.5-rdma-beta (CLI build 3.6.2.5-rdma-beta)
|
检查是否支持 WekaFS 的 GDS。 |
$ gdscheck -p
[...]
WekaFS: Supported
Userspace RDMA: Supported
[...]
|
检查 MLNX_OFED 信息。 |
使用 当前支持 MLNX_OFED_LINUX-5.1-0.6.6.0 $ ofed_info -s MLNX_OFED_LINUX-5.1-0.6.6.0:
|
检查 |
$ lsmod | grep nvidia_fs | grep ib_core && echo "Ready for Memory Peer Direct"
|
检查 |
$ dpkg -s libibverbs-dev
Package: libibverbs-dev
Status: install ok installed
Priority: optional
Section: libdevel
Installed-Size: 1151
Maintainer: Linux RDMA Mailing List <linux-rdma@vger.kernel.org>
Architecture: amd64
Multi-Arch: same
Source: rdma-core
Version: 47mlnx1-1.47329
|
11.16. 支持 WekaIO 文件系统的 GDS 配置文件更改#
默认情况下,基于 Weka RDMA 的写入配置处于禁用状态。
"fs": {
"weka": {
// enable/disable WekaFs rdma write
"rdma_write_support" : false
}
}
要支持 WekaIO 文件系统,请更改配置以添加新属性 rdma_dev_addr_list
"properties": {
// allow compat mode,
// this will enable use of cufile posix read/writes
//"allow_compat_mode": true,
"rdma_dev_addr_list": [
"172.16.8.88" , "172.16.8.89",
"172.16.8.90" , "172.16.8.91",
"172.16.8.92" , "172.16.8.93",
"172.16.8.94", "172.16.8.95"
]
}
11.17. 检查 WekaIO 文件系统的相关用户空间统计信息#
要检查 WekaIO 文件系统的相关用户空间统计信息,请发出以下命令
$ ./gds_stats -p <pid> -l 3 | grep GPU
有关统计信息的更多信息,请参阅 GPUDirect 存储中的用户空间 RDMA 计数器。
11.18. 检查 WekaFS 支持#
如果 WekaFS 支持不存在,则可能出现以下问题
问题 |
操作 |
---|---|
MLNX_OFED 对等直连未启用。 |
检查是否已安装 MLNX_OFED ( 如果在安装 MLNX_OFED 之前安装了 nvidia-fs Debian 软件包,则可能会发生此问题。当发生此问题时,请卸载并重新安装 nvidia-fs 软件包。 |
RDMA 设备未填充到 |
将 IP 地址添加到 |
配置的 RDMA 设备均未启动。 |
检查接口的 IB 连接。 |
12. 启用 IBM Spectrum Scale 对 GDS 的支持#
从 IBM Spectrum Scale 5.1.2 开始支持 GDS。
在查看 NVIDIA GDS 文档后,请参阅 IBM Spectrum Scale 5.1.2。请特别参阅《规划和安装指南》中的 GDS 部分。
规划:https://www.ibm.com/docs/en/spectrum-scale/5.1.2?topic=considerations-planning-gpudirect-storage
安装:https://www.ibm.com/docs/en/spectrum-scale/5.1.2?topic=installing-gpudirect-storage-spectrum-scale
有关故障排除,请参阅 https://www.ibm.com/docs/en/spectrum-scale/5.1.2?topic=troubleshooting-gpudirect-storage-issues。
12.1. IBM Spectrum Scale 对 GDS 的限制#
有关 IBM Spectrum Scale 对 GDS 的限制,请参阅以下文档
12.2. 检查 nvidia-fs.ko 对 Mellanox PeerDirect 的支持#
使用以下命令检查对内存对等直连的支持
$ cat /proc/driver/nvidia-fs/stats | grep -i "Mellanox PeerDirect Supported"
Mellanox PeerDirect Supported: True
在以上示例中,False 表示在安装 nvidia-fs 之前,MLNX_OFED 未安装 GPUDirect 存储支持。
检查 Mellanox PeerDirect 支持的另一种方法是通过 gdscheck -p
输出。如果已启用,您应该能够看到类似以下内容。
--Mellanox PeerDirect : Enabled
12.3. 验证 IBM Spectrum Scale 的已安装库#
可以执行以下任务(显示示例输出)以显示 IBM Spectrum Scale 的已安装库
检查是否支持 IBM Spectrum Scale 的 GDS
[~]# /usr/local/cuda/gds/tools/gdscheck -p | egrep -e "Spectrum Scale|PeerDirect|rdma_device_status" IBM Spectrum Scale : Supported --Mellanox PeerDirect : Enabled --rdma_device_status : Up: 2 Down: 0
检查 MLNX_OFED 信息
$ ofed_info -s MLNX_OFED_LINUX-5.4-1.0.3.0:
检查
nvidia-fs.ko
驱动程序[~]# cat /proc/driver/nvidia-fs/stats GDS Version: 1.0.0.82 NVFS statistics(ver: 4.0) NVFS Driver(version: 2.7.49) Mellanox PeerDirect Supported: True IO stats: Disabled, peer IO stats: Disabled Logging level: info Active Shadow-Buffer (MiB): 0 Active Process: 0 Reads : err=0 io_state_err=0 Sparse Reads : n=230 io=0 holes=0 pages=0 Writes : err=0 io_state_err=237 pg-cache=0 pg-cache-fail=0 pg-cache-eio=0 Mmap : n=27 ok=27 err=0 munmap=27 Bar1-map : n=27 ok=27 err=0 free=27 callbacks=0 active=0 Error : cpu-gpu-pages=0 sg-ext=0 dma-map=0 dma-ref=0 Ops : Read=0 Write=0 GPU 0000:2f:00.0 uuid:621f7d17-5e7d-8f79-be27-d2f4256ddd88 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=2
在 Ubuntu 上检查
libibverbs.so
$ dpkg -s libibverbs-dev root@fscc-sr650-59:~# dpkg -s libibverbs-dev Package: libibverbs-dev Status: install ok installed Priority: optional Section: libdevel Installed-Size: 1428 Maintainer: Linux RDMA Mailing List <linux-rdma@vger.kernel.org> Architecture: amd64 Multi-Arch: same Source: rdma-core Version: 54mlnx1-1.54103
在 RHEL 上检查
libibverbs.so
[]# rpm -qi libibverbs Name : libibverbs Version : 54mlnx1 Release : 1.54103 Architecture: x86_64 Install Date: Tue 13 Jul 2021 10:21:18 AM CEST Group : System Environment/Libraries Size : 535489 License : GPLv2 or BSD Signature : DSA/SHA1, Fri 02 Jul 2021 08:14:44 PM CEST, Key ID c5ed83e26224c050 Source RPM : rdma-core-54mlnx1-1.54103.src.rpm Build Date : Fri 02 Jul 2021 06:59:01 PM CEST Build Host : c-141-24-1-005.mtl.labs.mlnx Relocations : (not relocatable) URL : https://github.com/linux-rdma/rdma-core Summary : A library and drivers for direct userspace use of RDMA (InfiniBand/iWARP/RoCE) hardware Description : libibverbs is a library that allows userspace processes to use RDMA "verbs" as described in the InfiniBand Architecture Specification and the RDMA Protocol Verbs Specification. This includes direct hardware access from userspace to InfiniBand/iWARP adapters (kernel bypass) for fast path operations. Device-specific plug-in ibverbs userspace drivers are included: - libmlx5: Mellanox ConnectX-4+ InfiniBand HCA
12.4. 检查 PeerDirect 统计信息#
要检查内存对等统计信息,请运行以下脚本
list=`ls /sys/kernel/mm/memory_peers/nvidia-fs/`; for stat in $list;do echo "$stat value: " $(cat /sys/kernel/mm/memory_peers/nvidia-fs/$stat); done
示例输出
num_alloc_mrs value: 1288
num_dealloc_mrs value: 1288
num_dereg_bytes value: 1350565888
num_dereg_pages value: 329728
num_free_callbacks value: 0
num_reg_bytes value: 1350565888
num_reg_pages value: 32972
version value: 1.0
12.5. 检查与 IBM Spectrum Scale 相关的 nvidia-fs 统计信息#
使用以下步骤检查 IBM Spectrum Scale 文件系统的相关 nvidia-fs
统计信息。
启用
nvidia-fs
统计信息# echo 1 > /sys/module/nvidia_fs/parameters/rw_stats_enabled
$ cat /proc/driver/nvidia-fs/stats
查看输出
[~]# cat /proc/driver/nvidia-fs/stats GDS Version: 1.0.0.82 NVFS statistics(ver: 4.0) NVFS Driver(version: 2.7.49) Mellanox PeerDirect Supported: True IO stats: Disabled, peer IO stats: Disabled Logging level: info Active Shadow-Buffer (MiB): 0 Active Process: 0 Reads : err=0 io_state_err=0 Sparse Reads : n=230 io=0 holes=0 pages=0 Writes : err=0 io_state_err=237 pg-cache=0 pg-cache-fail=0 pg-cache-eio=0 Mmap : n=27 ok=27 err=0 munmap=27 Bar1-map : n=27 ok=27 err=0 free=27 callbacks=0 active=0 Error : cpu-gpu-pages=0 sg-ext=0 dma-map=0 dma-ref=0 Ops : Read=0 Write=0 GPU 0000:2f:00.0 uuid:621f7d17-5e7d-8f79-be27-d2f4256ddd88 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=2
12.6. 每个进程的 IBM Spectrum Scale 的 GDS 用户空间统计信息#
要检查 GDS 用户空间级别的统计信息,请确保 cufile.json
中的 cufile_stats
属性设置为 3。运行以下命令以检查特定进程的用户空间统计信息
$ /usr/local/cuda-<x>.<y>/gds/tools/gds_stats -p <pid> -l 3
cuFile STATS VERSION : 4
GLOBAL STATS:
Total Files: 1
Total Read Errors : 0
Total Read Size (MiB): 7302
Read BandWidth (GiB/s): 0.691406
Avg Read Latency (us): 6486
Total Write Errors : 0
Total Write Size (MiB): 0
Write BandWidth (GiB/s): 0
Avg Write Latency (us): 0
READ-WRITE SIZE HISTOGRAM :
0-4(KiB): 0 0
4-8(KiB): 0 0
8-16(KiB): 0 0
16-32(KiB): 0 0
32-64(KiB): 0 0
64-128(KiB): 0 0
128-256(KiB): 0 0
256-512(KiB): 0 0
512-1024(KiB): 0 0
1024-2048(KiB): 0 0
2048-4096(KiB): 3651 0
4096-8192(KiB): 0 0
8192-16384(KiB): 0 0
16384-32768(KiB): 0 0
32768-65536(KiB): 0 0
65536-...(KiB): 0 0
PER_GPU STATS:
GPU 0 Read: bw=0.690716 util(%)=199 n=3651 posix=0 unalign=0 dr=0 r_sparse=0 r_inline=0 err=0 MiB=7302 Write: bw=0 util(%)=0 n=0 posix=0 unalign=0 dr=0 err=0 MiB=0 BufRegister: n=2 err=0 free=0 MiB=4
PER_GPU POOL BUFFER STATS:
PER_GPU POSIX POOL BUFFER STATS:
PER_GPU RDMA STATS:
GPU 0000:43:00.0 : mlx5_0(130:64):Reads: 3594 Writes: 0 mlx5_1(130:64):Reads: 3708 Writes: 0
RDMA MRSTATS:
peer name nr_mrs mr_size(MiB)
mlx5_0 1 2
mlx5_1 1 2
在以上示例中,3954 MiB 的 IBM Spectrum Scale 读取 IO 通过 mlx5_0
,而 3708 MiB 的 IBM Spectrum Scale 读取通过 mlx5_1
。RDMA MRSTATS
值显示 RDMA 内存注册的数量和这些注册的大小。
12.7. 支持 IBM Spectrum Scale 的 GDS 配置#
配置 DC 密钥。
可以按以下方式配置 IBM Spectrum Scale 客户端的 DC 密钥
设置环境变量
CUFILE_RDMA_DC_KEY
。应将其设置为 32 位十六进制值。可以按以下示例所示进行设置export CUFILE_RDMA_DC_KEY = 0x11223344
在
cufile.json
中设置属性rdma_dc_key
。此属性是 32 位值,可以按以下示例所示进行设置"rdma_dc_key": "0xffeeddcc",
如果环境变量和
cufile.json
都设置了该属性,则环境变量CUFILE_RDMA_DC_KEY
将优先于cufile.json
中设置的rdma_dc_key
属性。如果以上均未设置,则配置的默认 DC 密钥为
0xffeeddcc
。在
cufile.json
中配置 IP 地址。应在
cufile.json
中使用要用于 IO 的 RDMA 设备的 IP 地址设置>rdma_dev_addr_list
属性。"properties": { ------- "rdma_dev_addr_list": [ "172.16.8.88" , "172.16.8.89", "172.16.8.90" , "172.16.8.91", "172.16.8.92" , "172.16.8.93", "172.16.8.94", "172.16.8.95" ] } --------- }
在
cufile.json
中配置max_direct_io_size_kb
属性。您可以使用以下属性更改 IO 大小
"properties": { ------- "max_direct_io_size_kb" : 1024 --------- }
在
cufile.json
中配置rdma_access_mask
属性。此属性是性能可调参数。有关此属性的最佳配置,请参阅 IBM Spectrum Scale 文档 https://www.ibm.com/docs/en/spectrum-scale/5.1.2?topic=configuring-gpudirect-storage-spectrum-scale。
"properties": { ------- "rdma_access_mask": "0x1f", --------- }
12.8. 回退到兼容模式的场景#
在某些情况下,无论 cufile.json
中的 allow_compat_mode
属性的值如何,都将导致 IBM Spectrum Scale IO 通过兼容模式。有关这些情况的完整列表,请参阅 http://www.ibm.com/support/pages/node/6444075。
12.9. GDS 对 IBM Spectrum Scale 的限制#
当前,每个 GPU 缓冲区的 RDMA 内存注册最大数量为 16。因此,每个 GPU 缓冲区可通过 RDMA 注册的最大内存大小为 16 * max_direct_to_size_kb
(在 cufile.json
中设置)。任何超出此偏移量的 IBM Spectrum Scale 的 GDS IO 都将通过反弹缓冲区,并且可能会对性能产生影响。
13. NetApp E 系列 BeeGFS 与 GDS 解决方案部署#
NetApp 支持 BeeGFS 高可用性。
有关如何部署 BeeGFS 并行文件系统的信息,请参阅《BeeGFS 与 Netapp E 系列技术报告》:Netapp BeeGFS 部署。对于需要高可用性的部署,请参阅 BeeGFS 高可用性与 NetApp E 系列。
13.1. Netapp BeeGFS/GPUDirect 存储和软件包要求#
BeeGFS 客户端和带有 GDS 的存储
CUDA 和 GDS 仅在 beegfs-client 主机上是必需的。BeeGFS 服务器主机没有 CUDA 或 GPUDirect 存储要求。
13.2. BeeGFS 客户端 GDS 配置#
安装 beegfs-client 后,需要为 RDMA 和 GDS 配置客户端构建。
编辑
/etc/beegfs/beegfs-client-autobuild.conf
。将文件的第 57 行更改为buildArgs=-j8 NVFS_H_PATH=/usr/src/mlnx-ofed-kernel-5.4/drivers/nvme/host OFED_INCLUDE_PATH=/usr/src/ofa_kernel/default/include
这应全部在同一行上。
重建 beegfs-client
sudo /etc/init.d/beegfs-client rebuild
13.3. 客户端上的 GPU/HCA 拓扑 - DGX-A100 和 OSS 服务器客户端服务器#
客户端服务器
ibdev |
netdev |
IP |
GPU |
Numa |
OSS |
目标 |
挂载点 |
---|---|---|---|---|---|---|---|
mlx5_4 |
ibp97s0f0 |
10.10.0.177/24 |
0,1,2,3 |
0 |
meta 1 |
5,6,7,8 |
|
mlx5_5 |
ibp97s0f1 |
10.10.1.177/24 |
0,1,2,3 |
0 |
meta 1 |
5,6,7,8 |
|
mlx5_10 |
ibp225s0f0 |
10.10.2.157/24 |
4,5,6,7 |
4 |
meta 2 |
1,2,3,4 |
|
mlx5_11 |
ibp225s0f1 |
10.10.3.157/24 |
4,5,6,7 |
4 |
meta 2 |
1,2,3,4 |
|
OSS 服务器
OSS |
ID |
IP |
Numa |
---|---|---|---|
meta01-numa0-1 |
1001 |
10.10.0.131:8003 |
0 |
meta01-numa1-2 |
1002 |
10.10.1.131:8004 |
1 |
meta02-numa0-1 |
2001 |
10.10.2.132:8003 |
0 |
meta02-numa1-2 |
2002 |
10.10.3.132:8004 |
1 |
13.4. 验证设置#
要验证设置,请在任何客户端上运行以下命令
13.4.1. 列出管理节点#
root@dgxa100-b:/sys/class# beegfs-ctl --listnodes --nodetype=management --details
meta-02.cpoc.local [ID: 1]
Ports: UDP: 8008; TCP: 8008
Interfaces: em3(TCP)
13.4.2. 列出元数据节点#
root@dgxa100-b:/sys/class# beegfs-ctl --listnodes --nodetype=meta -details
meta01-numa0-1-meta [ID: 1101]
Ports: UDP: 8005; TCP: 8005
Interfaces: ib0:net1(RDMA) ib0:net1(TCP)
meta01-numa1-2-meta [ID: 1102]
Ports: UDP: 8006; TCP: 8006
Interfaces: ib2:net3(RDMA) ib2:net3(TCP)
meta02-numa0-1-meta [ID: 2101]
Ports: UDP: 8005; TCP: 8005
Interfaces: ib0:net0(RDMA) ib0:net0(TCP)
meta02-numa1-2-meta [ID: 2102]
Ports: UDP: 8006; TCP: 8006
Interfaces: ib2:net2(RDMA) ib2:net2(TCP)
Number of nodes: 4
Root: 2101
13.4.3. 列出存储节点#
root@dgxa100-b:/sys/class# beegfs-ctl --listnodes --nodetype=storage -details
meta01-numa0-1 [ID: 1001]
Ports: UDP: 8003; TCP: 8003
Interfaces: ib0:net1(RDMA) ib0:net1(TCP)
meta01-numa1-2 [ID: 1002]
Ports: UDP: 8004; TCP: 8004
Interfaces: ib2:net3(RDMA) ib2:net3(TCP)
meta02-numa0-1 [ID: 2001]
Ports: UDP: 8003; TCP: 8003
Interfaces: ib0:net0(RDMA) ib0:net0(TCP)
meta02-numa1-2 [ID: 2002]
Ports: UDP: 8004; TCP: 8004
Interfaces: ib2:net2(RDMA) ib2:net2(TCP)
Number of nodes: 4
13.4.4. 列出客户端节点#
root@dgxa100-b:/sys/class# beegfs-ctl --listnodes --nodetype=client --details
B4330-6161F689-dgxa100-b [ID: 11]
Ports: UDP: 8004; TCP: 0
Interfaces: ibp97s0f0(RDMA) ibp97s0f0(TCP) ibp97s0f1(TCP) ibp97s0f1(RDMA) ibp225s0f0(TCP)
ibp225s0f0(RDMA) ibp225s0f1(TCP) ibp225s0f1(RDMA)
13.4.5. 显示客户端连接#
root@dgxa100-b:/sys/class# beegfs-net
mgmt_nodes
=============
meta-02.cpoc.local [ID: 1]
Connections: TCP: 1 (192.168.0.132:8008);
meta_nodes
=============
meta01-numa0-1-meta [ID: 1101]
Connections: RDMA: 1 (10.10.1.131:8005);
meta01-numa1-2-meta [ID: 1102]
Connections: RDMA: 1 (10.10.3.131:8006);
meta02-numa0-1-meta [ID: 2101]
Connections: RDMA: 1 (10.10.0.132:8005);
meta02-numa1-2-meta [ID: 2102]
Connections: RDMA: 1 (10.10.2.132:8006);
storage_nodes
=============
meta01-numa0-1 [ID: 1001]
Connections: RDMA: 8 (10.10.1.131:8003);
meta01-numa1-2 [ID: 1002]
Connections: RDMA: 8 (10.10.3.131:8004);
meta02-numa0-1 [ID: 2001]
Connections: RDMA: 16 (10.10.0.132:8003);
meta02-numa1-2 [ID: 2002]
Connections: RDMA: 8 (10.10.2.132:8004);
13.4.6. 验证与不同服务的连接#
root@dgxa100-b:/sys/class# beegfs-check-servers
Management
==========
meta-02.cpoc.local [ID: 1]: reachable at 192.168.0.132:8008 (protocol: TCP)
Metadata
==========
meta01-numa0-1-meta [ID: 1101]: reachable at 10.10.1.131:8005 (protocol: TCP)
meta01-numa1-2-meta [ID: 1102]: reachable at 10.10.3.131:8006 (protocol: TCP)
meta02-numa0-1-meta [ID: 2101]: reachable at 10.10.0.132:8005 (protocol: TCP)
meta02-numa1-2-meta [ID: 2102]: reachable at 10.10.2.132:8006 (protocol: TCP)
Storage
==========
meta01-numa0-1 [ID: 1001]: reachable at 10.10.1.131:8003 (protocol: TCP)
meta01-numa1-2 [ID: 1002]: reachable at 10.10.3.131:8004 (protocol: TCP)
meta02-numa0-1 [ID: 2001]: reachable at 10.10.0.132:8003 (protocol: TCP)
meta02-numa1-2 [ID: 2002]: reachable at 10.10.2.132:8004 (protocol: TCP)
13.4.7. 列出存储池#
在此示例中,我们使用了默认挂载点
root@dgxa100-b:/sys/class# sudo beegfs-ctl -liststoragepools
Pool ID Pool Description Targets Buddy Groups
======= ================== ============================ ============================
1 Default 1,2,3,4,5,6,7,8
13.4.8. 显示存储和元数据目标上的可用空间和 inodes#
root@dgxa100-b:/sys/class# beegfs-df
METADATA SERVERS:
TargetID Cap. Pool Total Free % ITotal IFree %
======== ========= ===== ==== = ====== ===== =
1101 normal 573.3GiB 572.9GiB 100% 401.1M 401.0M 100%
1102 normal 573.3GiB 572.9GiB 100% 401.1M 401.0M 100%
2101 normal 573.3GiB 572.9GiB 100% 401.1M 401.0M 100%
2102 normal 573.3GiB 572.9GiB 100% 401.1M 401.0M 100%
STORAGE TARGETS:
TargetID Cap. Pool Total Free % ITotal IFree %
======== ========= ===== ==== = ====== ===== =
1 normal 2574.7GiB 1470.8GiB 57% 270.1M 270.1M 100%
2 normal 2574.7GiB 1404.0GiB 55% 270.1M 270.1M 100%
3 normal 2574.7GiB 1265.5GiB 49% 270.1M 270.1M 100%
4 normal 2574.7GiB 1278.5GiB 50% 270.1M 270.1M 100%
5 normal 2574.7GiB 1274.0GiB 49% 270.1M 270.1M 100%
6 normal 2574.7GiB 1342.6GiB 52% 270.1M 270.1M 100%
7 normal 2574.7GiB 1485.3GiB 58% 270.1M 270.1M 100%
8 normal 2574.7GiB 1481.7GiB 58% 270.1M 270.1M 100%
13.5. 测试#
13.5.1. 验证集成是否正常工作#
一旦启动了具有 GDS 支持的 beegfs-client,就可以执行基本测试以验证集成是否正常工作
root@dgxa100-b:/usr/local/cuda-11.4/gds/tools# ./gdscheck.py -p
GDS release version: 1.1.1.14
nvidia_fs version: 2.7 libcufile version: 2.9
============
ENVIRONMENT:
============
=====================
DRIVER CONFIGURATION:
=====================
NVMe : Supported
NVMeOF : Unsupported
SCSI : Unsupported
ScaleFlux CSD : Unsupported
NVMesh : Unsupported
DDN EXAScaler : Unsupported
IBM Spectrum Scale : Unsupported
NFS : Unsupported
BEEGFS : Supported
WekaFS : Unsupported
Userspace RDMA : Unsupported
--Mellanox PeerDirect : Disabled
--rdma library : Not Loaded (libcufile_rdma.so)
--rdma devices : Not configured
--rdma_device_status : Up: 0 Down: 0
=====================
CUFILE CONFIGURATION:
=====================
properties.use_compat_mode : true
properties.gds_rdma_write_support : false
properties.use_poll_mode : false
properties.poll_mode_max_size_kb : 4
properties.max_batch_io_timeout_msecs : 5
properties.max_direct_io_size_kb : 16384
properties.max_device_cache_size_kb : 131072
properties.max_device_pinned_mem_size_kb : 33554432
properties.posix_pool_slab_size_kb : 4 1024 16384
properties.posix_pool_slab_count : 128 64 32
properties.rdma_peer_affinity_policy : RoundRobin
properties.rdma_dynamic_routing : 0
fs.generic.posix_unaligned_writes : false
fs.lustre.posix_gds_min_kb: 0
fs.beegfs.posix_gds_min_kb: 0
fs.weka.rdma_write_support: false
profile.nvtx : false
profile.cufile_stats : 0
miscellaneous.api_check_aggressive : false
=========
IOMMU: disabled
Platform verification succeeded
13.5.2. 进行基本 NetApp BeeGFS 文件系统测试#
/usr/local/cuda/gds/tools/gdsio_verify -f /mnt/beegfs/file 1g -d 0 -o 0 -s 1G -n 1 -m 1
gpu index :0, file :/mnt/beegfs/file 1g, gpu buffer alignment :0, gpu buffer offset :0, gpu devptr offset :0, file offset :0, io_requested :1073741824, io_chunk_size :1073741824, bufregister :true, sync :1, nr ios :1, fsync :0,
Data Verification Success
14. 设置和故障排除 VAST Data (NFSoRDMA+MultiPath)#
本节提供有关如何设置和排除 VAST Data (NFSoRDMA+MultiPath) 故障的信息。
14.1. 安装 MLNX_OFED 和 VAST NFSoRDMA+Multipath 软件包#
14.1.1. 客户端软件要求#
下表列出了使用 MLNX_OFED 和 VAST NFSoRDMA+Multipath 软件包的最低客户端软件要求。
NFS 连接类型 |
Linux 内核 |
MLNX_OFED |
---|---|---|
NFSoRDMA + 多路径 |
支持以下内核版本
|
支持以下 MLNX_OFED 版本
|
有关最新的支持性矩阵以及客户端配置步骤和软件包下载,请参阅:https://support.vastdata.com/hc/en-us/articles/360016813140-NFSoRDMA-with-Multipath。
必须安装 MLNX_OFED,VAST NFSoRDMA+Multipath 软件包才能最佳地运行。下载正确的 VAST 软件包以匹配您的内核 + MLNX_OFED 版本组合也很重要。有关如何安装具有 GDS 支持的 MLNX_OFED 的信息,请参阅 使用 nvidia-fs 的 NVMe 和 NVMeOF 支持故障排除和常见问题解答。
要验证 MLNX_OFED 的当前版本,请发出以下命令
$ ofed_info -s MLNX_OFED_LINUX-5.3-0.6.6.01:
要验证当前安装的 Linux 内核版本,请发出以下命令
$ uname -r -v
在您验证您的系统具有正确的内核和 MLNX_OFED 组合后,您可以安装 VAST Multipath 软件包。
14.1.2. 安装 VAST Multipath 软件包#
尽管 VAST Multipath 与 NFSoRDMA 软件包已提交上游以包含在未来的内核版本中,但目前仅可从以下位置下载:https://support.vastdata.com/hc/en-us/articles/360016813140-NFSoRDMA-with-Multipath。
请务必下载基于您的内核和 MLNX_OFED 版本的正确 .deb
文件。
安装 VAST NFSoRDMA+Multipath 软件包
$ sudo apt-get install mlnx-nfsrdma-*.deb
生成新的 initramfs 镜像
$ sudo update-initramfs -u -k `uname -r`
验证软件包已安装,并且版本是您期望的数字
$ dpkg -l | grep mlnx-nfsrdma ii mlnx-nfsrdma-dkms 5.3-OFED.5.1.0.6.6.0 all DKMS support for NFS RDMA kernel module
重新启动主机并运行以下命令以验证是否加载了正确的版本
注意
每个命令显示的版本应匹配。
$ cat /sys/module/sunrpc/srcversion 4CC8389C7889F82F5A59269 $ modinfo sunrpc | grep srcversion srcversion: 4CC8389C7889F82F5A59269
14.2. 设置网络#
本节提供有关如何为 GDS 设置 VAST 客户端网络的信息。
为了确保在使用 GDS 的同时获得最佳的 GPU 到存储性能,您需要以平衡的方式配置 VAST 和客户端网络。
14.2.1. VAST 网络配置#
VAST 是一种多节点架构。每个节点都有多个高速 (IB-HDR100 或 100GbE) 接口,可以托管面向客户端的虚拟 IP。有关更多信息,请参阅 VAST - 管理虚拟 IP (VIP) 池。
这是典型的工作流程
将 VAST 节点数 * 2(每个接口一个)。
使用生成的 IP 计数创建 VIP 池。
将 VAST-VIP 池放置在与客户端相同的 IP 子网上。
14.2.2. 客户端网络配置#
以下是有关客户端网络配置的信息。
通常,GPU 优化的客户端(例如 NVIDIA DGX-2 和 DGX-A100)配置有多个高速网络接口卡 (NIC)。在以下示例中,系统包含 8 个单独的 NIC,这些 NIC 被选择用于优化 NIC –>GPU 和 NIC –>CPU 带宽的平衡。
$ sudo ibdev2netdev
mlx5_0 port 1 ==> ibp12s0 (Up)
mlx5_1 port 1 ==> ibp18s0 (Up)
mlx5_10 port 1 ==> ibp225s0f0 (Down)
mlx5_11 port 1 ==> ibp225s0f1 (Down)
mlx5_2 port 1 ==> ibp75s0 (Up)
mlx5_3 port 1 ==> ibp84s0 (Up)
mlx5_4 port 1 ==> ibp97s0f0 (Down)
mlx5_5 port 1 ==> ibp97s0f1 (Down)
mlx5_6 port 1 ==> ibp141s0 (Up)
mlx5_7 port 1 ==> ibp148s0 (Up)
mlx5_8 port 1 ==> ibp186s0 (Up)
mlx5_9 port 1 ==> ibp202s0 (Up)
并非所有接口都已连接,这是为了确保最佳带宽。
当使用上述 VAST NFSoRDAM+Multipath 软件包时,建议为同一子网上的每个接口分配静态 IP,这也应与 VAST VIP 池上配置的子网匹配。如果将 GDS 与 NVIDIA DGX-A100 一起使用,则只需要一个简单的 netplan,例如
ibp12s0:
addresses: [172.16.0.17/24]
dhcp4: no
ibp141s0:
addresses: [172.16.0.18/24]
dhcp4: no
ibp148s0:
addresses: [172.16.0.19/24]
dhcp4: no
但是,如果您使用的是其他系统或非 GDS 代码,则需要应用以下代码以确保使用正确的接口从客户端 - > VAST 遍历。
注意
请参阅以下示例中每个接口的 routes
部分。
$ cat /etc/netplan/01-netcfg.yaml
network:
version: 2
renderer: networkd
ethernets:
enp226s0:
dhcp4: yes
ibp12s0:
addresses: [172.16.0.25/24]
dhcp6: no
routes:
- to: 172.16.0.0/24
via: 172.16.0.25
table: 101
routing-policy:
- from: 172.16.0.25
table: 101
ibp18s0:
addresses: [172.16.0.26/24]
dhcp4: no
routes:
- to: 172.16.0.0/24
via: 172.16.0.26
table: 102
routing-policy:
- from: 172.16.0.26
table: 102
ibp75s0:
addresses: [172.16.0.27/24]
dhcp4: no
routes:
- to: 172.16.0.0/24
via: 172.16.0.27
table: 103
routing-policy:
- from: 172.16.0.27
table: 103
ibp84s0:
addresses: [172.16.0.28/24]
dhcp4: no
routes:
- to: 172.16.0.0/24
via: 172.16.0.28
table: 104
routing-policy:
- from: 172.16.0.28
table: 104
ibp141s0:
addresses: [172.16.0.29/24]
dhcp4: no
routes:
- to: 172.16.0.0/24
via: 172.16.0.29
table: 105
routing-policy:
- from: 172.16.0.29
table: 105
ibp148s0:
addresses: [172.16.0.30/24]
dhcp4: no
routes:
- to: 172.16.0.0/24
via: 172.16.0.30
table: 106
routing-policy:
- from: 172.16.0.30
table: 106
ibp186s0:
addresses: [172.16.0.31/24]
dhcp4: no
routes:
- to: 172.16.0.0/24
via: 172.16.0.31
table: 107
routing-policy:
- from: 172.16.0.31
table: 107
ibp202s0:
addresses: [172.16.0.32/24]
dhcp4: no
routes:
- to: 172.16.0.0/24
via: 172.16.0.32
table: 108
routing-policy:
- from: 172.16.0.32
table: 108
在对 netplan 进行更改后,在发出以下命令之前,请确保您具有到客户端的 IPMI/控制台连接
$ sudo netplan apply
14.2.3. 验证网络连接#
一旦应用了正确的 netplan,请使用 ping 循环验证所有客户端接口和所有 VAST-VIP 之间的连接
# Replace with appropriate interface names
$ export IFACES="ibp12s0 ibp18s0 ibp75s0 ibp84s0 ibp141s0 ibp148s0 ibp186s0 ibp202s0"
# replace with appropriate VAST-VIPs
$ export VIPS=$(echo 172.16.0.{101..116})
$ echo "starting pingtest" > pingtest.log
$ for i in $IFACES;do for v in $VIPS; do echo $i >> pingtest.log; ping -c 1 $v -W 0.2 -I $i|grep loss >> pingtest.log;done;done;
# Verify no failures:
$ grep '100%' pingtest.log
您还应验证是否满足以下条件之一
所有客户端接口都直接连接到与 VAST 相同的 IB 交换机。
客户端交换机和连接到 VAST 的交换机之间有足够的交换机间链路 (ISL)。
要验证当前的 IB 交换机拓扑,请发出以下命令
$ sudo ibnetdiscover
<output trimmed>
[37] "H-b8599f0300c3f4cb"[1](b8599f0300c3f4cb) # "vastraplab-cn1 HCA-2" lid 55 2xHDR # <-- example of Vast-Node
[43] "S-b8599f0300e361f2"[43] # "MF0;RL-QM87-C20-U33:MQM8700/U1" lid 1 4xHDR # <-- example of ISL
[67] "H-1c34da030073c27e"[1](1c34da030073c27e) # "rl-dgxa-c21-u19 mlx5_9" lid 23 4xHDR # <-- example of client
14.3. 挂载 VAST NFS#
要充分利用可用的 VAST VIP,您必须通过发出以下命令来挂载文件系统
$ sudo mount -o proto=rdma,port=20049,vers=3 \
-o noidlexprt,nconnect=40 \
-o localports=172.16.0.25-172.16.0.32 \
-o remoteports=172.16.0.101-172.16.0.140 \
172.16.0.101:/ /mnt/vast
选项包括
- proto
必须指定 RDMA。
- port=20049
必须指定,这是 RDMA 控制端口。
- noidlexprt
不要断开空闲连接。这是为了在没有挂起的 I/O 时检测和恢复失败的连接。
- nconnect
并发连接数。为了获得最佳平衡,应可被下面指定的 remoteports 数量均匀地整除。
- localports
要绑定的本地端口的 IPv4 地址列表。
- remoteports
要绑定的 NFS 服务器 IPv4 端口列表。
对于 localports 和 remoteports,您可以使用 - 分隔符指定包含范围,例如,FIRST-LAST。多个范围或单个 IP 地址可以用 ~(波浪号)分隔
14.4. 调试和监控 VAST Data#
通常,/proc
下的 mountstats
显示 xprt
统计信息。但是,VAST Multipath 软件包没有以非兼容方式使用 nfsstat
实用程序对其进行修改,而是使用额外的状态报告扩展了 mountstats
,以便专门从 /sys/kernel/debug
访问。
为每个 RPC 客户端添加了 stats
节点,RPC 客户端 0 显示已完成的挂载
$ sudo cat /sys/kernel/debug/sunrpc/rpc_clnt/0/stats
添加的信息是每个 xprt 的多路径 IP 地址信息和字符串格式的 xprt 状态。
例如
xprt: rdma 0 0 1 0 24 3 3 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0
172.25.1.101 -> 172.25.1.1, state: CONNECTED BOUND
xprt: rdma 0 0 1 0 24 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0
172.25.1.102 -> 172.25.1.2, state: CONNECTED BOUND
xprt: rdma 0 0 1 0 23 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0
172.25.1.103 -> 172.25.1.3, state: CONNECTED BOUND
xprt: rdma 0 0 1 0 22 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 0 0 0
172.25.1.104 -> 172.25.1.4, state: CONNECTED BOUND
xprt: rdma 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
172.25.1.101 -> 172.25.1.5, state: BOUND
xprt: rdma 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
172.25.1.102 -> 172.25.1.6, state: BOUND
xprt: rdma 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
172.25.1.103 -> 172.25.1.7, state: BOUND
xprt: rdma 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
172.25.1.104 -> 172.25.1.8, state: BOUND
15. 使用 Linux PCI P2PDMA 的 NVMe 支持故障排除和常见问题解答#
本节提供有关使用 Linux PCI P2PDMA 的 NVMe 支持的故障排除信息。
15.1. Linux 内核要求#
检查 Ubuntu 发行版上的 Linux 内核版本是否高于 6.2 及以上版本。
对于其他发行版,请检查是否已编译 PCI P2PDMA 功能。如果未启用 PCI P2PDMA,则可以从 MLNX_OFED 安装 GDS 特定的 NVMe 补丁,以支持使用 nvidia-fs.ko
的 GDS。
$ cat /proc/kallsyms | grep -i p2pdma_pgmap_ops
0000000000000000 d p2pdma_pgmap_ops
检查您的系统是否配备 NVIDIA GPU,且该 GPU 的架构新于或等于 NVIDIA Ampere 架构。
15.2. 支持的 GPU#
支持 A100、A40、L4、L40S 和 H100。
15.3. 设置驱动程序注册表以启用 PCI P2PDMA#
禁用多路径支持
上游驱动程序中当前未启用带有 PCI P2PDMA 的 NVMe 多路径,并且在没有专门补丁的情况下将无法工作。
$ cat /etc/modprobe.d/nvme.conf
options nvme_core multipath=N
#RH/SLES:
$ sudo dracut -f
#Ubuntu :
$ sudo update-initramfs -u -k `uname -r`
$ sudo reboot
$ cat /sys/module/nvme_core/parameters/multipath
N
pci_p2pdma 支持 ( 启用静态 BAR1 并强制禁用写合并)
在驱动程序 modprobe conf 设置中设置以下参数,使其在重启后仍然保留
$ cat /etc/modprobe.d/nvidia-temp.conf
options nvidia NVreg_RegistryDwords="RMForceStaticBar1=1;RmForceDisableIomapWC=1;"
注意
对于 Hopper 之前的 GPU(L4、L40、A100、A40),应应用以下额外的 ForceP2P=0 设置
$ cat /etc/modprobe.d/nvidia-p2pdma.conf
options nvidia
NVreg_RegistryDwords="RMForceStaticBar1=1;ForceP2P=0;RmForceDisableIomapWC=1;"
#RH/SLES:
$ sudo dracut -f
#ubuntu :
$ sudo update-initramfs -u -k `uname -r`
# reboot
$ sudo reboot
# check the settings
$ cat /proc/driver/nvidia/params | grep -i static
RegistryDwords: "RMForceStaticBar1=1;RmForceDisableIomapWC=1;"
15.4. cufile.json 设置#
将以下配置参数添加到 /etc/cufile.json
或应用程序特定的 JSON 文件中
{
"properties": {
"use_pci_p2pdma": true
}
}
15.5. 验证 GDS 是否支持 P2P 模式#
/usr/local/cuda-<x>.<y>/gds/tools/gdscheck.py -p
GDS release version: 1.13.0.7
nvidia_fs version: 2.24 libcufile version: 2.12
Platform: x86_64
============
ENVIRONMENT:
============
=====================
DRIVER CONFIGURATION:
=====================
NVMe P2PDMA : Supported
NVMe : Supported
NVMeOF : Unsupported
注意
如果 NVMe 同时受 PCI P2PDMA 和 nvidia-fs
支持,则 NVMe P2PDMA 模式优先。
15.6. RAID 支持#
目前,带有 PCI P2PDMA 的 GDS 不支持 RAID。
15.7. 为 GDS 挂载本地文件系统#
目前,EXT4 和 XFS 是 GDS 唯一支持的基于块设备的文件系统。由于 Direct IO 语义,EXT4 文件系统必须以设置为 data=ordered
的日志模式挂载。这必须显式包含在挂载选项中,以便库可以识别它
$ sudo mount -o data=ordered /dev/nvme0n1 /mnt
如果 EXT4 日志模式不在预期模式下,则 cuFileHandleRegister
将失败,并且相应的错误消息将记录在日志文件中。例如,在以下情况下,/mnt1
以 writeback 模式挂载,并且 GDS 返回错误
$ mount | grep /mnt1
/dev/nvme0n1p2 on /mnt1 type ext4 (rw,relatime,data=writeback)
$ ./cufile_sample_001 /mnt1/foo 0
opening file /mnt1/foo
file register error:GPUDirect Storage not supported on current file
15.8. 检查现有的 EXT4 挂载#
要检查现有的 EXT4 挂载
$ mount | grep ext4
/dev/sda2 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
/dev/nvme1n1 on /mnt type ext4 (rw,relatime,data=ordered)
/dev/nvme0n1p2 on /mnt1 type ext4 (rw,relatime,data=writeback)
注意
可以使用类似的检查来检查现有的 XFS 挂载,例如
mount | grep xfs
15.9. 检查块设备挂载的 IO 统计信息#
以下命令和部分日志显示了如何获取 IO 统计信息
$ sudo iotop
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 193.98 K/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
881 be/3 root 0.00 B/s 15.52 K/s 0.00 % 0.01 % [jbd2/sda2-8]
1 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % init splash
15.10. 执行基本的 EXT4 文件系统测试#
要执行基本的 EXT4 文件系统测试,请发出以下命令
$ /usr/local/cuda-x.y/gds/tools/gdsio_verify -f /mnt/nvme/gdstest/tests/reg1G -n 1 -m 0 -s 1024 -o 0 -d 0 -t 0 -S -g 4K
示例输出
gpu index :0,file :/mnt/weka/gdstest/tests/reg1G, RING buffer size :0, gpu buffer alignment :4096, gpu buffer offset :0, file offset :0, io_requested :1024, bufregister :false, sync :0, nr ios :1,fsync :0,
address = 0x564ffc5e76c0
Data Verification Success
15.11. 卸载 EXT4 文件系统#
要卸载 EXT4 文件系统,请发出以下命令
$ sudo umount /mnt/
15.12. 块设备的 Udev 设备命名#
该库在识别基于 NVMe 的块设备时存在限制,因为它期望设备名称具有 nvme
前缀作为命名约定的一部分。
15.13. 批量 I/O 性能#
已观察到,m 个独立的批次,每个批次包含 n/m 个条目,比 1 个包含 n 个条目的批次表现出更好的性能,尤其是在基于 NVMe 的存储的情况下。
15.14. 统计信息#
没有单独的统计信息来区分 PCI P2PDMA 模式和 nvidia-fs 模式。GDS 模式统计信息对于这两种模式是通用的,应根据应用程序运行的模式进行区分。
16. 使用 nvidia-fs 的 NVMe 和 NVMeOF 支持的故障排除和常见问题解答#
本节提供有关 NVME 和 NVMeOF 支持的故障排除信息。
16.1. MLNX_OFED 要求和安装#
要启用对 NVMe 和 NVMeOF 的 GDS 支持,您需要安装至少 MLNX_OFED 5.3 或更高版本。
您必须安装支持 GDS 的 MLNX_OFED。
安装完成后,要使更改生效,请使用 update -initramfs
并重新启动。使用 MLNX_OFED 5.3-1.0.5.01 测试的 Linux 内核版本为 4.15.0-x 和 5.4.0-x。发出以下命令
$ sudo ./mlnxofedinstall --with-nvmf --with-nfsrdma --enable-gds --add-kernel-support --dkms
注意
从 MLNX_OFED 5.3 开始,不再需要 --enable-gds
标志。
$ sudo update-initramfs -u -k `uname -r`
$ reboot
16.2. DOCA 要求和安装#
通过 DOCA 也可获得对 NVMe 和 NVMe-oF 的 GDS 支持。如果您已通过 MLNX_OFED 安装了 GDS 补丁(如上一步所述),则不需要此步骤。要通过 DOCA 安装 GDS 补丁,请参阅 在主机上安装软件。
如果您没有受支持的 HostOS/内核,则需要从上述文档安装 DOCA 额外的软件包。之后,可以按如下方式安装 NVMe/NVMe-oF 软件包
对于 Ubuntu
$ sudo apt install doca-ofed mlnx-fw-updater mlnx-nvme-dkms
$ sudo update-initramfs -u -k `uname -r`
$ reboot
对于 RHEL
$ sudo dnf install doca-ofed mlnx-fw-updater kmod-mlnx-nvme
$ sudo dracut -f
$ reboot
注意
有关支持矩阵,请参阅 每个 DOCA 主机安装配置文件支持的主机操作系统和功能。
16.3. 确定 NVMe 设备是否支持 GDS#
NVMe 设备必须与 GDS 兼容;设备不能具有块设备完整性功能。
对于设备完整性,Linux 块层基于主机内存中的有效负载完成元数据处理。这与标准 GDS IO 路径有所偏差,因此无法兼容这些设备。当检测到此类底层设备时,cuFile 文件注册将失败,并在 cufile.log
文件中记录相应的错误日志。
$ cat /sys/block/<nvme>/integrity/device_is_integrity_capable
16.4. GDS 中的 RAID 支持#
目前,GDS 仅支持 RAID 0。
16.5. 为 GDS 挂载本地文件系统#
目前,EXT4 和 XFS 是 GDS 唯一支持的基于块设备的文件系统。由于 Direct IO 语义,ext4 文件系统必须以设置为 data=ordered
的日志模式挂载。这必须显式包含在挂载选项中,以便库可以识别它
$ sudo mount -o data=ordered /dev/nvme0n1 /mnt
如果 EXT4 日志模式不在预期模式下,则 cuFileHandleRegister
将失败,并且相应的错误消息将记录在日志文件中。例如,在以下情况下,/mnt1
以 writeback 模式挂载,并且 GDS 返回错误
$ mount | grep /mnt1
/dev/nvme0n1p2 on /mnt1 type ext4 (rw,relatime,data=writeback)
$ ./cufile_sample_001 /mnt1/foo 0
opening file /mnt1/foo
file register error:GPUDirect Storage not supported on current file
16.6. 检查现有的 EXT4 挂载#
要检查现有的 EXT4 挂载
$ mount | grep ext4
/dev/sda2 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
/dev/nvme1n1 on /mnt type ext4 (rw,relatime,data=ordered)
/dev/nvme0n1p2 on /mnt1 type ext4 (rw,relatime,data=writeback)
注意
可以使用类似的检查来检查现有的 XFS 挂载,例如
mount | grep xfs
16.7. 检查块设备挂载的 IO 统计信息#
以下命令和部分日志显示了如何获取 IO 统计信息
$ sudo iotop
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 193.98 K/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
881 be/3 root 0.00 B/s 15.52 K/s 0.00 % 0.01 % [jbd2/sda2-8]
1 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % init splash
16.8. GPU 亲缘性的 RAID 组配置#
从可用的 NVMe 设备创建一个 RAID 组可能不是 GDS 性能的最佳选择。您可能需要创建由与指定 GPU 具有 pci 亲缘性的设备组成的 RAID 组。这是为了防止 GPU 和 NVMe 设备之间出现跨节点 P2P 流量。
如果未强制执行亲缘性,GDS 将使用设备反弹缓冲区的内部机制,将数据从 NVMe 设备复制到最接近驱动器的中间设备,然后将数据复制回实际的 GPU。如果启用了 NVLink,这将加速这些传输。
16.9. 执行基本的 EXT4 文件系统测试#
要执行基本的 EXT4 文件系统测试,请发出以下命令
$ /usr/local/cuda-x.y/gds/tools/gdsio_verify -f /mnt/nvme/gdstest/tests/reg1G -n 1 -m 0 -s 1024 -o 0 -d 0 -t 0 -S -g 4K
示例输出
gpu index :0,file :/mnt/weka/gdstest/tests/reg1G, RING buffer size :0, gpu buffer alignment :4096, gpu buffer offset :0, file offset :0, io_requested :1024, bufregister :false, sync :0, nr ios :1,fsync :0,
address = 0x564ffc5e76c0
Data Verification Success
16.10. 卸载 EXT4 文件系统#
要卸载 EXT4 文件系统,请发出以下命令
$ sudo umount /mnt/
16.11. 块设备的 Udev 设备命名#
该库在识别基于 NVMe 的块设备时存在限制,因为它期望设备名称具有 nvme
前缀作为命名约定的一部分。
16.12. 批量 I/O 性能#
已观察到,m 个独立的批次,每个批次包含 n/m 个条目,比 1 个包含 n 个条目的批次表现出更好的性能,尤其是在基于 NVMe 的存储的情况下。
17. 显示 GDS NVIDIA FS 驱动程序统计信息#
GDS 在 procfs
文件系统上公开 IO 统计信息。
要显示驱动程序统计信息,请运行以下命令。
$ cat /proc/driver/nvidia-fs/stat
查看输出,例如
GDS Version: 1.0.0.71 NVFS statistics(ver: 4.0) NVFS Driver(version: 2:7:47) Mellanox PeerDirect Supported: True IO stats: Enabled, peer IO stats: Enabled Logging level: info Active Shadow-Buffer (MiB): 0 Active Process: 0 Reads : n=0 ok=0 err=0 readMiB=0 io_state_err=0 Reads : Bandwidth(MiB/s)=0 Avg-Latency(usec)=0 Sparse Reads : n=6 io=0 holes=0 pages=0 Writes : n=0 ok=0 err=0 writeMiB=0 io_state_err=0 pg-cache=0 pg-cache-fail=0 pg-cache-eio=0 Writes : Bandwidth(MiB/s)=0 Avg-Latency(usec)=0 Mmap : n=183 ok=183 err=0 munmap=183 Bar1-map : n=183 ok=183 err=0 free=165 callbacks=18 active=0 Error : cpu-gpu-pages=0 sg-ext=0 dma-map=0 dma-ref=0 Ops : Read=0 Write=0 GPU 0000:be:00.0 uuid:87e5c586-88ed-583b-df45-fcee0f1e7917 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:e7:00.0 uuid:029faa3b-cb0d-2718-259c-6dc650c636eb : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:5e:00.0 uuid:39eeb04b-1c52-81cc-d76e-53d03eb6ed32 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:57:00.0 uuid:a99a7a93-7801-5711-258b-c6aca4fe6d85 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:39:00.0 uuid:d22b0bc4-cdb1-65ac-7495-3570e5860fda : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:34:00.0 uuid:e11b33d9-60f7-a721-220a-d14e5b15a52c : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=128 cross_root_port(%)=0 GPU 0000:b7:00.0 uuid:e8630cd2-5cb7-cab7-ef2e-66c25507c119 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:e5:00.0 uuid:b3d46477-d54f-c23f-dc12-4eb5ea172af6 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:e0:00.0 uuid:7a10c7bd-07e0-971b-a19c-61e7c185a82c : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:bc:00.0 uuid:bb96783c-5a46-233a-cbce-071aeb308083 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:e2:00.0 uuid:b6565ee8-2100-7009-bcc6-a3809905620d : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=2 cross_root_port(%)=0 GPU 0000:5c:00.0 uuid:5527d7fb-a560-ab42-d027-20aeb5512197 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:59:00.0 uuid:bb734f6b-24ad-2f83-86c3-6ab179bce131 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:3b:00.0 uuid:0ef0b9ee-bb8f-cdae-4535-c0d790b2c663 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:b9:00.0 uuid:ad59f685-5836-c2ea-2c79-3c95bea23f0d : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0 GPU 0000:36:00.0 uuid:fda65234-707b-960a-d577-18c519301848 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
17.1. nvidia-fs 统计信息#
下表描述了 nvidia-fs
统计信息。
类型 |
统计信息 |
描述 |
---|---|---|
读取 |
|
读取请求的总数。 |
|
成功读取请求的总数。 |
|
|
读取错误的次数。 |
|
Readmb (mb) |
读入 GPU 的总数据量。 |
|
|
看到的读取错误。 某些页面可能位于页面缓存中。 |
|
读取 |
带宽 (MB/s) |
IO 正在进行时的活动读取带宽。这是从 IO 提交到 GDS 内核驱动程序到 GDS 内核驱动程序收到 IO 完成的时间段。 没有用户空间参与。 |
平均延迟 (usec) |
IO 正在进行时的活动读取延迟。这是从 IO 提交到 GDS 内核驱动程序到 GDS 内核驱动程序收到 IO 完成的时间段。 没有用户空间参与。 |
|
稀疏读取 |
|
稀疏读取请求的总数。 |
|
读取期间观察到的空洞总数。 |
|
|
跨越空洞的页面总数。 |
|
写入 |
|
写入请求的总数。 |
|
成功写入请求的总数。 |
|
|
写入错误的次数。 |
|
Writemb (mb) |
从 GPU 写入到磁盘的总数据量。 |
|
|
看到的写入错误。 某些页面可能位于页面缓存中。 |
|
|
在页面缓存中找到的写入请求总数。 |
|
|
在页面缓存中找到但无法刷新的写入请求总数。 |
|
|
在 |
|
写入 |
带宽 (MB/s) |
IO 正在进行时的活动写入带宽。这是从 IO 提交到 GDS 内核驱动程序到 GDS 内核驱动程序收到 IO 完成的时间段。 没有用户空间参与。 |
平均延迟 (\(\mu\)sec) |
IO 正在进行时的活动写入延迟。这是从 IO 提交到 GDS 内核驱动程序到 GDS 内核驱动程序收到 IO 完成的时间段。 没有用户空间参与。 |
|
Mmap |
|
发出的 mmap 系统调用的总数。 |
|
成功 mmap 系统调用的总数。 |
|
|
通过 mmap 系统调用观察到的错误。 |
|
|
发出的 munmap 总数。 |
|
Bar-map |
|
GPU BAR 内存被固定的总次数。 |
|
成功 GPU BAR 内存被固定的总次数。 |
|
|
在 BAR1 固定期间观察到的错误总数。 |
|
|
BAR1 内存被解除固定的总次数。 |
|
|
NVIDIA 内核驱动程序调用 GDS 驱动程序回调的总次数。这在以下实例中调用
|
|
|
固定的 BAR1 内存的活动数量。 (此值为总数,而不是总内存。) |
|
Error |
|
当调用 |
|
由于 GPU 页面数大于 |
|
|
DMA 映射错误。 |
|
Ops |
Read |
正在进行的活动读取 IO 的总数。 |
Write |
正在进行的活动写入 IO 的总数。 |
17.2. 分析每个 GPU 的统计信息#
您可以分析每个 GPU 的统计信息,以更好地了解该 GPU 中正在发生的情况。
考虑以下示例输出
GPU 0000:5e:00:0 uuid:dc87fe99-4d68-247b-b5d2-63f96d2adab1 : pinned_MB=0 cache_MB=0 max_pinned_MB=79
GPU 0000:b7:00:0 uuid:b3a6a195-d08c-09d1-bf8f-a5423c277c04 : pinned_MB=0 cache_MB=0 max_pinned_MB=76
GPU 0000:e7:00:0 uuid:7c432aed-a612-5b18-76e7-402bb48f21db : pinned_MB=0 cache_MB=0 max_pinned_MB=80
GPU 0000:57:00:0 uuid:aa871613-ee53-9a0c-a546-851d1afe4140 : pinned_MB=0 cache_MB=0 max_pinned_MB=80
在此示例输出中,0000:5e:00:0
是 GPU 的 PCI BDF,其 UUID 为 Dc87fe99-4d68-247b-b5d2-63f96d2adab1
。这与可用于观察此 GPU 的 nvidia-smi
统计信息的 UUID 相同。
以下是有关统计信息的一些附加信息
pinned-MB
显示使用 GDS 驱动程序中的nvidia_p2p_get_pages
固定的活动 GPU 内存,以 MB 为单位,跨所有活动进程。cache_MB
显示使用nvidia_p2p_get_pages
固定的活动 GPU 内存,但此内存被 GDS 用作内部缓存,跨所有活动进程。max_pinned_MB
显示 GDS 在任何时间点在此 GPU 上跨多个进程固定的最大 GPU 内存。此值指示管理员可用于系统大小调整的最大 BAR 大小。
17.3. 重置 nvidia-fs 统计信息#
要重置 nvidia-fs
统计信息,请运行以下命令
$ sudo bash
$ echo 1 >/proc/driver/nvidia-fs/stats
17.4. 检查内核文件系统和存储驱动程序的对等亲缘性统计信息#
以下 proc
文件包含有关通过 nvidia-fs
回调的对等亲缘性 DMA 统计信息
nvidia-fs
/stats
nvidia-fs
/peer_affinity
nvidia-fs
/peer_distance
要启用统计信息,请运行以下命令
$ sudo bash
$ echo 1 > /sys/module/nvidia_fs/parameters/peer_stats_enabled
要以常规用户身份查看合并的统计信息,请运行以下命令
$ cat /proc/driver/nvidia-fs/stats
示例输出
GDS Version: 1.0.0.71
NVFS statistics(ver: 4.0)
NVFS Driver(version: 2:7:47)
Mellanox PeerDirect Supported: True
IO stats: Enabled, peer IO stats: Enabled
Logging level: info
Active Shadow-Buffer (MiB): 0
Active Process: 0
Reads : n=0 ok=0 err=0 readMiB=0 io_state_err=0
Reads : Bandwidth(MiB/s)=0 Avg-Latency(usec)=0
Sparse Reads : n=6 io=0 holes=0 pages=0
Writes : n=0 ok=0 err=0 writeMiB=0 io_state_err=0 pg-cache=0 pg-cache-fail=0 pg-cache-eio=0
Writes : Bandwidth(MiB/s)=0 Avg-Latency(usec)=0
Mmap : n=183 ok=183 err=0 munmap=183
Bar1-map : n=183 ok=183 err=0 free=165 callbacks=18 active=0
Error : cpu-gpu-pages=0 sg-ext=0 dma-map=0 dma-ref=0
Ops : Read=0 Write=0
GPU 0000:be:00.0 uuid:87e5c586-88ed-583b-df45-fcee0f1e7917 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:e7:00.0 uuid:029faa3b-cb0d-2718-259c-6dc650c636eb : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:5e:00.0 uuid:39eeb04b-1c52-81cc-d76e-53d03eb6ed32 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:57:00.0 uuid:a99a7a93-7801-5711-258b-c6aca4fe6d85 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:39:00.0 uuid:d22b0bc4-cdb1-65ac-7495-3570e5860fda : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:34:00.0 uuid:e11b33d9-60f7-a721-220a-d14e5b15a52c : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=128 cross_root_port(%)=0
GPU 0000:b7:00.0 uuid:e8630cd2-5cb7-cab7-ef2e-66c25507c119 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:e5:00.0 uuid:b3d46477-d54f-c23f-dc12-4eb5ea172af6 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:e0:00.0 uuid:7a10c7bd-07e0-971b-a19c-61e7c185a82c : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:bc:00.0 uuid:bb96783c-5a46-233a-cbce-071aeb308083 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:e2:00.0 uuid:b6565ee8-2100-7009-bcc6-a3809905620d : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=2 cross_root_port(%)=0
GPU 0000:5c:00.0 uuid:5527d7fb-a560-ab42-d027-20aeb5512197 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:59:00.0 uuid:bb734f6b-24ad-2f83-86c3-6ab179bce131 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:3b:00.0 uuid:0ef0b9ee-bb8f-cdae-4535-c0d790b2c663 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:b9:00.0 uuid:ad59f685-5836-c2ea-2c79-3c95bea23f0d : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
GPU 0000:36:00.0 uuid:fda65234-707b-960a-d577-18c519301848 : Registered_MiB=0 Cache_MiB=0 max_pinned_MiB=1 cross_root_port(%)=0
cross_root_port (%)
端口是通过 nvidia-fs
回调的总 DMA 流量的百分比,此值跨越 GPU 和其对等设备(如 HCA)之间的 PCIe 根端口。
这可能是某些平台上吞吐量低的主要原因。
这不考虑通过
cudaMemcpyDeviceToDevice
或cuMemcpyPeer
与指定 GPU 启动的 DMA 流量。
17.5. 检查内核文件系统和存储驱动程序的对等亲缘性使用情况#
要获取内核文件系统和存储驱动程序的对等亲缘性使用情况,请运行以下命令
$ cat /proc/driver/nvidia-fs/peer_affinity
查看示例输出,例如
GPU P2P DMA distribution based on pci-distance (last column indicates p2p via root complex) GPU :0000:bc:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e0:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e5:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:57:00.0 :0 0 524288 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:59:00.0 :0 0 524288 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:be:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:34:00.0 :0 0 1274489 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e7:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:b7:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:36:00.0 :0 0 524288 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:3b:00.0 :0 0 524288 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:39:00.0 :0 0 524288 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:b9:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:5c:00.0 :0 0 524288 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:e2:00.0 :0 0 39434 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 GPU :0000:5e:00.0 :0 0 513889 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
每一行代表一个 GPU 条目,列指示对等设备的等级,按升序排列。等级越低,亲缘性越好。每一列条目是指定 GPU 与属于同一等级的对等设备之间发生的 DMA 事务总数。
例如,GPU 0000:34:00.0
行通过等级 3 的对等设备具有 2621440
次 IO 操作。最后一列中的非零值表示 IO 通过根复合体路由。
以下是一些示例
运行以下命令
$ /usr/local/cuda-x.y/gds/samples /mnt/lustre/test 0
$ cat /proc/driver/nvidia-fs/stats
以下是输出
GDS Version: 1.0.0.71
NVFS statistics(ver: 4.0)
NVFS Driver(version: 2:7:47)
Mellanox PeerDirect Supported: True
IO stats: Enabled, peer IO stats: Enabled
Logging level: info
Active Shadow-Buffer (MB): 0
Active Process: 0
Reads : n=0 ok=0 err=0 readmb=0 io_state_err=0
Reads : Bandwidth(MB/s)=0 Avg-Latency(usec)=0
Sparse Reads : n=0 io=0 holes=0 pages=0
Writes : n=1 ok=1 err=0 writemb=0 io_state_err=0 pg-cache=0 pg-cache-fail=0
pg-cache-eio=0
Writes : Bandwidth(MB/s)=0 Avg-Latency(usec)=0
Mmap : n=1 ok=1 err=0 munmap=1
Bar1-map : n=1 ok=1 err=0 free=1 callbacks=0 active=0
Error : cpu-gpu-pages=0 sg-ext=0 dma-map=0
Ops : Read=0 Write=0
GPU 0000:34:00:0 uuid:98bb4b5c-4576-b996-3d84-4a5d778fa970 : pinned_MB=0 cache_MB=0 max_pinned_MB=0 cross_root_port(%)=100
运行以下命令
$ cat /proc/driver/nvidia-fs/peer_affinity
以下是输出
GPU P2P DMA distribution based on pci-distance
(last column indicates p2p via root complex)
GPU :0000:b7:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:b9:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:bc:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:be:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e0:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e2:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e5:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e7:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:34:00:0 :0 0 0 0 0 0 0 0 0 0 0 2
GPU :0000:36:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:39:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:3b:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:57:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:59:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:5c:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:5e:00:0 :0 0 0 0 0 0 0 0 0 0 0 0
在上面的示例中,GPU (34:00.0
) 和其一个对等设备之间存在 DMA 事务。对等设备具有最高可能的等级,这表明它在 pci 距离方面离相应的 GPU 最远。
要检查流量百分比,请检查 /proc/driver/nvidia-fs/stats
中的 cross_root_ port %
。在上面的第三个示例中,此值为 100%
,这意味着对等流量正在通过 QPI 链路进行。
17.6. 显示 GPU 到对等设备的距离表#
peer_distance
表显示每个对等设备的设备级 IO 分布及其针对指定 GPU 的等级,它补充了基于等级的统计信息。
peer_distance 表显示每个对等设备的设备级 IO 分布及其针对指定 GPU 的等级。它补充了基于等级的统计信息。
排名按以下顺序进行
主要优先级给予 p2p 距离(高 2 字节)。
次要优先级给予设备带宽(低 2 字节)
对于跨越根端口的对等路径,会增加 p2p 距离的固定成本 (127)。这样做是为了诱导优先选择一个 CPU 根端口下的路径,而不是跨越 CPU 根端口的路径。
发出以下命令
$ cat /proc/driver/nvidia-fs/peer_distance
示例输出
gpu peer peerrank p2pdist np2p link gen class
0000:af:00.0 0000:86:00.0 0x820088 0x82 0 0x8 0x3 network
0000:af:00.0 0000:18:00.0 0x820088 0x82 0 0x8 0x3 nvme
0000:af:00.0 0000:86:00.1 0x820088 0x82 0 0x8 0x3 network
0000:af:00.0 0000:19:00.1 0x820088 0x82 0 0x8 0x3 network
0000:af:00.0 0000:87:00.0 0x820088 0x82 0 0x8 0x3 nvme
0000:af:00.0 0000:19:00.0 0x820088 0x82 0 0x8 0x3 network
0000:3b:00.0 0000:86:00.0 0x820088 0x82 0 0x8 0x3 network
0000:3b:00.0 0000:18:00.0 0x820088 0x82 0 0x8 0x3 nvme
0000:3b:00.0 0000:86:00.1 0x820088 0x82 0 0x8 0x3 network
0000:3b:00.0 0000:19:00.1 0x820088 0x82 0 0x8 0x3 network
0000:3b:00.0 0000:87:00.0 0x820088 0x82 0 0x8 0x3 nvme
0000:3b:00.0 0000:19:00.0 0x820088 0x82 0 0x8 0x3 network
0000:5e:00.0 0000:86:00.0 0x820088 0x82 0 0x8 0x3 network
0000:5e:00.0 0000:18:00.0 0x820088 0x82 0 0x8 0x3 nvme
0000:5e:00.0 0000:86:00.1 0x820088 0x82 0 0x8 0x3 network
0000:5e:00.0 0000:19:00.1 0x820088 0x82 0 0x8 0x3 network
0000:5e:00.0 0000:87:00.0 0x820088 0x82 0 0x8 0x3 nvme
0000:5e:00.0 0000:19:00.0 0x820088 0x82 0 0x8 0x3 network
0000:d8:00.0 0000:86:00.0 0x820088 0x82 0 0x8 0x3 network
0000:d8:00.0 0000:18:00.0 0x820088 0x82 0 0x8 0x3 nvme
0000:d8:00.0 0000:86:00.1 0x820088 0x82 0 0x8 0x3 network
0000:d8:00.0 0000:19:00.1 0x820088 0x82 0 0x8 0x3 network
0000:d8:00.0 0000:87:00.0 0x820088 0x82 0 0x8 0x3 nvme
0000:d8:00.0 0000:19:00.0 0x820088 0x82 0 0x8 0x3 network
17.7. GDSIO 工具#
GDSIO 是一个综合 IO 基准测试工具,它使用 cufile API 进行 IO。该工具位于 /usr/local/cuda-x.y/tools
目录中。有关如何使用此工具的更多信息,请运行 /usr/local/cuda-x.y/tools/gdsio -h
或查看 /usr/local/cuda-x.y/tools/README
文件中的 gdsio 部分。在下面的示例中,文件是在 ext4 文件系统上创建的。
发出以下命令
# ./gdsio -f /root/sg/test -d 0 -w 4 -s 1M -x 0 -i 4K:32K:1K -I 1
示例输出
IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 671/1024(KiB)
IOSize: 4-32-1(KiB) Throughput: 0.044269 GiB/sec, Avg_Latency:
996.094925 usecs ops: 60 total_time 0.014455 secs
此命令在名为 test 的文件上执行写入 IO (-I 1
),文件大小为 1MiB (-s 1M
),IO 大小在 4KiB 到 32 KiB 之间变化,步长为 1KiB (-i 4K:32K:1K)。传输使用 GDS (-x 0
) 完成,使用 4 个线程 (-w 4
) 在 GPU 0 (-d 0
) 上。
该工具的一些附加功能包括
支持在文件中的随机偏移量处进行读/写。
gdsio 工具提供选项以在随机偏移量处对文件执行读取和写入操作。
使用 -I 2 和 -I 3 选项分别以随机偏移量执行文件读取和写入操作,但随机偏移量始终为 4KiB 对齐。
# ./gdsio -f /root/sg/test -d 0 -w 4 -s 1M -x 0 -i 4K:32K:1K -I 3 IoType: RANDWRITE XferType: GPUD Threads: 4 DataSetSize: 706/1024(KiB) IOSize: 4-32-1(KiB) Throughput: 0.079718 GiB/sec, Avg_Latency: 590.853274 usecs ops: 44 total_time 0.008446 secs
要以未对齐的 4KiB 偏移量执行随机读取和写入,可以将
-U
选项与-I 0
或-I 1
分别用于读取和写入。# ./gdsio -f /root/sg/test -d 0 -w 4 -s 1M -x 0 -i 4K:32K:1K -I 1 -U IoType: RANDWRITE XferType: GPUD Threads: 4 DataSetSize: 825/1024(KiB) IOSize: 4-32-1(KiB) Throughput: 0.055666 GiB/sec, Avg_Latency: 919.112500 usecs ops: 49 total_time 0.014134 secs
用于重复数据删除和压缩的随机缓冲区填充。
使用
-R
选项使用随机数据填充 io 大小缓冲区 (-i
)。然后,此随机数据将写入文件中的不同文件偏移量。# ./gdsio -f /root/sg/test -d 0 -w 4 -s 1M -x 0 -i 4K:32K:1K -I 1 -R IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 841/1024(KiB) IOSize: 4-32-1(KiB) Throughput: 0.059126 GiB/sec, Avg_Latency: 788.884580 usecs ops: 69 total_time 0.013565 secs
使用
-F
选项将使用随机数据填充整个文件。# ./gdsio -f /root/sg/test -d 0 -w 4 -s 1M -x 0 -i 4K:32K:1K -I 1 -F IoType: WRITE XferType: GPUD Threads: 4 DataSetSize: 922/1024(KiB) IOSize: 4-32-1(KiB) Throughput: 0.024376 GiB/sec, Avg_Latency: 1321.104532 usecs ops: 73 total_time 0.036072 secs
这对于使用重复数据删除和压缩算法以最大限度减少磁盘访问的文件系统非常有用。使用随机数据增加了这些文件系统更频繁地访问后端磁盘的可能性。
可变块大小。
要在文件上执行读取或写入操作,您可以指定块大小 (-i),它表示 IO 将以块大小长度的块执行。要检查所使用的块大小的统计信息,请使用
gds_stats
工具。确保/etc/cufile.json
文件已将 cufile_stats 设置为 3# ./gds_stats -p <pid of the gdsio process> -l 3
示例输出
0-4(KiB): 0 0 4-8(KiB): 0 17205 8-16(KiB): 0 45859 16-32(KiB): 0 40125 32-64(KiB): 0 0 64-128(KiB): 0 0 128-256(KiB): 0 0 256-512(KiB): 0 0 512-1024(KiB): 0 0 1024-2048(KiB): 0 0 2048-4096(KiB): 0 0 4096-8192(KiB): 0 0 8192-16384(KiB): 0 0 16384-32768(KiB): 0 0 32768-65536(KiB): 0 0 65536-...(KiB): 0 0
突出显示的计数器显示,对于上面的命令,用于文件 IO 的块大小范围为 4-32 KiB。
验证模式用法和限制。
为了确保数据完整性,可以选择使用
-V
选项在验证模式下执行写入和读取 IO。这是一个示例# ./gdsio -V -f /root/sg/test -d 0 -w 1 -s 2G -o 0 -x 0 -k 0 -i 4K:32K:1K -I 1 IoType: WRITE XferType: GPUD Threads: 1 DataSetSize: 2097144/2097152(KiB) IOSize: 4-32-1(KiB) Throughput: 0.074048 GiB/sec, Avg_Latency: 231.812570 usecs ops: 116513 total_time 27.009349 secs Verifying data IoType: READ XferType: GPUD Threads: 1 DataSetSize: 2097144/2097152(KiB) IOSize: 4-32-1(KiB) Throughput: 0.103465 GiB/sec, Avg_Latency: 165.900663 usecs ops: 116513 total_time 19.330184 secs
以上命令将执行写入,然后执行读取验证测试。
使用验证模式时,请记住以下几点
带有验证选项 (
-V
) 的读取测试 (-I 0) 应与使用-V
选项写入 (-I 1) 的文件一起使用带有验证选项 (
-V
) 的读取测试 (-I 2) 应与使用-V
选项写入 (-I 3) 的文件一起使用,并使用相同的随机种子 (-k
) 使用相同数量的线程、偏移量和数据大小带有验证选项 (
-V
) 的写入测试 (-I 1/3) 将执行写入,然后执行读取。验证模式不能在定时模式 (
-T
选项) 中使用。如果在定时模式下使用验证模式,它将被忽略。
配置文件
GDSIO 提供了一个选项,用于配置执行 IO 所需的参数,并在配置文件中使用这些配置运行 IO。配置文件提供了执行多个作业的选项,其中每个作业都有一些不同的配置。
配置文件具有全局参数和作业特定参数支持。例如,使用配置文件,您可以配置每个作业在 GPU 上执行,并使用不同数量的线程。全局参数(例如 IO 大小和传输模式)对于每个作业保持不变。有关更多信息,请参阅
/usr/local/cuda-x.y/tools/README
和/usr/local/cuda-x.y/tools/rw-sample.gdsio
文件。配置参数后,要使用配置文件执行 IO 操作,请运行以下命令# ./gdsio <config file name>
有关表格字段的列表,请参见 表格字段。
17.8. 表格字段#
下表描述了 #./gdsio <config file name>
命令输出中的表格字段。
全局选项 |
描述 |
---|---|
|
GDSIO 传输类型
|
|
IO 类型,rw=read,rw=write,rw=randread,rw=randwrite |
|
块大小,例如,bs=1M,对于可变块大小,可以指定范围,例如,bs=1M:4M:1M,(1M:起始块大小,4M:结束块大小,1M:大小变化的步长)。 |
|
文件大小,例如,size=2G。 |
|
持续时间(秒)。 |
|
使用 1 启用验证 |
|
跳过 cufile 缓冲区注册,在 cpu 模式下忽略。 |
|
设置 NVlinks。 如果 p2p 流量是跨节点的,则建议使用此字段。 |
|
使用随机种子,例如,1234。 |
|
每次写入后重新填充 io 缓冲区。 |
|
用随机数据填充请求缓冲区。 |
|
使用非页面对齐的随机偏移量。 |
|
从文件偏移量开始读取/写入。 |
每个作业的选项 |
描述 |
|
NUMA 节点。 |
|
GPU 设备索引(检查 nvidia-smi)。 |
|
每个作业的 IO 线程数。 |
|
文件所在的目录名称。每个线程将基于每个文件工作。 |
|
单文件模式的文件名,其中线程共享同一文件。(注意:目录模式和文件模式不应在作业中混合使用)。 |
|
要使用的内存类型。支持的值:0 - ( |
|
文件描述符模式。0 - O_DIRECT (默认) 1 - non-O_DIRECT |
17.9. gdscheck 工具#
/usr/local/cuda-x.y/tools/gdscheck.py
工具用于执行 GDS 平台检查,并具有其他选项,可以使用 -h
选项找到这些选项。
$ ./gdscheck.py -h
usage: gdscheck.py [-h] [-p] [-f FILE] [-v] [-V]
GPUDirectStorage platform checker
optional arguments:
-h, --help show this help message and exit
-p gds platform check
-f FILE gds file check
-v gds version checks
-V gds fs checks
要执行 GDS 平台检查,请发出以下命令并期望输出采用以下格式
# ./gdscheck.py -p
GDS release version: 1.0.0.78
nvidia_fs version: 2.7 libcufile version: 2.4
============
ENVIRONMENT:
============
=====================
DRIVER CONFIGURATION:
=====================
NVMe : Supported
NVMeOF : Unsupported
SCSI : Unsupported
ScaleFlux CSD : Unsupported
NVMesh : Unsupported
DDN EXAScaler : Supported
IBM Spectrum Scale : Unsupported
NFS : Unsupported
WekaFS : Unsupported
Userspace RDMA : Unsupported
--Mellanox PeerDirect : Enabled
--rdma library : Not Loaded (libcufile_rdma.so)
--rdma devices : Not configured
--rdma_device_status : Up: 0 Down: 0
=====================
CUFILE CONFIGURATION:
=====================
properties.use_compat_mode : true
properties.gds_rdma_write_support : true
properties.use_poll_mode : false
properties.poll_mode_max_size_kb : 4
properties.max_batch_io_timeout_msecs : 5
properties.max_direct_io_size_kb : 16384
properties.max_device_cache_size_kb : 131072
properties.max_device_pinned_mem_size_kb : 33554432
properties.posix_pool_slab_size_kb : 4 1024 16384
properties.posix_pool_slab_count : 128 64 32
properties.rdma_peer_affinity_policy : RoundRobin
properties.rdma_dynamic_routing : 0
fs.generic.posix_unaligned_writes : false
fs.lustre.posix_gds_min_kb: 0
fs.weka.rdma_write_support: false
profile.nvtx : false
profile.cufile_stats : 0
miscellaneous.api_check_aggressive : false
=========
GPU INFO:
=========
GPU index 0 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 1 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 2 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 3 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 4 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 5 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 6 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 7 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 8 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 9 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 10 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 11 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 12 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 13 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 14 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
GPU index 15 Tesla V100-SXM3-32GB bar:1 bar size (MiB):32768 supports GDS
==============
PLATFORM INFO:
==============
IOMMU: disabled
Platform verification succeeded
17.10. GPUDirect 存储的 NFS 支持#
本节提供有关 GDS 的 NFS 支持的信息。
17.10.1. 在 MLNX_OFED 5.3 或更高版本上安装带有 RDMA 支持的 Linux NFS 服务器#
要安装带有 RDMA 支持的标准 Linux 基于内核的 NFS 服务器,请完成以下步骤
注意
服务器必须具有 Mellanox connect-X4/5 NIC,并安装了 MLNX_OFED 5.3 或更高版本。
发出以下命令
$ ofed_info -s MLNX_OFED_LINUX-5.3-1.0.5.1:
查看输出以确保服务器已安装。
$ sudo apt-get install nfs-kernel-server $ mkfs.ext4 /dev/nvme0n1 $ mount -o data=ordered /dev/nvme0n1 /mnt/nvme $ cat /etc/exports /mnt/nvme *(rw,async,insecure,no_root_squash,no_subtree_check) $ service nfs-kernel-server restart $ modprobe rpcrdma $ echo rdma 20049 > /proc/fs/nfsd/portlist
17.10.2. 为 NFS 客户端安装 GPUDirect 存储支持#
要安装带有 GDS 支持的 NFS 客户端,请完成以下步骤
注意
客户端必须具有 Mellanox connect-X4/5 NIC,并安装了 MLNX_OFED 5.3 或更高版本。
发出以下命令
$ ofed_info -s MLNX_OFED_LINUX-5.3-1.0.5.0:
查看输出以确保支持存在。
$ sudo apt-get install nfs-common $ modprobe rpcrdma $ mkdir -p /mnt/nfs_rdma_gds $ sudo mount -v -o proto=rdma,port=20049,vers=3 172.16.0.101:/ /mnt/nfs_rdma_gds To mount with nconnect using VAST nfs client package: Eg: client IB interfaces 172.16.0.17 , 172.16.0.18, 172.16.0.19, 172.16.0.20, 172.16.0.21,172.16.0.22,172.16.0.23 172.16.0.24 $ sudo mount -v -o proto=rdma,port=20049,vers=3,nconnect=20,localports=172.16.0.17-172.16.0.24,remoteports=172.16.0.101-172.16.0.120 172.16.0.101:/ /mnt/nfs_rdma_gds
17.11. NFS GPUDirect 存储统计信息和调试#
可以使用用于监视 IO 的常规 Linux 工具(如 iotop
和 nfsstat
)来观察 NFS IO。
要启用 NFS RPC 统计信息调试,请运行以下命令
$ rpcdebug -v
要观察 GDS 相关的 IO 统计信息,请运行以下命令
$ cat /proc/driver/nvidia-fs/stats
要确定每个进程的 GDS 统计信息,请运行以下命令
$ /usr/local/cuda-x.y/tools/gds_stats -p <PID> -l 3
17.12. GPUDirect 存储 IO 行为#
本节提供有关 GDS 中的 IO 行为的信息。
17.12.1. 使用 GPUDirect 存储 Direct IO 的读取/写入原子性一致性#
在 GDS 中,max_direct_io_size_kb
属性控制 IO 单元大小,该限制以该大小发出到基础文件系统。默认情况下,此值为 16MB。这意味着从 Linux VFS 的角度来看,原子性大小限制为 max_direct_io_size_kb
大小,而不是原始请求大小。此限制存在于标准 GDS 路径和兼容模式中。
17.12.2. 以 O_APPEND 模式打开的文件写入 (cuFileWrite)#
对于以 O_APPEND 模式打开且具有并发写入器的文件,如果使用的 IO 大小大于 max_direct_io_size_kb
属性,则由于写入原子性限制,该文件可能包含来自多个写入器的交错数据。即使底层文件系统具有锁定保证,也无法阻止这种情况。
17.12.3. GPU 到 NIC 的对等亲缘性#
该库维护一个对等亲缘性表,该表是基于 pci 距离的 GPU 和平台中可用 NIC 的排名,用于 RDMA。目前,排名中的限制不考虑 NIC 的 NUMA 属性。对于不与 GPU 共享公共根端口的 NIC,即使存在与 GPU 位于同一 CPU 插槽上的 NIC,P2P 流量也可能通过 QPI 链路跨套接字路由。
17.12.4. 带有未注册缓冲区的兼容模式#
目前,在兼容模式下,带有未注册缓冲区的 IO 路径不具有最佳性能,并且在每次 cuFileRead 或 cuFileWrite 中都进行缓冲区分配和释放。
17.12.5. 使用非注册缓冲区执行未对齐写入#
对于未对齐写入,与注册缓冲区相比,使用非注册缓冲区可能无法获得最佳性能。
17.12.6. NFS 中的进程挂起#
当应用程序崩溃时,在 NFS 环境中观察到进程挂起。
17.12.7. CUDA 9 及更早版本的工具支持限制#
gdsio 二进制文件是针对 CUDA 运行时 10.1 构建的,并且依赖于 CUDA 运行时环境的版本等于或高于 10.1。否则,该工具将报告驱动程序依赖性错误。
17.13. 动态路由的 GDS 统计信息#
动态路由决策在 I/O 操作粒度上执行。GDS 用户空间统计信息包含每个 GPU 的计数器,以指示已使用动态路由路由的 I/O 数量。
条目 |
描述 |
---|---|
|
使用动态路由为给定 GPU 路由 I/O 的 |
在 PER_GPU POOL BUFFER STATS
和 PER_GPU POSIX POOL BUFFER STATS
中存在现有计数器,用户可以从中推断出动态路由选择哪些 GPU 用作反弹缓冲区。
平台上的 GPU(0 和 1)与 NIC 不共享相同的 PCIe 主桥
"rdma_dev_addr_list": [ "192.168.0.12", "192.168.1.12" ], "rdma_dynamic_routing": true, "rdma_dynamic_routing_order": [ "GPU_MEM_NVLINKS", "GPU_MEM", "SYS_MEM" ]
$ gds_stats -p <process id> -l 3
GPU 0 Read: bw=0 util(%)=0 n=0 posix=0 unalign=0 dr=0 r_sparse=0 r_inline=0 err=0 MiB=0 Write: bw=3.37598 util(%)=532 n=6629 posix=0 unalign=0 dr=6629 err=0 MiB=6629 BufRegister: n=4 err=0 free=0 MiB=4 GPU 1 Read: bw=0 util(%)=0 n=0 posix=0 unalign=0 dr=0 r_sparse=0 r_inline=0 err=0 MiB=0 Write: bw=3.29297 util(%)=523 n=6637 posix=0 unalign=0 dr=6637 err=0 MiB=6637 BufRegister: n=4 err=0 free=0 MiB=4 PER_GPU POOL BUFFER STATS: GPU : 6 pool_size_MiB : 7 usage : 1/7 used_MiB : 1 GPU : 7 pool_size_MiB : 7 usage : 0/7 used_MiB : 0 GPU : 8 pool_size_MiB : 7 usage : 2/7 used_MiB : 2 GPU : 9 pool_size_MiB : 7 usage : 2/7 used_MiB : 2 PER_GPU POSIX POOL BUFFER STATS: PER_GPU RDMA STATS: GPU 0000:34:00.0 : mlx5_3(138:48):0 mlx5_6(265:48):0 GPU 0000:36:00.0 : mlx5_3(138:48):0 mlx5_6(265:48):0 GPU 0000:39:00.0 : mlx5_3(138:48):0 mlx5_6(265:48):0 GPU 0000:3b:00.0 : mlx5_3(138:48):0 mlx5_6(265:48):0 GPU 0000:57:00.0 : mlx5_3(7:48):0 mlx5_6(265:48):0 GPU 0000:59:00.0 : mlx5_3(7:48):0 mlx5_6(265:48):0 GPU 0000:5c:00.0 : mlx5_3(3:48):3318 mlx5_6(265:48):0 GPU 0000:5e:00.0 : mlx5_3(3:48):3318 mlx5_6(265:48):0 GPU 0000:b7:00.0 : mlx5_6(3:48):3316 mlx5_3(265:48):0 GPU 0000:b9:00.0 : mlx5_6(3:48):3317 mlx5_3(265:48):0 GPU 0000:bc:00.0 : mlx5_6(7:48):0 mlx5_3(265:48):0 GPU 0000:be:00.0 : mlx5_6(7:48):0 mlx5_3(265:48):0 GPU 0000:e0:00.0 : mlx5_6(138:48):0 mlx5_3(265:48):0 GPU 0000:e2:00.0 : mlx5_6(138:48):0 mlx5_3(265:48):0 GPU 0000:e5:00.0 : mlx5_6(138:48):0 mlx5_3(265:48):0 GPU 0000:e7:00.0 : mlx5_6(138:48):0 mlx5_3(265:48):0
平台配置中,GPU 与 NIC 不共享相同的 PCIe 主桥,并且 GPU 之间没有 NVLink。对于此类配置,管理员可以设置策略以使用系统内存,而不是默认的 P2P 策略。
"rdma_dev_addr_list": [ "192.168.0.12", "192.168.1.12" ], "rdma_dynamic_routing": true, "rdma_dynamic_routing_order": [ "SYS_MEM" ]
PER_GPU STATS: GPU 4 Read: bw=0 util(%)=0 n=0 posix=0 unalign=0 r_sparse=0 r_inline=0 err=0 MiB=0 Write: bw=1.11GiB util(%)=0 n=1023 posix=1023 unalign=1023 dr=1023 err=0 MiB=1023 BufRegister: n=0 err=0 free=0 MiB=0 GPU 8 Read: bw=0 util(%)=0 n=0 posix=0 unalign=0 r_sparse=0 r_inline=0 err=0 MiB=0 Write: bw=1.11GiB util(%)=0 n=1023 posix=1023 unalign=1023 dr=1023 err=0 MiB=1023 BufRegister: n=0 err=0 free=0 MiB=0 PER_GPU POSIX POOL BUFFER STATS: GPU 4 4(KiB) :0/0 1024(KiB) :0/1 16384(KiB) :0/0 GPU 8 4(KiB) :0/0 1024(KiB) :1/1 16384(KiB) :0/0
17.13.1. 对等亲和性动态路由#
动态路由决策在 I/O 操作粒度上执行。GDS 用户空间统计信息包含每个 GPU 的计数器,以指示已使用动态路由路由的 I/O 数量。
条目 |
描述 |
---|---|
|
使用动态路由为给定 GPU 路由 I/O 的 |
在 PER_GPU POOL BUFFER STATS
和 PER_GPU POSIX POOL BUFFER STATS
中存在现有计数器,用户可以从中推断出动态路由选择哪些 GPU 用作反弹缓冲区。
// "rdma_dev_addr_list": [ "192.168.4.12", "192.168.5.12", "192.168.6.12", "192.168.7.12" ],
cufile.log:
--------------
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:133 Computing GPU->NIC affinity table:
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:34:00.0 RDMA dev: mlx5_6 mlx5_8 mlx5_7 mlx5_9
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:36:00.0 RDMA dev: mlx5_6 mlx5_8 mlx5_7 mlx5_9
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:39:00.0 RDMA dev: mlx5_6 mlx5_8 mlx5_7 mlx5_9
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:3b:00.0 RDMA dev: mlx5_6 mlx5_8 mlx5_7 mlx5_9
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:57:00.0 RDMA dev: mlx5_6 mlx5_8 mlx5_7 mlx5_9
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:59:00.0 RDMA dev: mlx5_6 mlx5_8 mlx5_7 mlx5_9
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:5c:00.0 RDMA dev: mlx5_6 mlx5_8 mlx5_7 mlx5_9
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:5e:00.0 RDMA dev: mlx5_6 mlx5_8 mlx5_7 mlx5_9
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:b7:00.0 RDMA dev: mlx5_6
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:b9:00.0 RDMA dev: mlx5_6
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:bc:00.0 RDMA dev: mlx5_7
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:be:00.0 RDMA dev: mlx5_7
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:e0:00.0 RDMA dev: mlx5_8
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:e2:00.0 RDMA dev: mlx5_8
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:e5:00.0 RDMA dev: mlx5_9
23-02-2021 10:17:49:641 [pid=22436 tid=22436] INFO curdma-ldbal:139 GPU: 0000:e7:00.0 RDMA dev: mlx5_9
gds_stats 中的一个示例,显示了示例 IO 测试期间 GPU 到 NIC 的绑定
PER_GPU RDMA STATS:
GPU 0000:34:00.0 : mlx5_6(265:48):0 mlx5_8(265:48):0 mlx5_7(265:48):0 mlx5_9(265:48):0
GPU 0000:36:00.0 : mlx5_6(265:48):0 mlx5_8(265:48):0 mlx5_7(265:48):0 mlx5_9(265:48):0
GPU 0000:39:00.0 : mlx5_6(265:48):0 mlx5_8(265:48):0 mlx5_7(265:48):0 mlx5_9(265:48):0
GPU 0000:3b:00.0 : mlx5_6(265:48):0 mlx5_8(265:48):0 mlx5_7(265:48):0 mlx5_9(265:48):0
GPU 0000:57:00.0 : mlx5_6(265:48):0 mlx5_8(265:48):0 mlx5_7(265:48):0 mlx5_9(265:48):0
GPU 0000:59:00.0 : mlx5_6(265:48):0 mlx5_8(265:48):0 mlx5_7(265:48):0 mlx5_9(265:48):0
GPU 0000:5c:00.0 : mlx5_6(265:48):0 mlx5_8(265:48):0 mlx5_7(265:48):0 mlx5_9(265:48):0
GPU 0000:5e:00.0 : mlx5_6(265:48):0 mlx5_8(265:48):0 mlx5_7(265:48):0 mlx5_9(265:48):0
GPU 0000:b7:00.0 : mlx5_6(3:48):22918 mlx5_7(7:48):0 mlx5_8(138:48):0 mlx5_9(138:48):0
GPU 0000:b9:00.0 : mlx5_6(3:48):22949 mlx5_7(7:48):0 mlx5_8(138:48):0 mlx5_9(138:48):0
GPU 0000:bc:00.0 : mlx5_7(3:48):22945 mlx5_6(7:48):0 mlx5_8(138:48):0 mlx5_9(138:48):0
GPU 0000:be:00.0 : mlx5_7(3:48):22942 mlx5_6(7:48):0 mlx5_8(138:48):0 mlx5_9(138:48):0
GPU 0000:e0:00.0 : mlx5_8(3:48):22937 mlx5_9(7:48):0 mlx5_6(138:48):0 mlx5_7(138:48):0
GPU 0000:e2:00.0 : mlx5_8(3:48):22930 mlx5_9(7:48):0 mlx5_6(138:48):0 mlx5_7(138:48):0
GPU 0000:e5:00.0 : mlx5_9(3:48):22922 mlx5_8(7:48):0 mlx5_6(138:48):0 mlx5_7(138:48):0
GPU 0000:e7:00.0 : mlx5_9(3:48):22920 mlx5_8(7:48):0 mlx5_6(138:48):0 mlx5_7(138:48):0
对于基于内核的 DFS、DDN-Lustre 和 VAST-NFS,nvidia-fs 驱动程序提供回调以确定给定目标 GPU 的最佳 NIC。nvidia-fs peer_affinity 可用于跟踪端到端 IO 亲和性行为。
例如,使用 GPU_MEM_NVLINK 的路由策略,不应看到如下面的统计信息片段所示的跨端口流量
$ cat /proc/driver/nvidia-fs/peer_affinity
GPU P2P DMA distribution based on pci-distance
(last column indicates p2p via root complex)
GPU :0000:bc:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e0:00.0 :0 0 205305577 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e5:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:57:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:59:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:be:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:34:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e7:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:b7:00.0 :0 0 205279892 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:36:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:3b:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:39:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:b9:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:5c:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e2:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:5e:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
使用 P2P 的路由策略,可以预期看到如下面的统计信息片段所示的跨端口流量
dgxuser@e155j-dgx2-c6-u04:~/ssen$ cat /proc/driver/nvidia-fs/peer_affinity
GPU P2P DMA distribution based on pci-distance
(last column indicates p2p via root complex)
GPU :0000:bc:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e0:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e5:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:57:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:59:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:be:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:34:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9186359
GPU :0000:e7:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:b7:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:36:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9191164
GPU :0000:3b:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9194318
GPU :0000:39:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9188836
GPU :0000:b9:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:5c:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:e2:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
GPU :0000:5e:00.0 :0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
18. GDS 库跟踪#
GDS 库具有 USDT(静态跟踪点),可以与 Linux 工具(如 lttng
、bcc
/bpf
、perf
)一起使用。本节假定您熟悉这些工具。
本节中的示例显示了使用 `bcc
/bpf
<iovisor/bcc>`__ 跟踪工具进行跟踪。GDS 不附带这些跟踪工具。有关安装 bcc/bpf 工具的更多信息,请参阅 安装 BCC。用户必须具有 root 权限才能安装。
注意
用户还必须具有 sudo
访问权限才能使用这些工具。
18.1. 示例:显示跟踪点#
要显示跟踪点,请运行以下命令
# ./tplist -l /usr/local/gds/lib/libcufile.so
查看输出,例如
/usr/local/cuda-x.y/lib/libcufile.so cufio:cufio_px_read /usr/local/cuda-x.y/lib/libcufile.so cufio:cufio_rdma_read /usr/local/cuda-x.y/lib/libcufile.so cufio:cufio_gds_read /usr/local/cuda-x.y/lib/libcufile.so cufio:cufio_gds_read_async /usr/local/cuda-x.y/lib/libcufile.so cufio:cufio_px_write /usr/local/cuda-x.y/lib/libcufile.so cufio:cufio_gds_write /usr/local/cuda-x.y/lib/libcufile.so cufio:cufio_gds_write_async /usr/local/cuda-x.y/lib/libcufile.so cufio-internal:cufio-internal-write-bb /usr/local/cuda-x.y/lib/libcufile.so cufio-internal:cufio-internal-read-bb /usr/local/cuda-x.y/lib/libcufile.so cufio-internal:cufio-internal-bb-done /usr/local/cuda-x.y/lib/libcufile.so cufio-internal:cufio-internal-io-done /usr/local/cuda-x.y/lib/libcufile.so cufio-internal:cufio-internal-map
18.1.1. 示例:跟踪点参数#
以下是跟踪点参数的示例。
cufio_px_read
此跟踪点跟踪 POSIX IO 读取,并接受以下参数
参数 1:文件描述符
参数 2:文件偏移量
参数 3:读取大小
参数 4:GPU 缓冲区偏移量
参数 5:返回值
参数 6:执行 IO 的 GPU ID
cufio_rdma_read
此跟踪点跟踪通过 WEKA 文件系统的 IO 读取,并接受以下参数
参数 1:文件描述符
参数 2:文件偏移量
参数 3:读取大小
参数 4:GPU 缓冲区偏移量
参数 5:返回值
参数 6:执行 IO 的 GPU ID
参数 7:IO 是否对 GPU 反弹缓冲区执行
cufio_rdma_write
此跟踪点跟踪通过 WEKA 文件系统的 IO 读取,并接受以下参数
参数 1:文件描述符
参数 2:文件偏移量
参数 3:写入大小
参数 4:GPU 缓冲区偏移量
参数 5:返回值
参数 6:执行 IO 的 GPU ID
参数 7:IO 是否对 GPU 反弹缓冲区执行
cufio_gds_read
此跟踪点跟踪通过 GDS 内核驱动程序的 IO 读取,并接受以下参数
参数 1:文件描述符
参数 2:文件偏移量
参数 3:读取大小
参数 4:GPU 缓冲区偏移量
参数 5:返回值
参数 6:执行 IO 的 GPU ID
参数 7:IO 是否对 GPU 反弹缓冲区执行
cufio_gds_read_async
此跟踪点跟踪通过 GDS 内核驱动程序的 IO 读取,并设置了轮询模式,并接受以下参数
参数 1:文件描述符
参数 2:文件偏移量
参数 3:读取大小
参数 4:GPU 缓冲区偏移量
参数 5:返回值
参数 6:执行 IO 的 GPU ID
参数 7:IO 是否对 GPU 反弹缓冲区执行
cufio_px_write
此跟踪点跟踪 POSIX IO 写入,并接受以下参数
参数 1:文件描述符
参数 2:文件偏移量
参数 3:写入大小
参数 4:GPU 缓冲区偏移量
参数 5:返回值
参数 6:执行 IO 的 GPU ID
cufio_gds_write
此跟踪点跟踪通过 GDS 内核驱动程序的 IO 写入,并接受以下参数
参数 1:文件描述符
参数 2:文件偏移量
参数 3:写入大小
参数 4:GPU 缓冲区偏移量
参数 5:返回值
参数 6:执行 IO 的 GPU ID
参数 7:IO 是否对 GPU 反弹缓冲区执行
cufio_gds_unaligned_write
如果 IO 未对齐,则此跟踪点跟踪通过 GDS 内核驱动程序的 IO 写入,并接受以下参数
参数 1:文件描述符
参数 2:文件偏移量
参数 3:写入大小
参数 4:GPU 缓冲区偏移量
参数 5:返回值
参数 6:执行 IO 的 GPU ID
参数 7:IO 是否对 GPU 反弹缓冲区执行
cufio_gds_write_async
此跟踪点跟踪通过 GDS 内核驱动程序的 IO 写入,并设置了轮询模式,并接受以下参数
参数 1:文件描述符
参数 2:文件偏移量
参数 3:写入大小
参数 4:GPU 缓冲区偏移量
参数 5:返回值
参数 6:执行 IO 的 GPU ID
参数 7:IO 是否对 GPU 反弹缓冲区执行
cufio-internal-write-bb
此跟踪点跟踪通过内部 GPU 反弹缓冲区的 IO 写入,并且特定于 EXAScaler 文件系统和基于块设备的文件系统。此跟踪点位于每个 IO 的热 IO 路径跟踪中,并接受以下参数
参数 1:应用程序 GPU(GPU ID)
参数 2:GPU 反弹缓冲区(GPU ID)
参数 3:文件描述符
参数 4:文件偏移量
参数 5:写入大小
参数 6:应用程序 GPU 缓冲区偏移量
参数 7:从应用程序 GPU 缓冲区传输到目标 GPU 反弹缓冲区的字节大小。
参数 8:到目前为止通过反弹缓冲区传输的总字节大小。
参数 9:此事务中的待处理 IO 计数
cufio-internal-read-bb
此跟踪点跟踪通过内部 GPU 反弹缓冲区的 IO 读取,并且特定于 EXAScaler 文件系统和基于块设备的文件系统。此跟踪点位于每个 IO 的热 IO 路径跟踪中,并接受以下参数
参数 1:应用程序 GPU(GPU ID)
参数 2:GPU 反弹缓冲区(GPU ID)
参数 3:文件描述符
参数 4:文件偏移量
参数 5:读取大小
参数 6:应用程序 GPU 缓冲区偏移量
参数 7:从 GPU 反弹缓冲区传输到应用程序 GPU 缓冲区的字节大小。
参数 8:到目前为止通过反弹缓冲区传输的总字节大小。
参数 9:此事务中的待处理 IO 计数。
cufio-internal-bb-done
此跟踪点跟踪通过反弹缓冲区的所有 IO,并在通过反弹缓冲区完成 IO 时调用。此跟踪点可用于跟踪通过反弹缓冲区的所有 IO,并接受以下参数
参数 1:IO 类型 读取 - 0,写入 - 1
参数 2:应用程序 GPU(GPU ID)
参数 3:GPU 反弹缓冲区(GPU ID)
参数 4:文件描述符
参数 5:文件偏移量
参数 6:读取/写入大小
参数 7:GPU 缓冲区偏移量
参数 8:IO 是否未对齐(1 - True,0 - False)
参数 9:缓冲区是否已注册(1 - True,0 - False)
cufio-internal-io-done
此跟踪点跟踪通过 GDS 内核驱动程序的所有 IO。当 IO 完成时调用此跟踪点,并接受以下参数
参数 1:IO 类型 读取 - 0,写入 - 1
参数 2:执行 IO 的 GPU ID
参数 3:文件描述符
参数 4:文件偏移量
参数 5:传输的总字节数
cufio-internal-map
此跟踪点跟踪使用 cuFileBufRegister
的 GPU 缓冲区注册,并接受以下参数
参数 1:GPU ID
参数 2:执行注册的 GPU 缓冲区大小
参数 3:用于此缓冲区的 max_direct_io_size。
阴影内存大小在 /etc/cufile.json 文件中设置。
参数 4:布尔值,指示缓冲区是否已固定。
参数 5:布尔值,指示此缓冲区是否为 GPU 反弹缓冲区。
参数 6:GPU 偏移量。
可以通过运行以下命令找到这些跟踪点中每个参数的数据类型
# ./tplist -l /usr/local/cuda-x.y/lib/libcufile.so -vvv | grep cufio_px_read -A 7
cufio:cufio_px_read [sema 0x0]
以下是输出
# ./tplist -l /usr/local/cuda-x.y/lib/libcufile.so -vvv | grep cufio_px_read -A 7
cufio:cufio_px_read [sema 0x0]
location #1 /usr/local/cuda-x.y/lib/libcufile.so 0x16437c
argument #1 4 signed bytes @ dx
argument #2 8 signed bytes @ cx
argument #3 8 unsigned bytes @ si
argument #4 8 signed bytes @ di
argument #5 8 signed bytes @ r8
argument #6 4 signed bytes @ ax
18.2. 示例:跟踪发出 cuFileRead/ cuFileWrite 的进程的 IO 活动#
此示例提供了有关如何跟踪发出 cuFileRead
或 cuFileWrite
API 的进程的 IO 活动的信息。
运行以下命令。
# ./funccount u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_* -i 1 -T -p 59467 Tracing 7 functions for "u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_*"... Hit Ctrl-C to end.
查看输出,例如
cufio_gds_write 1891 16:21:13 FUNC COUNT cufio_gds_write 1852 16:21:14 FUNC COUNT cufio_gds_write 1865 ^C 16:21:14 FUNC COUNT cufio_gds_write 1138 Detaching...
18.3. 示例:显示通过 GDS 的所有 IO 的 IO 模式#
此示例提供了有关如何显示和理解通过 GDS 的所有 IO 的 IO 模式的信息。
运行以下命令
# ./argdist -C 'u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():size_t:arg3# Size Distribution'
查看输出,例如
[16:38:22] IO Size Distribution COUNT EVENT 4654 arg3 = 1048576 7480 arg3 = 131072 9029 arg3 = 65536 13561 arg3 = 8192 14200 arg3 = 4096 [16:38:23] IO Size Distribution COUNT EVENT 4682 arg3 = 1048576 7459 arg3 = 131072 9049 arg3 = 65536 13556 arg3 = 8192 14085 arg3 = 4096 [16:38:24] IO Size Distribution COUNT EVENT 4678 arg3 = 1048576 7416 arg3 = 131072 9018 arg3 = 65536 13536 arg3 = 8192 14082 arg3 = 4096
1M、128K、64K、8K 和 4K IO 都在通过 GDS 完成读取。
18.4. 了解进程的 IO 模式#
您可以查看输出以了解进程的 IO 模式。
运行以下命令。
# ./argdist -C 'u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():size_t:arg3#IO Size Distribution' -p 59702
查看输出。
[16:40:46] IO Size Distribution COUNT EVENT 20774 arg3 = 4096 [16:40:47] IO Size Distribution COUNT EVENT 20727 arg3 = 4096 [16:40:48] IO Size Distribution COUNT EVENT 20713 arg3 = 4096
进程 59702 发出 4K IO。
18.5. 不同 GPU 上具有文件描述符的进程的 IO 模式#
运行以下命令。
# ./argdist -C 'u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():int,int,size:arg1, arg6,arg3#IO Size Distribution arg1=fd, arg6=GPU# arg3=IOSize' -p `pgrep -n gdsio`
查看输出,例如
[17:00:03] u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():int,int,size_t:arg1,arg6,arg3#IO Size Distribution arg1=fd, arg6=GPU# arg3=IOSize COUNT EVENT 5482 arg1 = 87, arg6 = 2, arg3 = 131072 7361 arg1 = 88, arg6 = 1, arg3 = 65536 9797 arg1 = 89, arg6 = 0, arg3 = 8192 11145 arg1 = 74, arg6 = 3, arg3 = 4096 [17:00:04] u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():int,int,size_t:arg1,arg6,arg3#IO Size Distribution arg1=fd, arg6=GPU# arg3=IOSize COUNT EVENT 5471 arg1 = 87, arg6 = 2, arg3 = 131072 7409 arg1 = 88, arg6 = 1, arg3 = 65536 9862 arg1 = 89, arg6 = 0, arg3 = 8192 11079 arg1 = 74, arg6 = 3, arg3 = 4096 [17:00:05] u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():int,int,size_t:arg1,arg6,arg3#IO Size Distribution arg1=fd, arg6=GPU# arg3=IOSize COUNT EVENT 5490 arg1 = 87, arg6 = 2, arg3 = 131072 7402 arg1 = 88, arg6 = 1, arg3 = 65536 9827 arg1 = 89, arg6 = 0, arg3 = 8192 11131 arg1 = 74, arg6 = 3, arg3 = 4096
gdsio
向 GPU 2、1、0 和 3 的 4 个文件发出 READS
,fd=87、88、89、74,IO-SIZE
分别为 128K、64K、8K 和 4K。
18.6. 确定 GPU 中进程的 IOPS 和带宽#
您可以确定 GPU 中每个进程的 IOPS 和带宽。
运行以下命令。
#./argdist -C 'u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():int,int,size_t:arg1, arg6,arg3:arg6==0||arg6==3#IO Size Distribution arg1=fd, arg6=GPU# arg3=IOSize' -p `pgrep -n gdsio`
查看输出。
[17:49:33] u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():int,int,size_t:arg1,arg6,arg3:arg6==0||arg6==3#IO Size Distribution arg1=fd, arg6=GPU# arg3=IOSize COUNT EVENT 9826 arg1 = 89, arg6 = 0, arg3 = 8192 11168 arg1 = 86, arg6 = 3, arg3 = 4096 [17:49:34] u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():int,int,size_t:arg1,arg6,arg3:arg6==0||arg6==3#IO Size Distribution arg1=fd, arg6=GPU# arg3=IOSize COUNT EVENT 9815 arg1 = 89, arg6 = 0, arg3 = 8192 11141 arg1 = 86, arg6 = 3, arg3 = 4096 [17:49:35] u:/usr/local/cuda-x.y/lib/libcufile.so:cufio_gds_read():int,int,size_t:arg1,arg6,arg3:arg6==0||arg6==3#IO Size Distribution arg1=fd, arg6=GPU# arg3=IOSize COUNT EVENT 9914 arg1 = 89, arg6 = 0, arg3 = 8192 11194 arg1 = 86, arg6 = 3, arg3 = 4096
gdsio 正在所有 4 个 GPU 上执行 IO,并且输出已针对 GPU 0 和 GPU 3 进行过滤。
每个 GPU 的带宽为 GPU 0 - 9826 IOPS,块大小为 8K,带宽 = ~80MB/s 。
18.7. 显示发出 cuFileRead 的进程的读取频率#
您可以显示有关发出 cuFileRead
API 的进程的读取频率的信息。
运行以下命令。
#./argdist -C 'r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID'
查看输出,例如
[17:58:01] r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID COUNT EVENT 31191 $PID = 60492 31281 $PID = 60593 [17:58:02] r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID COUNT EVENT 11741 $PID = 60669 30447 $PID = 60593 30670 $PID = 60492 [17:58:03] r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID COUNT EVENT 29887 $PID = 60593 29974 $PID = 60669 30017 $PID = 60492 [17:58:04] r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID COUNT EVENT 29972 $PID = 60593 30062 $PID = 60492 30068 $PID = 60669
18.8. 显示 cuFileRead 花费超过 0.1 毫秒时的读取频率#
您可以显示 cuFileRead
API 花费超过 0.1 毫秒时的读取频率。
运行以下命令。
#./argdist -C 'r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID:$latency > 100000'
查看输出,例如
[18:07:35] r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID:$latency > 100000 COUNT EVENT 17755 $PID = 60772 [18:07:36] r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID:$latency > 100000 COUNT EVENT 17884 $PID = 60772 [18:07:37] r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID:$latency > 100000 COUNT EVENT 17748 $PID = 60772 [18:07:38] r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID:$latency > 100000 COUNT EVENT 17898 $PID = 60772 [18:07:39] r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead():u32:$PID:$latency > 100000 COUNT EVENT 17811 $PID = 60772
18.9. 显示每个进程的 cuFileRead 延迟#
您可以显示每个进程的 cuFileRead
API 的延迟。
运行以下命令。
#./funclatency /usr/local/cuda-x.y/lib/libcufile.so:cuFileRead -i 1 -T -u
查看输出,例如
Tracing 1 functions for "/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead"... Hit Ctrl-C to end.
以下是两个进程,PID 为 60999 和 PID 为 60894,它们正在发出 cuFileRead
18:12:11 Function = cuFileRead [60999] usecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 0 | | 64 -> 127 : 17973 |****************************************| 128 -> 255 : 13383 |***************************** | 256 -> 511 : 27 | | Function = cuFileRead [60894] usecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 0 | | 64 -> 127 : 17990 |****************************************| 128 -> 255 : 13329 |***************************** | 256 -> 511 : 19 | | 18:12:12 Function = cuFileRead [60999] usecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 0 | | 64 -> 127 : 18209 |****************************************| 128 -> 255 : 13047 |**************************** | 256 -> 511 : 58 | | Function = cuFileRead [60894] usecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 0 | | 64 -> 127 : 18199 |****************************************| 128 -> 255 : 13015 |**************************** | 256 -> 511 : 46 | | 512 -> 1023 : 1 |
18.10. 示例:跟踪发出 cuFileBufRegister 的进程#
此示例显示您可以跟踪发出 cuFileBufRegister
API 的进程。
运行以下命令
# ./trace 'u:/usr/local/cuda-x.y/lib/libcufile.so:cufio-internal-map "GPU %d Size %d Bounce-Buffer %d",arg1,arg2,arg5'
查看输出,例如
PID TID COMM FUNC - 62624 62624 gdsio_verify cufio-internal-map GPU 0 Size 1048576 Bounce-Buffer 1 62659 62726 fio cufio-internal-map GPU 0 Size 8192 Bounce-Buffer 0 62659 62728 fio cufio-internal-map GPU 2 Size 131072 Bounce-Buffer 0 62659 62727 fio cufio-internal-map GPU 1 Size 65536 Bounce-Buffer 0 62659 62725 fio cufio-internal-map GPU 3 Size 4096 Bounce-Buffer 0
gdsio_verify
发出了 IO,但它未使用 cuFileBufRegister
注册 GPU 内存。因此,GDS 库在 GPU 0 上固定了 1M 的反弹缓冲区。另一方面,FIO 在 GPU 2 上发出了 128K 的 cuFileBufRegister
。
18.11. 示例:跟踪进程在调用 cuFileBufRegister 时是否恒定#
您可以跟踪进程在调用 cuFileBufRegister
API 时是否恒定。
运行以下命令
# ./trace 'u:/usr/local/cuda-x.y/lib/libcufile.so:cufio-internal-map (arg5 == 0) "GPU %d Size %d",arg1,arg2'
查看输出,例如
PID TID COMM FUNC - 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576 444 472 cufile_sample_0 cufio-internal-map GPU 0 Size 1048576
如本示例所示,进程中有一个线程在 GPU 0 上持续发出 1M 的 cuFileBufRegister
。这可能意味着 API 在循环中被调用,并且可能会影响性能。
注意
cuFileBufRegister
涉及固定 GPU 内存,这是一项昂贵的操作。
18.12. 示例:监视正在通过反弹缓冲区的 IO#
此示例显示了如何监视 IO 是否正在通过反弹缓冲区。
运行以下命令
# ./trace 'u:/usr/local/cuda-x.y/lib/libcufile.so:cufio-internal-bb-done "Application GPU %d Bounce-Buffer GPU %d Transfer Size %d Unaligned %d Registered %d", arg2,arg3,arg8,arg9,arg10'
查看输出,例如
PID TID COMM FUNC -
1013 1041 gdsio App-GPU 0 Bounce-Buffer GPU 0 Transfer Size 1048576 Unaligned 1 Registered 0
1013 1042 gdsio App-GPU 3 Bounce-Buffer GPU 3 Transfer Size 1048576 Unaligned 1 Registered 0
1013 1041 gdsio App-GPU 0 Bounce-Buffer GPU 0 Transfer Size 1048576 Unaligned 1 Registered 0
1013 1042 gdsio App-GPU 3 Bounce-Buffer GPU 3 Transfer Size 1048576 Unaligned 1 Registered 0
The ``gdsio`` app has 2 threads and both are doing unaligned IO on GPU 0 and GPU 3. Since the IO is unaligned, bounce buffers are also from the same application GPU.
18.13. 示例:跟踪 cuFileRead 和 cuFileWrite 失败、打印、错误代码和失败时间#
此示例显示了如何跟踪 cuFileRead
和 cuFileWrite
失败、打印、错误代码和失败时间。
运行以下命令
# ./trace 'r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileRead ((int)retval < 0) "cuFileRead failed: %d", retval' 'r:/usr/local/cuda-x.y/lib/libcufile.so:cuFileWrite ((int)retval < 0) "cuFileWrite failed: %d", retval' -T
查看输出,例如
TIME PID TID COMM FUNC - 23:22:16 4201 4229 gdsio cuFileRead cuFileRead failed: -5 23:22:42 4237 4265 gdsio cuFileWrite cuFileWrite failed: -5
在本示例中,观察到两个失败,返回代码为 EIO (-5),并带有时间戳。
18.14. 示例:每个 GDS 进程的用户空间统计信息#
cuFile
库以每个进程的 API 级别计数器的形式导出用户级别统计信息。除了常规 GDS IO 路径之外,还有用户空间文件系统和 IO 兼容模式的路径,这些模式使用 POSIX 读取/写入,这些读取/写入不通过 nvidia-fs 驱动程序。用户级别统计信息在这些场景中更有用。
计数器有一个详细级别,用户可以使用 JSON 配置文件指定该级别以启用和设置级别。以下描述了各种详细级别。
级别 |
描述 |
---|---|
级别 0 |
cuFile 统计信息将被禁用。 |
级别 1 |
cuFile 统计信息将仅报告全局计数器,例如总体吞吐量、平均延迟和错误计数。 |
级别 2 |
除了全局计数器之外,还将报告 IO 大小直方图,以提供有关访问模式的信息。 |
级别 3 |
在此级别,将报告每个 GPU 的计数器以及 cuFile 内部池缓冲区的实时使用情况。 |
以下是使用 /etc/cufile.json
文件启用 GDS 统计信息的 JSON 配置键
"profile": {
// cufile stats level(0-3)
"cufile_stats": 3
},
18.15. 示例:查看进程的 GDS 用户级别统计信息#
此示例显示了如何使用 gds_stats
工具显示进程的用户级别统计信息。
先决条件:在运行该工具之前,请确保 IO 应用程序处于活动状态,并且 gds_stats
具有与应用程序相同的用户权限。
gds_stats
工具可用于读取由 libcufile.so
导出的统计信息。
统计信息的输出显示在标准输出中。如果用户权限不同,则可能没有足够的权限来查看统计信息。gds_stats
的未来版本将把 nvidia-fs
内核级别统计信息集成到此工具中。
要使用该工具,请运行以下命令
$ /usr/local/cuda-x.y/tools/gds_stats -p <pidof application> -l <stats_level(1-3)>
在指定统计信息级别时,请确保在 /etc/cufile.json
文件中也启用了相应的级别 (profile.cufile_stats
)。
GDS 用户级别统计信息在库关闭或运行 cuFileDriverClose
API 时记录到 cufile.log
文件一次。要查看日志文件中的统计信息,请将日志级别设置为 INFO。
18.16. 示例:显示每个 GDS 进程的示例用户级别统计信息#
此示例显示了如何显示每个 GDS 进程的示例用户级别统计信息。
运行以下命令
$ ./gds_stats -p 23198 -l 3
查看输出,例如
cuFile STATS VERSION : 8 GLOBAL STATS: Read: ok = 215814 err = 0 Write: ok = 0 err = 0 HandleRegister: ok = 1 err = 0 HandleDeregister: ok = 0 err = 0 BufRegister: ok = 128 err = 0 BufDeregister: ok = 0 err = 0 BatchSubmit: ok = 0 err = 0 BatchComplete: ok = 0 err = 0 BatchSetup: ok = 0 err = 0 BatchCancel: ok = 0 err = 0 BatchDestroy: ok = 0 err = 0 BatchEnqueued: ok = 0 err = 0 PosixBatchEnqueued: ok = 0 err = 0 BatchProcessed: ok = 0 err = 0 PosixBatchProcessed: ok = 0 err = 0 Total Read Size (MiB): 107907 Read BandWidth (GiB/s): 2.50343 Avg Read Latency (us): 49731 Total Write Size (MiB): 0 Write BandWidth (GiB/s): 0 Avg Write Latency (us): 0 Total Batch Read Size (MiB): 0 Total Batch Write Size (MiB): 0 Batch Read BandWidth (GiB/s): 0 Batch Write BandWidth (GiB/s): 0 Avg Batch Submit Latency (us): 0 Avg Batch Completion Latency (us): 0 READ-WRITE SIZE HISTOGRAM : 0-4(KiB): 0 0 4-8(KiB): 0 0 8-16(KiB): 0 0 16-32(KiB): 0 0 32-64(KiB): 0 0 64-128(KiB): 0 0 128-256(KiB): 0 0 256-512(KiB): 0 0 512-1024(KiB): 0 0 1024-2048(KiB): 107907 0 2048-4096(KiB): 0 0 4096-8192(KiB): 0 0 8192-16384(KiB): 0 0 16384-32768(KiB): 0 0 32768-65536(KiB): 0 0 65536-...(KiB): 0 0 PER_GPU STATS: GPU 0(UUID: ce4dfa044611339ca1e22bf10a772fe) Read: bw=2.50531 util(%)=12791 n=107907 posix=0 unalign=0 dr=0 r_sparse=0 r_inline=0 err=0 MiB=107907 Write: bw=0 util(%)=0 n=0 posix=0 unalign=0 dr=0 err=0 MiB=0 BufRegister: n=128 err=0 free=0 MiB=128 PER_GPU POOL BUFFER STATS: PER_GPU POSIX POOL BUFFER STATS: PER_GPU RDMA STATS: GPU 0000:43:00.0(UUID: ce4dfa044611339ca1e22bf10a772fe) : RDMA MRSTATS: peer name nr_mrs mr_size(MiB) mlx5_0 1 2 mlx5_1 1 2 PER GPU THREAD POOL STATS: gpu node: 0 enqueues:0 completes:0 pending suspends:0 pending yields:0 active:0 suspends:0
19. GPUDirect Storage 中的用户空间计数器#
下表提供了有关 GDS 中用户空间计数器的信息。
计数器名称 |
描述 |
---|---|
文件总数 |
使用
|
读取错误总数 |
|
读取大小总计 |
使用 cuFileRead 读取的总字节数(MB)。 |
读取带宽 |
一秒时间段内的平均总体读取吞吐量(GiB/s)。 |
平均读取延迟 |
一秒时间段内的总体平均读取延迟(微秒)。 |
写入错误总数 |
cuFileWrite 错误的总数。 |
写入大小总计 |
使用 cuFileWrite 写入的总字节数(MB)。 |
写入带宽 |
一秒时间段内的平均总体写入吞吐量(GiB/s)。 |
平均写入延迟 |
一秒时间段内的总体平均读取延迟(微秒)。 |
批量读取大小总计 |
使用 cuFile 批量模式读取的总字节数(MB)。 |
批量写入大小总计 |
使用 cuFile 批量模式写入的总字节数(MB)。 |
批量读取带宽 |
cuFile 批量模式在一秒时间段内的平均总体读取吞吐量(GiB/s)。 |
批量写入带宽 |
cuFile 批量模式在一秒时间段内的平均总体写入吞吐量(GiB/s)。 |
平均批量提交延迟 |
使用 |
平均批量完成延迟 |
一秒时间段内的总体平均 cuFile 批量 IO 完成延迟(微秒)。这包括提交和完成时间。 |
计数器名称 |
描述 |
---|---|
Read |
基于 IO 大小的 cuFileRead 请求数量分布。Bin Size 使用 4K 对数刻度。 |
Write |
基于 IO 大小的 cuFileWrite 请求数量分布。Bin Size 使用 4K 对数刻度。 |
计数器名称 |
描述 |
---|---|
Read.bw/Write.bw |
每个 GPU 的平均 GPU 读取/写入带宽(GiB/s)。 |
Read.util/Write.util |
每个 GPU 的平均读取/写入利用率(%)。如果 A 是资源在时间间隔 T 内处于繁忙状态的总时长,则利用率定义为 A/T。此处报告的利用率超过一秒时间段。 |
Read.n/Write.n |
每个 GPU 的 |
Read.posix/Write.posix |
每个 GPU 使用 POSIX 读取/写入 API 的 |
Read.dr/Write.dr |
已使用动态路由为 GPU 发出的 如果路由策略使用 SYS_MEM,则除了 |
Read.unalign/Write.unalign |
每个 GPU 的 |
Read.error/Write.error |
每个 GPU 的 |
Read.mb/Write.mb |
每个 GPU 使用 |
BufRegister.n |
每个 GPU 的 |
BufRegister.err |
使用 |
BufRegister.free |
每个 GPU 的 |
BufRegister.mb |
每个 GPU 当前注册的总字节数(MB)。 |
计数器名称 |
描述 |
---|---|
pool_size_mb |
为每个 GPU 反弹缓冲区分配的缓冲区总大小(MB)。 |
used_mb |
当前每个 GPU 用于基于反弹缓冲区的 IO 的缓冲区总大小。 |
usage |
当前使用的反弹缓冲区的比例。 |
计数器名称 |
描述 |
---|---|
HandleRegister HandleDeregister |
ok:已发出并成功完成的 cuFileHandleRegister 调用数。 err:已发出并完成但出现错误的 cuFileHandleRegister 调用数。ok:已发出并成功完成的 cuFileHandleDeregister 调用数。 err:已发出并完成但出现错误的 cuFileHandleDeregister 调用数。 |
BufRegister |
ok:已发出并成功完成的 cuFileBufRegister 调用数。 err:已发出并完成但出现错误的 cuFileBufRegister 调用数。 |
BufDeregister |
ok:已发出并成功完成的 cuFileBufDeregister 调用数。 err:已发出并完成但出现错误的 cuFileBufDeregister 调用数。 |
BatchSubmit |
ok:已发出并成功完成的 cuFileBatchIOSubmit 调用数。 err:已发出并完成但出现错误的 cuFileBatchIOSubmit 调用数。 |
BatchComplete |
ok:已发出并成功完成的 cuFileBatchIOGetStatus 调用数。 err:已发出并完成但出现错误的 cuFileBatchIOGetStatus 调用数。 |
BatchSetup |
ok:已发出并成功完成的 cuFileBatchIOSetUp 调用数。 err:已发出并完成但出现错误的 cuFileBatchIOSetUp 调用数。 |
BatchCancel |
ok:已发出并成功完成的 cuFileBatchIOCancel 调用数。 err:已发出并完成但出现错误的 cuFileBatchIOCancel 调用数。 |
BatchDestroy |
ok:已发出并成功完成的 cuFileBatchIODestroy 调用数。 err:已发出并完成但出现错误的 cuFileBatchIODestroy 调用数。 |
BatchEnqueued |
对于具有未对齐大小/偏移量的批量条目,该条目可能具有对齐(GDS 路径)和未对齐(Posix 路径)部分。此条目指示在这种情况下 GDS 路径 IO 的数量。这些 IO 不会直接提交,而是排队到线程池中。 ok:成功排队到线程池的 GDS 路径 IO 数。 err:无法排队到线程池的 GDS 路径 IO 数。 |
PosixBatchEnqueued |
与 BatchEnqueued 类似,但用于排队的 Posix IO 数。 ok:成功排队到线程池的 Posix 路径 IO 数。 err:无法排队到线程池的 Posix 路径 IO 数。 |
BatchProcessed |
此计数器指示使用 ok:成功处理的 IO 数。 err:完成但出现错误的 IO 数。 |
PosixBatchProcessed |
此计数器指示使用 ok:成功处理的 IO 数。 err:完成但出现错误的 IO 数。 |
19.1. 每个 GPU 中 IO 使用率的分布#
cuFile 库具有每个应用程序 GPU 的 IO 利用率指标。此指标指示 cuFile 资源在 IO 中繁忙的时间量(以百分比表示)。
要运行单线程 gdsio
测试,请运行以下命令
$./gdsio -f /mnt/md1/test -d 0 -n 0 -w 1 -s 10G -i 4K -x 0 -I 1
以下是示例输出
PER_GPU STATS
GPU 0 Read: bw=0 util(%)=0 n=0 posix=0 unalign=0 err=0 mb=0 Write: bw=0.154598
util(%)=89 n=510588 posix=0 unalign=0 err=0 mb=1994 BufRegister: n=1 err=0 free=0 mb=0
util
指标表示应用程序在 89% 的时间内在 GPU 0 上完成 IO。
要使用两个线程运行 gdsio
测试,请运行以下命令
$./gdsio -f /mnt/md1/test -d 0 -n 0 -w 2 -s 10G -i 4K -x 0 -I 1
以下是示例输出
PER_GPU STATS
GPU 0 Read: bw=0 util(%)=0 n=0 posix=0 unalign=0 err=0 mb=0 Write: bw=0.164967 util(%)=186 n=140854 posix=0 unalign=0 err=0 mb=550 BufRegister: n=2 err=0 free=0 mb=0
现在利用率为 ~186%,这表明每个 GPU 用于 IO 的并行度。
19.2. 动态路由的用户空间统计信息#
gds_stats
的 PER_GPU
部分有一个 dr
计数器,该计数器指示已使用动态路由为 GPU 发出了多少 cuFileRead
/ cuFileWrite
。
$ ./gds_stats -p <pidof application> -l 3
GPU 0 Read: bw=0 util(%)=0 n=0 posix=0 unalign=0 dr=0 r_sparse=0 r_inline=0
err=0 MiB=0 Write: bw=3.37598 util(%)=532 n=6629 posix=0 unalign=0 dr=6629 err=0
MiB=6629 BufRegister: n=4 err=0 free=0 MiB=4
GPU 1 Read: bw=0 util(%)=0 n=0 posix=0 unalign=0 dr=0 r_sparse=0 r_inline=0
err=0 MiB=0 Write: bw=3.29297 util(%)=523 n=6637 posix=0 unalign=0 dr=6637 err=0
MiB=6637 BufRegister: n=4 err=0 free=0 MiB=4
20. GPUDirect Storage 中的用户空间 RDMA 计数器#
该库提供计数器来监视每个 GPU 级别的 RDMA 流量,并且要求 cuFile 以值为 3 的详细级别启动。
表 cuFile RDMA IO 计数器 (PER_GPU RDMA STATS) 提供了以下信息
每列存储 GPU 和 NIC 之间发送/接收的总字节数。
每行显示 RDMA 负载相对于所有 NIC 的 GPU 分布。
每行反映了 GPU 与 NIC 的亲和性顺序。
理想情况下,所有流量都应通过具有最佳亲和性或最靠近 GPU 的 NIC 路由,如 示例 1 中所示。
在表中每个 NIC 条目的注释中,主编号是以 GPU 和 NIC 之间的跳数表示的 pci 距离,次编号表示 NIC 的当前带宽(link_width 乘以 pci_generation)。GPU 用于 RDMA 的 NIC 从 rdma_dev_addr_list cufile.json
属性加载
"rdma_dev_addr_list": [
"172.172.1.240",
"172.172.1.241",
"172.172.1.242",
"172.172.1.243",
"172.172.1.244",
"172.172.1.245",
"172.172.1.246",
"172.172.1.247" ],
每个 IP 地址对应于一个 IB 设备,该设备在 RDMA 计数器表中显示为列条目。
20.1. cuFile RDMA IO 计数器 (PER_GPU RDMA STATS)#
下表列出了 cuFile RDMA IO 计数器。
条目 |
描述 |
---|---|
GPU |
总线设备功能 |
NIC |
+)Bus device function
+)Device Attributes
++)pci-distance between GPU and NIC
++)device bandwidth indicator
+)Send/Receive bytes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20.2. cuFile RDMA 内存注册计数器 (RDMA MRSTATS)#
以下表格列出了 cuFile RDMA 内存注册计数器。
条目 |
描述 |
---|---|
对等名称 |
网卡的系统名称。 |
nr_mrs |
每个网卡的活动内存注册计数。 |
mr_size(mb) |
总大小 |
对等名称 |
nr_ms |
mr_size (mb) |
---|---|---|
mlx5_3 |
128 |
128 |
mlx5_5 |
128 |
128 |
mlx5_11 |
0 |
0 |
mlx5_1 |
0 |
0 |
mlx5_15 |
128 |
128 |
mlx5_19 |
128 |
128 |
mlx5_17 |
128 |
128 |
mlx5_9 |
128 |
128 |
mlx5_13 |
128 |
128 |
mlx5_7 |
128 |
128 |
21. 问题诊断速查表#
以下表格可以帮助用户诊断 GDS 问题。
请务必检查以下变量,并观察性能是否达到预期。
影响性能的变量 |
描述 |
启用/禁用功能的步骤(“操作方法”) |
---|---|---|
兼容模式 |
在 |
在 cufile.json 中设置 allow_compat_mode: false。 或 将 CUFILE_FORCE_COMPAT_MODE 环境变量设置为 false。 |
日志级别 |
在 cufile.json 中将日志级别设置为 ERROR |
以下 cufile.json 中的设置会将日志级别设置为 ERROR。 "logging": {
// log
目录,如果未启用,将在当前工作目录下创建日志文件 //"dir": "/home/<xxxx>",
// NOTICE|ERROR|WARN|INFO|DEBUG|TRACE (in decreasing order of severity)
"level": "ERROR"
},
|
Nvidia-fs 统计信息 |
确保 nvidia-fs 读取/写入统计信息已禁用。这些统计信息可能会对小 IO 大小产生性能影响。默认情况下,这些信息是禁用的。 |
要检查统计信息的当前状态,请使用以下命令。
0 - 禁用 1 - 启用 要禁用它们,
|
GDR 统计信息/RDMA 统计信息(CQE 错误) |
||
放宽排序 |
对于分布式文件系统,请确保网卡已启用放宽排序 在 CX-6 上设置“MAX_ACC_OUT_READ=44”。 对于 CX-7,设置“MAX_ACC_OUT_READ=128”。 |
|
持久模式 |
启用持久模式 |
|
时钟速度 |
将时钟速度设置为最大值 |
|
BAR 大小 |
确保 BAR 大小已启用为最大可能值 |
|
Numa 亲缘性 |
在 NIC-GPU 位于同一交换机中的进程中设置 numa 亲缘性 |
|
MRRS |
为 NIC/NVMe 设置 PCIe 最大读取请求大小。指定最大读取请求大小使请求者 (NIC/NVME) 能够从 GPU 内存读取数据,大小可达指定大小,以提高从 GPU 到存储的写入性能。 |
使用以下命令检查设置
读取当前值
设置为 4K
设置为 512 字节
可接受的值为:0 - 128B,1 - 256B,2 - 512B,3 - 1024B,4 - 2048B 和 5 - 4096B。 警告:指定此范围之外的选择器索引可能会导致系统崩溃。 |
对于 ROCE 设置,请考虑以下附加项
CPU 调速器 |
性能 |
|
RX/TX 环 |
将它们设置为最大值 |
|
RX/TX 通道 |
设置为允许的最大值 |
|
LRO |
开启大接收卸载 |
|
IRQ 亲缘性 |
将 IRQ 亲缘性设置为仿射 NUMA 节点 |
|
IRQ 平衡 |
关闭 IRQ 平衡器 |
|
TX 队列长度 |
增加 TX 队列长度 |
|
如果以上步骤没有帮助,请收集以下信息并与我们分享。
测量 GDR 性能 |
对于 RDMA 连接和性能问题,请运行 ib_read 和 ib_write 测试,并启用 cuda 和 GPU |
请按照 linux-rdma/perftest 的说明进行操作 在测试中使用选项
|
使用 Nsight Systems |
对于 RDMA 连接和性能问题,请运行 ib_read 和 ib_write 测试,并启用 cuda 和 GPU |
|
描述环境 |
虚拟化(Docker 或实际 VM)或 BM |
|
收集 gds 日志 |
收集 cufile.log
|
|
调试
Dmesg 错误? |
检查内核错误 |
|
MiG 模式已启用? |
检查是否启用 MIG |
|
FM 已启用或未启用 |
对于基于 NVSwitch 的系统。检查 fabric manager 是否正在运行且处于活动状态,并且没有任何错误 |
|