# 各个厂商的显卡
---
1. **Nvidia GPU**
2. **Ascend NPU**
3. **Habana Goya**
Habana Goya 是由 Habana Labs(现在是英特尔的一部分)开发的人工智能推理处理器(AI inference processor)。Goya 是一种专为高效运行神经网络推理工作负载而设计的 AI 芯片,主要用于数据中心和云计算环境中的推理任务。
英特尔在 2019 年收购了 Habana Labs,并将其作为推动其数据中心 AI 业务的重要组成部分。自那时起,Habana 的 Goya 和 Gaudi 产品继续发展,并与英特尔的整体 AI 硬件生态系统(如至强处理器和 FPGA)紧密集成。
4. **AWS Neuron**
AWS Neuron 是 Amazon Web Services (AWS) 推出的专用软件开发工具链,旨在优化和加速在 AWS 基础设施上运行的机器学习(ML)模型,特别是在 AWS Inferentia 和 Trainium 芯片上。
5. **Ada**
Ada 是 NVIDIA 的一个显卡架构系列,全称为 Ada Lovelace,以计算机科学先驱艾达·洛夫莱斯(Ada Lovelace)命名。Ada Lovelace 是 NVIDIA 于 2022 年推出的架构,用于下一代的 GeForce RTX 40 系列显卡。这些显卡采用了更先进的工艺和技术,在图形性能和能效上相比于前代 Ampere 架构有显著提升。
# 辅助定位工具
---
`nvidia-smi`: 它是一个随 NVIDIA 驱动一起安装的命令行程序。它会报告系统中每个 GPU 的基本监控数据和硬件参数、配置数据。 nvidia-smi 可以列出 ECC 错误计数 (Xid 48) 并指示电源线是否已拔出 (Xid 54) 等。同时运行“nvidia-smi –q”以获得全面输出。
`DCGM`: nvidia data center gpu manager是一套用于在集群环境中管理和监控 NVIDIA 数据中心 GPU 的工具。它包括主动健康监控、全面诊断、系统警报和治理策略(包括电源和时钟管理)。 DCGM 诊断是一款运行状况检查工具,可以检查基本的 GPU 运行状况,包括是否存在 ECC 错误、PCIe 问题、带宽问题以及运行 CUDA 程序的常见问题。
`nvidia-bug-report.sh`: 它是与 NVIDIA 驱动一起安装的脚本。它从系统收集调试日志和命令输出,包括内核日志和NVIDIA驱动程序本身收集的日志。该命令应以 root 身份运行。nvidia-bug-report.sh 通常会快速运行,但在极少数情况下可能会运行缓慢。最多需要一小时才能完成。如果命令仍然挂起,请使用附加参数运行命令,如下所示:nvidia-bug-report.sh --safe-mode --extra-system-data
# GPU 通信方式
---
## 单机多卡
**PCIe**
单机多卡的 GPU 通常通过 PCIe 总线与主板相连,数据传输经过主机内存(CPU 内存),再传送到另一块 GPU。
此类通信的主要瓶颈在于主机内存的带宽和延迟。
**NVLink**
多块支持 NVLink 的 GPU 可以通过 NVLink 直接连接,无需经过主机内存。这显著提高了带宽和降低了延迟。
NVLink 可以组建 GPU 拓扑结构,比如全互联网状拓扑,使多卡间通信更加高效。
**NVSwitch**
NVSwitch 是一种用于多 GPU 系统的大规模互连架构,扩展了 NVLink 的能力,类似于网络交换机。
NVSwitch 允许在单个服务器中连接多达 16 块 GPU,并支持每对 GPU 之间的全速通信。
实现了所有 GPU 之间的等效通信带宽,适合大规模的深度学习模型训练。
`nvidia-smi topo -m`
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-061c4e4afc0a449699ba460be1114f97.png)
- X: 自身
- SYS:通过 PCIe 的连接以及 NUMA 节点之间的 SMP 互连(例如,QPI/UPI)
- NODE:通过 PCIe 的连接以及 NUMA 节点内 PCIe 主机桥之间的互连
- PHB:通过 PCIe 和 PCIe 主机桥(通常是 CPU)的连接
- PXB:通过多个 PCIe 桥互连(不跨 PCIe 主机桥)
- PIX:通过最多一个 PCIe 桥互连
- NV# :通过数量为n组的 NVLinks 互连
![img_v3_02ap_933858bab0b9495cb4a566609b9a2a0g.jpg](https://blog.zs-fighting.cn/upload/2024/05/img_v3_02ap_933858ba-b0b9-495c-b4a5-66609b9a2a0g-b4434da79cca49068ddef7eb75ca137f.jpg)
## 多机多卡
**PCIe (通过网络)**
- 简介: 在多机环境下,GPU 之间通常通过 CPU、网络接口卡(NIC)和 PCIe 进行间接通信。
- 通信方式: 数据需先从 GPU 通过 PCIe 传输到主机内存,再通过网络接口传输到另一台机器的主机内存,然后通过 PCIe 传到目标 GPU。
此类通信效率低,主要瓶颈在于网络带宽和延迟。
**RDMA (Remote Direct Memory Access)**
- 简介: RDMA 是一种网络通信技术,允许直接访问远程机器内存,从而避免 CPU 干预,降低延迟和 CPU 开销。
- 带宽和延迟: 使用 RDMA,网络延迟显著降低,带宽也可以达到网络接口的理论上限(如 100 Gbps)。
- 通信方式: RDMA 允许 GPU 之间直接交换数据,不需要通过主机内存,极大地加速了跨服务器的数据传输。通常结合 InfiniBand 网络和 NVIDIA 的 NCCL(NVIDIA Collective Communications Library)进行优化的多机多卡通信。
**NVLink + NVSwitch (跨节点)**
- 简介: 在有些大规模系统中,NVLink 和 NVSwitch 也可以跨节点使用,通过网络接口进行远程连接。
- 通信方式: 在多个节点间通过高速网络连接,例如使用 InfiniBand 和 NVLink 混合架构,使得不同服务器上的 GPU 可以通过高速链路互联。
这通常用于大型 HPC(高性能计算)集群或 AI 超级计算机。
# 故障检测方式
---
## 单机多卡
### P2P
P2P 测试是指 Peer-to-Peer 通信测试,用于评估多块 GPU 之间的直接通信性能。P2P 通信允许 GPU 之间绕过 CPU,直接通过高速互联(如 NVLink 或 PCIe)传输数据,这种方式可以显著降低延迟并提高带宽。
**如何进行 P2P 测试**
在实际操作中,P2P 测试可以通过工具如 NVIDIA's NCCL (NVIDIA Collective Communications Library) 或 CUDA P2P 示例程序进行。
- 1. 使用 CUDA 示例程序
```bash
# 在 CUDA Toolkit 的安装路径下找到 samples/ 目录,进入 samples/ 目录下的 p2pBandwidthLatencyTest 文件夹。
cd /usr/local/cuda/samples/1_Utilities/p2pBandwidthLatencyTest
make
# 编译成功后,生成的可执行文件会在 p2pBandwidthLatencyTest 文件夹下。
./p2pBandwidthLatencyTest
# 该测试会输出不同 GPU 之间的 P2P 带宽和延迟。
```
- 2. 使用 NCCL (NVIDIA Collective Communications Library)
```bash
# NCCL 提供了 all_reduce_perf 示例程序,可以测试 GPU 之间的 P2P 通信性能。
nccl-tests/build/all_reduce_perf -b 8 -e 128M -f 2 -g 2
```
![image.png](https://blog.zs-fighting.cn/upload/2024/08/image-74546115f0e64724a87e110d367d3641.png)
### nccl-tests
`./build/all_reduce_perf -b 8 -e 128M -f 2 -g 4`
### GEMM
[TODO]
## 多机多卡
---
### nccl-tests
**(2机16卡)**
![image.png](https://blog.zs-fighting.cn/upload/2024/08/image-c1003b3877d8453a9b4d2bfc15e0b10c.png)
```bash
mpirun -np 16 \
--prefix /usr/local/openmpi \
--allow-run-as-root -bind-to none -map-by slot \
-H NcclTestsSourceIp:8,NcclTestsDestIp:8 \
-x NCCL_SOCKET_IFNAME=eth0 \
-x NCCL_DEBUG=INFO \
-x NCCL_DEBUG_SUBSYS=ALL \
-x NCCL_IB_DISABLE=0 \
-x NCCL_NET_GDR_LEVEL=2 \
-x NCCL_IB_QPS_PER_CONNECTION=4 \
-x NCCL_IB_TC=0 \
-x NCCL_IB_SL=0 \
-x NCCL_PROTO=Simple \
-x NCCL_ALGO=Auto \
-x NCCL_IB_HCA=mlx5_0,mlx5_2 \
-x NCCL_DEBUG_FILE=/tmp/nccl_debug_single.log \
-x NCCL_CUMEM_ENABLE=0 \
-mca pml ob1 -mca btl_tcp_if_include eth0 -mca btl ^openib \
/usr/local/nccl-tests/build/all_reduce_perf -b 8M -e 2G -n 1000 -f 2 -g 1
```
## 配置项
---
- **IOMMU**
- **ACSCtrl**
- **GPU_Manufacturer**
- **GPU_Number**
- **Driver_SDK**
- **P2P_Bandwidth**
- **Link_Width**
- **NVLink**
- **Fabric_Manager**
- **Remap_Failure**
- **SRAM_UE(ECC errors)**
- **DBE**
- **SBE**
- **ECC_Pending_Mode**
- **Power**
- **Temperature**
- **Frequency_Lock**
- **Dmesg**
# XID errors
---
- 什么是 Xid errors:
XID消息是NVIDIA驱动程序向操作系统的内核日志或事件日志打印的错误报告。XID消息用于标识GPU错误事件,提供GPU硬件、NVIDIA软件或您应用程序中的错误类型、错误位置、错误代码等信息。
## 根据XID状态排查问题
---
内核日志搜索: `dmesg -T |grep -i xid`
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-1904dfda1d9f4172a4c50fc1f86012b5.png)
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-d4199feac23a42e5b7adb03f6aed68ee.png)
# Dcgm
---
## dcgmi diag 命令支持的所有参数
**参数说明**
- -r: 选择不同的测试级别,适合不同的诊断需求。
- -p: 允许详细定制测试参数。
- --fail-early: 当检测到第一个问题时立即停止测试,节省时间。
- --statspath: 指定结果保存路径,便于后续分析。
- -j: 以 JSON 格式获取输出,更方便程序化处理。
- -f: 强制运行,即使在一些特殊情况下。
- -v: 显示详细的执行信息,帮助调试。
- -s: 静默模式输出,仅显示最终结果。
- -t: 设置超时,防止测试时间过长。
- -n: 隐藏主机名,在多主机环境中使用。
- -h: 查看帮助信息,获取可用参数和用法。
- --no-color: 禁用彩色输出,适合纯文本环境。
- --force-reboot: 强制重启设备,以确保测试环境干净。
- --retry: 指定重试次数,以应对偶发的测试失败。
- --log-path: 设置日志文件路径,记录详细测试信息。
- --gpu-index: 选择特定 GPU 进行诊断,适用于多 GPU 环境。
## 常用的命令
`dcgmi diag -r 4 --fail-early --statspath $work_dir 2>&1 | tee $log_file`
![image.png](https://blog.zs-fighting.cn/upload/2024/08/image-19e16af1a2bb4e66b043cc7998b15985.png)
repo: https://github.com/NVIDIA/dcgm-exporter
官方文档: https://docs.nvidia.com/datacenter/cloud-native/gpu-telemetry/latest/dcgm-exporter.html
监控指标说明: https://docs.nvidia.com/datacenter/dcgm/latest/dcgm-api/dcgm-api-field-ids.html
aliyun 监控指标说明: https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/introduction-to-metrics
# ECC errors
---
## ECC 的基本原理
ECC 是一种内存保护技术,它通过增加冗余信息来检测和纠正数据中的单个位错误。内存或存储设备在存储数据时会生成一个额外的 ECC 校验码,当数据被读取时,这个校验码可以用来检测是否发生了错误。如果检测到错误,并且错误在 ECC 能纠正的范围内(如单个位错误),ECC 将自动纠正错误并返回正确的数据。
## ECC 错误的分类
- 可纠正的 ECC 错误:
**Corrected ECC Error**:这类错误是 ECC 检测到并成功纠正的错误。这种错误通常不会对系统的运行产生明显影响,因为它们被及时纠正。
- 未纠正的 ECC 错误:
**Uncorrected ECC Error**:这类错误是 ECC 检测到但无法纠正的错误。这种错误通常会导致系统不稳定,可能会导致应用程序崩溃或系统挂起。如果累积到一定程度,未纠正的 ECC 错误可能表明硬件存在严重问题。
## 为什么 ECC 错误重要?
ECC 错误的重要性在于它们是硬件健康状况的重要指标,特别是在高可靠性要求的计算环境中,如数据中心、科学计算、金融交易等场景。ECC 错误的检测和管理能够帮助提前发现潜在的硬件问题,从而采取相应措施,防止系统崩溃或数据损坏。
在 GPU 机器故障检测中,未纠正的 ECC 错误(Uncorrected ECC Errors)确实是非常关键的指标,因为它们可能导致计算错误、数据损坏,甚至使 GPU 崩溃。这些错误通常是硬件故障的标志,特别是内存问题。因此,在检测 GPU 故障时,未纠正的 ECC 错误应该是主要关注的对象。
## 检测方式
**1)列出所有可用的 ECC 错误统计项**
你可以通过以下命令来查看 GPU 支持的所有 ECC 错误统计项:
```bash
nvidia-smi --help-query-gpu
```
在输出中,你会看到类似 ecc.errors.* 的条目。这些条目表示可以查询的 ECC 错误类型。
**2)查询所有 ECC 错误信息**
你可以使用 nvidia-smi 的 --query-gpu 选项来查询所有可能的 ECC 错误统计项。下面是一个例子,列出了所有常见的 ECC 错误项:
```bash
nvidia-smi --query-gpu=ecc.errors.corrected.volatile.sram,ecc.errors.corrected.volatile.l1_cache,ecc.errors.corrected.volatile.l2_cache,ecc.errors.corrected.volatile.device_memory,ecc.errors.uncorrected.volatile.sram,ecc.errors.uncorrected.volatile.l1_cache,ecc.errors.uncorrected.volatile.l2_cache,ecc.errors.uncorrected.volatile.device_memory --format=csv,noheader
```
上面的命令会返回如下信息:
- **ecc.errors.corrected.volatile.total**
统计的是自上次 GPU 重新启动以来,所有已纠正的易失性 ECC 错误的总数。易失性表示这些错误的计数会在 GPU 重新启动后被重置。
- **ecc.errors.corrected.aggregate.total**
统计的是所有已纠正的 ECC 错误的总数,包括易失性和非易失性的错误。这是一个累积的计数,不会在 GPU 重新启动后重置。
- **ecc.errors.uncorrected.aggregate.total**
统计的是所有未纠正的 ECC 错误的总数,包括易失性和非易失性的错误。这也是一个累积的计数,不会在 GPU 重新启动后重置。
- **ecc.errors.uncorrected.volatile.total**
统计的是自上次 GPU 重新启动以来,所有未纠正的易失性 ECC 错误的总数。
- **ecc.errors.corrected.volatile.sram**
SRAM 中已纠正的 ECC 错误(易失性)。
- **ecc.errors.corrected.volatile.l1_cache**
L1 缓存中已纠正的 ECC 错误(易失性)。
- **ecc.errors.corrected.volatile.l2_cache**
L2 缓存中已纠正的 ECC 错误(易失性)。
- **ecc.errors.corrected.volatile.device_memory**
设备内存(DRAM)中已纠正的 ECC 错误(易失性)。
- **ecc.errors.uncorrected.volatile.sram**
SRAM 中未纠正的 ECC 错误(易失性)。
- **ecc.errors.uncorrected.volatile.l1_cache**
L1 缓存中未纠正的 ECC 错误(易失性)。
- **ecc.errors.uncorrected.volatile.l2_cache**
L2 缓存中未纠正的 ECC 错误(易失性)。
- **ecc.errors.uncorrected.volatile.device_memory**
设备内存(DRAM)中未纠正的 ECC 错误(易失性)。
**在 GPU 中,存储器的层次结构从快速但容量较小的缓存到较慢但容量较大的设备内存(DRAM)。以下是这些不同类型存储器的顺序:**
> SRAM (Static Random-Access Memory):
>
> 位置: 通常用于存储小而频繁访问的数据,例如寄存器和某些缓存。
>
> 特点: 非常快,但容量较小。用于 CPU/GPU 的寄存器文件和一些缓存中。
>
> L1 Cache:
>
> 位置: 紧邻 GPU 的计算核心。
>
> 特点: 最接近计算核心的缓存,速度最快,容量最小。用于存储最近访问的指令和数据,以加速处理。
>
> L2 Cache:
>
> 位置: 通常位于 GPU 内存控制器和 L1 缓存之间。
>
> 特点: 比 L1 缓存稍慢,但容量更大。它作为 L1 缓存的后备存储,并在核心之间共享。
>
> Device Memory (DRAM):
>
> 位置: 这是 GPU 的主要内存。
>
> 特点: 容量最大,但速度最慢。用于存储大量的数据和程序,是 L1 和 L2 缓存的最终后备存储。
>
> 顺序总结:
>
> SRAM → L1 Cache → L2 Cache → Device Memory (DRAM)
>
> 这个顺序反映了从快速小容量存储器到较慢大容量存储器的存储层次结构。 ECC 错误的纠正也会依次在这些不同层次中发生。
**3)具体查询命令的结构**
你可以按需修改 --query-gpu 选项来查询特定的 ECC 错误统计项。以下是命令结构的例子:
```bash
nvidia-smi --query-gpu=<ecc.errors.type> --format=csv,noheader
```
例如,要查询所有已纠正和未纠正的 ECC 错误,可以使用:
```bash
nvidia-smi --query-gpu=ecc.errors.corrected.aggregate.total,ecc.errors.uncorrected.aggregate.total --format=csv,noheader
```
**4)检查是否启用 ECC 模式**
ECC 错误只有在 GPU 的 ECC 模式启用时才会被记录。你可以使用以下命令检查 ECC 模式是否启用:
```bash
nvidia-smi --query-gpu=ecc.mode.current --format=csv,noheader
```
通过这些方法,你可以查看并监控 GPU 上所有可能的 ECC 错误,帮助诊断和管理 GPU 的健康状态。
官方文档: https://docs.nvidia.com/deploy/a100-gpu-mem-error-mgmt/index.html
# PCIe
## ACS(Access Control Services,访问控制服务)
PCIe ACS(Access Control Services,访问控制服务)是 PCI Express(PCIe)规范的一部分,它为多功能设备或多插槽系统中的数据路径控制提供了一组功能。ACS 的主要目标是确保设备之间的隔离,以增强安全性和提高系统的稳定性。
**主要功能**
- 请求隔离:ACS 允许系统中的每个 PCIe 设备之间的请求(如读、写、配置访问等)进行隔离,防止未经授权的设备访问不该访问的内存或其他设备。这在虚拟化环境中特别重要,因为不同的虚拟机可能会共享同一台主机的硬件资源,确保它们之间的隔离非常关键。
- 错误隔离:当发生错误时,ACS 能够确保错误仅限于特定设备或路径,而不会影响整个系统。这有助于提高系统的可靠性。
- 基于地址的路由:ACS 允许设备根据目标地址来决定数据包的路由。这在多设备系统中尤为重要,可以确保数据包到达正确的目标设备。
**使用场景**
- 虚拟化:在虚拟化环境中,多个虚拟机可能会共享一个 PCIe 设备。ACS 确保这些虚拟机之间的数据隔离,防止它们相互干扰。
- 安全性:ACS 增强了系统的安全性,确保设备之间的通信不被其他设备窃听或篡改。
- 多 GPU 系统:在多 GPU 系统中,ACS 确保 GPU 之间的隔离,防止数据包被错误的 GPU 接收。
**配置与控制**
ACS 通常通过系统 BIOS 或操作系统中的相关设置进行启用或配置。在某些高性能计算和虚拟化环境中,正确配置 ACS 是确保系统稳定性和安全性的重要步骤。
**ACS功能**
- ACS Source Validation (SV): 验证请求源的有效性。
- ACS Translation Blocking (TB): 阻止对地址转换服务的访问。
- ACS P2P Request Redirect (RR): 控制设备对等请求的转发。
- ACS P2P Completion Redirect (CR): 控制设备对等完成操作的转发。
- ACS Upstream Forwarding (UF): 控制请求是否仅被转发到上游端口。
- ACS Direct Translated P2P (DT): 控制直接地址翻译的对等传输。
**相关命令**
- 查看开启了ACS哪些功能.
`lspci -vvv | grep -i ACSCtl`
- 关闭ACS
```bash
#!/bin/bash
#
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# Disable ACS on every device that supports it
# Don't do anything on DGX-2 platforms, they are fine the way they are.
PLATFORM=$(dmidecode --string system-product-name)
logger "PLATFORM=${PLATFORM}"
# Enforce platform check here.
case "${PLATFORM}" in
"NVIDIA DGX-2"*)
logger "INFO: Disabling ACS is no longer necessary for ${PLATFORM}"
exit 0
;;
*)
;;
esac
# must be root to access extended PCI config space
if [ "$EUID" -ne 0 ]; then
echo "ERROR: $0 must be run as root"
exit 1
fi
for BDF in `lspci -d "*:*:*" | awk '{print $1}'`; do
# skip if it doesn't support ACS
setpci -v -s ${BDF} ECAP_ACS+0x6.w > /dev/null 2>&1
if [ $? -ne 0 ]; then
#echo "${BDF} does not support ACS, skipping"
continue
fi
logger "Disabling ACS on `lspci -s ${BDF}`"
setpci -v -s ${BDF} ECAP_ACS+0x6.w=0000
if [ $? -ne 0 ]; then
logger "Error disabling ACS on ${BDF}"
continue
fi
NEW_VAL=`setpci -v -s ${BDF} ECAP_ACS+0x6.w | awk '{print $NF}'`
if [ "${NEW_VAL}" != "0000" ]; then
logger "Failed to disable ACS on ${BDF}"
continue
fi
done
ret=$(for i in $(lspci -d "10b5:" | awk '{print $1}') ; do lspci -vvv -s $i | grep ACSCtl;done|grep "+"|wc -l)
echo "After Configuration, ACSCtl value is $ret. Expected to be 0"
exit 0
```
# NCCL
---
[pdf介绍](https://images.nvidia.com/events/sc15/pdfs/NCCL-Woolley.pdf)
# NVLink
---
[TODO]
# RDMA
---
**Remote Direct Memory Access**
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-5367e885e2794344a0ee6d20fc23de0b.png)
https://zhuanlan.zhihu.com/p/55142557
## Infiniband
---
- `ibdev2netdev`
- `ibstat`
- `ibstatus`
# 常见的检测命令
---
- **检测XID errors**
`dmesg -T |grep -i xid`
- **dcgmi check errors**
`dcgmi diag -r 4 --fail-early`
![image.png](https://blog.zs-fighting.cn/upload/2024/08/image-839b98a66c1341cfa6fab5dba84c1ae1.png)
- **检测GPU掉卡数量 & 检测GPU数量**
每个GPU末尾标识为(rev a1). 输出信息末尾为(rev ff), 表示GPU异常.
掉卡数量
`lspci -d 10de:|grep "rev ff"`
正常数量
`lspci -d 10de:|grep -v 1af1`
- **GPU温度检测**
`nvidia-smi --query-gpu=temperature.gpu --format=csv`
- **GPU功耗检测**
`nvidia-smi`
存在某张卡的功率一栏是Unknown或者err
- **查询所有RDMA网卡的接口状态**
`ibdev2netdev |grep -v eth0`
- **RDMA网卡抖动检测**
`dmesg -T | grep -i eth|grep -i link|grep -i down|wc -l`
- **mtu检测**
查询所有RDMA网卡的接口名称
`show_gids |grep v2|awk '{print $7}'|sed '/^$/d'|grep -v eth0`
依次查询每个RDMA网卡的mtu
`ip -4 -j -p addr show dev ${ifname}|grep mtu`
# 相关知识
## GPU架构
**NVIDIA GPU 架构的演进:**
![Nvidia_gpu_timeline.jpeg](https://blog.zs-fighting.cn/upload/2024/06/fbac5ea3-62b1-4ba8-ba43-9791c0e9f5a7-75090a8c4826466a92949c0a97e508fe.jpeg)
**架构区别:**
- **Hopper 架构**: Hopper 架构是 NVIDIA GPU 的第九代架构,2022 年发布。相较于 Ampere,Hopper 架构支持第四代 Tensor Core,且采用新型流式处理器,每个 SM 能力更强。Hopper 架构在计算能力、深度学习加速和图形功能方面带来新的创新和改进。
- **Ampere 架构**: Ampere 架构是 NVIDIA GPU 的第八代架构,2020 年发布。Ampere 架构在计算能力、能效和深度学习性能方面都有重大提升。Ampere 架构的 GPU 采用了多个[流多处理器](SM)和更大的总线宽度,提供了更多的 CUDA Core 和更高的频率。它还引入了第三代 Tensor Core,提供更强大的深度学习计算性能。Ampere 架构的 GPU 还具有更高的内存容量和带宽,适用于大规模的数据处理和机器学习任务。
- **Turing 架构**: Turing 架构是 NVIDIA GPU 的第七代架构,发布于 2018 年。Turing 架构引入了实时光线追踪(RTX)和深度学习超采样(DLSS)等重要功能。
- **Volta 架构**: Volta 架构是 NVIDIA GPU 的第六代架构,发布于 2017 年。Volta 架构专注于深度学习和人工智能应用,并引入了 Tensor Core。
## 常见卡型
- H100/H800/H20
- L20/L40
- A100/A800/A30/A10
- T4
- V100
## GPU 的核心架构及参数
- **Tensor Core**: Tensor Core 是 NVIDIA Volta 架构及其后续架构(如 Ampere 架构)中引入的一种特殊计算单元。它们专门用于深度学习任务中的张量计算,如[矩阵乘法]和卷积运算。Tensor Core 核心特别大,通常与深度学习框架(如 TensorFlow 和 PyTorch)相结合使用,它可以把整个矩阵都载入寄存器中批量运算,实现十几倍的效率提升。
- **CUDA Core**: CUDA Core 是 NVIDIA GPU 上的计算核心单元,用于执行通用的并行计算任务,是最常看到的核心类型。NVIDIA 通常用最小的运算单元表示自己的运算能力,CUDA Core 指的是一个执行基础运算的处理元件,我们所说的 CUDA Core 数量,通常对应的是 FP32 计算单元的数量。
- **RT Core**: RT Core 是 NVIDIA 的专用硬件单元,主要用于加速光线追踪计算。正常数据中心级的 GPU 核心是没有 RT Core 的,主要是消费级显卡才为光线追踪运算添加了 RTCores。RT Core 主要用于游戏开发、电影制作和虚拟现实等需要实时渲染的领域。
# 原理
## Tensor Core 原理
---
在 NVIDIA 的通用 GPU 架构中,主要存在三种核心类型:CUDA Core、Tensor Core 以及 RT Core。其中,Tensor Core 扮演着极其关键的角色。
Tensor Core 是针对深度学习和 AI 工作负载而设计的专用核心,可以实现混合精度计算并加速矩阵运算,尤其擅长处理半精度(FP16)和全精度(FP32)的矩阵乘法和累加操作。Tensor Core 在加速深度学习训练和推理中发挥着重要作用。
### 初代 Tensor Core
---
当 NVIDIA 的架构演进到 Volta 架构时,标志着深度学习优化的重大突破。Volta 架构的一个显著特点是引入了大量的 Tensor Core,这一变化对于加速深度学习应用产生了革命性的影响。
![image.png](https://blog.zs-fighting.cn/upload/2024/06/image-e832fd5395ec48dcb0b544f7d859d654.png)
在 Tensor Core 出现之前,CUDA Core 是实现深度学习加速的核心硬件技术。CUDA Core 可以处理各种精度的运算。如上图 Volta 架构图所示,**左侧有 FP64、FP32 和 INT32 CUDA Cores 核心,右侧则是许多 Tensor Core 核心。**
- **CUDA Core**
尽管 CUDA Core 能够广泛地支持并行计算模式,它在执行深度学习中最常见的操作,如卷积(Conv)和矩阵乘法(GEMM)时仍然面临效率上的挑战。
具体来说,CUDA Core 在执行这些操作时,需要将数据在寄存器、算术逻辑单元(ALU)和寄存器之间进行多次搬运,这种过程既耗时又低效。此外,每个 CUDA Core 单个时钟周期只能执行一次运算,而且 CUDA Core 的数量和时钟速度都有其物理限制,这些因素共同限制了深度学习计算性能的提升。
- **Tensor Core**
随着 Volta 架构的推出,NVIDIA 引入了 Tensor Core,这是一种专为 AI 训练和推理设计的可编程矩阵乘法和累加单元。V100 GPU 中包含了 640 个 Tensor Core,每个流多处理器(SM)配备了 8 个 Tensor Core。相较于 CUDA Core,Tensor Core 能够在每个时钟周期内执行更多的运算,特别是它可以高效地完成矩阵乘法和累加操作两种操作是深度学习中最频繁和计算密集的任务之一。
通过利用 Tensor Core,V100 能够为 AI 训练和推理提供高达 125 Tensor TFLOPS 的算力。这种强大的性能,使得 V100 在处理深度学习任务时,相比于仅使用 CUDA Core 的早期架构,能够实现显著的加速。
### Tensor Core 工作原理
---
在具体的运算过程中,Tensor Core 采用融合乘法加法(FMA)的方式来高效地处理计算任务。每个 Tensor Core 每周期能执行 4x4x4 GEMM,64 个 浮点乘法累加(FMA)运算。
![image.png](https://blog.zs-fighting.cn/upload/2024/06/image-c25f38eba8754e0288fda641c1a7fb0c.png)
如上图所示,在执行运算 D=A*B+C,其中 A、B、C 和 D 是 4×4 矩阵。矩阵乘法输入 A 和 B 是 FP16 矩阵,而累加矩阵 C 和 D 可以是 FP16 或 FP32 矩阵。
具体来说,它首先接受两个 4x4 的 FP16 精度的输入矩阵 A 和 B,执行它们的矩阵乘法。然后,将这个乘法的结果与第三个 4x4 的矩阵 C 相加,其中矩阵 C 可以是 FP16 或 FP32 精度。最终,Tensor Core 输出一个新的 4x4 矩阵 D,该矩阵同样可以是 FP16 或 FP32 精度。
这也就实现了底层硬件上的混合精度计算。通过将矩阵乘法的输入限定为 FP16 精度,可以大幅减少所需的计算资源和内存带宽,从而加速计算。同时,通过允许累加矩阵 C 和输出矩阵 D 使用 FP32 精度,可以保证运算结果的准确性和数值稳定性。这种灵活的精度策略,结合 Tensor Core 的高效计算能力,使得在保持高性能的同时,还能有效控制深度学习模型的训练和推理过程中的资源消耗。
接下来我们再打开一层进一步探讨 Tensor Core 的运算能力。上文我们谈到在每个 Tensor Core 每个时钟执行 64 个 FP32 FMA 混合精度运算,一个 SM 中一共有 8 个 Tensor Core,所以每个时钟周期内总共执行 512 个浮点运算(8 个 Tensor Core × 64 个 FMA 操作/核)。
因此在 AI 应用中,Volta V100 GPU 的吞吐量与 Pascal P100 GPU 相比,每个 SM 的 AI 吞吐量提高 8 倍,此外得益于 Volta 架构在 SM 数量和核心设计上的优化,总体上共提高 12 倍。
### Tensor Core 与 CUDA 编程
---
如图所示,在 CUDA 编程体系中,我们并非直接对线程进行控制,也就是图中的弯弯的线,而是通过控制一个 Warp,一个 Warp 包含很多线程(通常为 32 个线程),这些线程同时并行执行,利用 GPU 的并行计算能力。
![image.png](https://blog.zs-fighting.cn/upload/2024/06/image-f4e455188796473eab8c5b0129dce56c.png)
在实际执行过程中,CUDA 会对 Warp 进行同步操作,确保其中的所有线程都达到同步点,并获取相同的数据。然后,这些线程将一起执行矩阵相乘和其他计算操作,通常以 16x16 的矩阵块为单位进行计算。最终,计算结果将被存储回不同的 Warp 中,以便后续处理或输出。
我们可以把 Warp 理解为软件上的一个大的线程概念,它帮助简化了对 GPU 并行计算资源的管理和利用。通过有效地利用 Warp 的并行性,CUDA 程序可以实现高效、快速的并行计算。
在 CUDA 程序执行过程中,我们可以通过线程的 Warp 来调度 Tensor Core 的执行。多个 Tensor Core 可以同时通过 Warp 内的线程来执行计算任务,利用 Tensor Core 提供的高性能矩阵运算能力。每个 Warp 内的线程可以利用 Tensor Core 执行 16x16x16 的矩阵运算,充分发挥 GPU 的计算潜能。
```c
template<typename Use, int m, int n, int k, typename T, typename Layout=void> class fragment;
void load_matrix_sync(fragment<...> &a, const T* mptr, unsigned ldm);
void load_matrix_sync(fragment<...> &a, const T* mptr, unsigned ldm, layout_t layout);
void store_matrix_sync(T* mptr, const fragment<...> &a, unsigned ldm, layout_t layout);
void fill_fragment(fragment<...> &a, const T& v);
void mma_sync(fragment<...> &d, const fragment<...> &a, const fragment<...> &b, const fragment<...> &c, bool satf=false);
```
其中:
- `fragment`:Tensor Core 数据存储类,支持 `matrix_a`、`matrix_b` 和 `accumulator`;
- `load_matrix_sync`:Tensor Core 数据加载 API,支持将矩阵数据从 global memory 或 shared memory 加载到 fragment;
- `store_matrix_sync`:Tensor Core 结果存储 API,支持将计算结果从 fragment 存储到 global memory 或 shared memory;
- `fill_fragment`:fragment 填充 API,支持常数值填充;
- `mma_sync`:Tensor Core 矩阵乘计算 API,支持 D = AB + C 或者 C = AB + C。
CUDA 通过**CUDA C++ WMMA API**向外提供了 Tensor Core 在 Warp 级别上的计算操作支持。这些 C++接口提供了专门用于矩阵加载、矩阵乘法和累加、以及矩阵存储等操作的功能。例如上图所示代码中,其中的 `mma_sync` 就是执行具体计算的 API 接口。借助这些 API,开发者可以高效地利用 Tensor Core 进行深度学习中的矩阵计算,从而加速神经网络模型的训练和推理过程。
一个 Tensor Core 每个周期可以执行 4x4x4 的 GEMM 运算。然而,在 CUDA 的层面,为什么提供了使用 16x16x16 的 GEMM 运算 API 呢?
![image.png](https://blog.zs-fighting.cn/upload/2024/06/image-1c48e18524a2437190033de093cdadce.png)
事实上,如果我们整体来看,如上图所示,一个 Tensor Core 是一个 4x4 的 Tensor Core 核心。但实际上,在一个 SM(Streaming Multiprocessor)中有多个 Tensor Core,我们无法对每个 Tensor Core 进行细粒度的控制,否则效率会很低。因此,一个 Warp 就扮演了重要角色,将多个 Tensor Core 打包在一起,以执行更大规模的计算任务。
通过 Warp 层的卷积指令,CUDA 向外提供了一个 16x16x16 的抽象层,使得开发者可以通过一条指令完成多个 Tensor Core 的协同工作,实现高效的并行计算。这条指令也即我们之前提到的mma_sync API,它允许开发者利用 Warp 内的线程同时调度多个 Tensor Core 执行矩阵乘加操作,从而提高 GPU 计算的效率和性能。
那么现在有一个问题,Tensor Core 是如何跟卷积计算或者 GEMM 计算之间进行映射的呢?
例如 GPU 中的 Tensor Core 一次仅仅只有 4x4 这么小的 kernel,怎么处理 input image $224224$,kernel $77$ 的 GEMM 计算呢?
或者说在现在大模型时代,Tensor Core 是怎么处理 Transformer 结构 inputembedding 为 $20482048$,hiddensize 为 $10241024$ 的 GEMM 呢?
上文我们已经提到,卷积运算可以被转化为矩阵乘法操作,这一点是连接卷积和 Tensor Core 的桥梁。
![image.png](https://blog.zs-fighting.cn/upload/2024/06/image-594b61965ffd4d35b7d4290b91016ae9.png)
在实际执行过程中,如上图中所示,蓝色矩阵和黄色矩阵的片段会被取出进行计算,即所谓的 Fragment。这些 Fragment 进行计算后形成 Fragment block,而这些 Fragment block 在 CUDA 编程模型中就是通过线程块(Thread block)的来组织执行的。在线程块内部的计算过程中,会进一步提取部分数据形成 Warp level 级别的计算,Warp level 的计算其实还是很大,于是在 Fragment 执行时会将其变为满足我们 Tensor Core 和矩阵输入的计算了。
## SM Clock
---
SM (Streaming Multiprocessor) Clock 是 NVIDIA GPU 中的重要时钟频率,代表了流式多处理器 (Streaming Multiprocessor, SM) 的工作频率。SM 是 GPU 的基本计算单元,负责执行并行计算任务,而 SM Clock 则直接影响这些计算任务的执行速度。
**什么是 SM Clock(SM 时钟频率)?**
**定义**:
- SM Clock 是流式多处理器的工作频率,表示 SM 内部所有计算单元(包括 CUDA 核心和 Tensor 核心)的同步工作速度。
**影响性能的关键**:
- 计算性能:SM Clock 越高,SM 内部的计算单元就能以更快的速度执行指令,从而提高 GPU 的计算性能。
- 数据吞吐量:更高的时钟频率也意味着更高的数据吞吐量,SM 可以在更短的时间内处理更多的数据。
- 响应时间:提高 SM Clock 可以减少任务的执行时间,有助于提高应用程序的响应速度,特别是在实时渲染和高性能计算中。
**SM Clock 的作用**:
- 直接影响计算能力:GPU 的总体计算能力与 SM Clock 直接相关。更高的 SM Clock 频率可以提高每个 SM 的计算能力,从而提升 GPU 的整体性能。
- 影响能耗与热量:更高的时钟频率通常意味着更高的功耗和热量输出。这要求 GPU 设计中考虑到散热和电力管理。
**SM Clock 与其他时钟的关系**:
- Memory Clock(内存时钟频率):控制显存的工作频率,影响数据传输速率。
- Graphics Clock(图形时钟频率):通常与 SM Clock 相同或近似,控制着整个 GPU 核心的时钟频率,包括 SM 和其他单元。
## 卷积计算
---
卷积运算是深度学习和神经网络中常用的一种操作,用于从输入数据中提取特征。卷积操作通常用于处理图像数据,但也可以应用于其他类型的数据,如语音、文本等。在深度学习中,卷积运算通常与激活函数(如 ReLU)、池化层等结合使用,构成卷积神经网络(CNN),用于提取并学习数据中的特征,从而实现图像识别、分类、分割等任务。Tensor Core 则是 NVIDIA 推出的一种专为加速深度学习中的矩阵计算而设计的硬件加速器
### CNN vs GEMM
---
在深度学习中,卷积运算通常指的是利用一个小的、可学习的过滤器(或称为卷积核)在输入数据(如图像)上滑动,并在每个位置计算过滤器与其覆盖区域的元素逐点相乘后的总和,这个过程可以捕捉到局部特征。对于多通道输入,卷积运算会对每个通道执行此操作,并将结果累加起来得到最终的输出。当应用于图像处理时,这种机制使得卷积网络能够有效地识别图像中的边缘、纹理等特征。
卷积神经网络 CNN 一般包含许多卷积层,这些层通过卷积运算提取输入数据的特征。在算法层面上,卷积运算的加速通常涉及到一个关键步骤——数据重排,即执行 Im2col 操作。
Im2col 操作的目的是将卷积运算转换为矩阵乘法,这样做有几个显著的好处。首先,它允许利用已有的高效矩阵乘法算法(如 GEMM,General Matrix Multiply)来加速卷积计算。其次,这种转换可以减少重复的内存访问,因为在传统的卷积运算中,同一个输入元素可能会被多个卷积核重复使用。
Im2col 是计算机视觉领域中将图片转换成矩阵的矩阵列(Column)的计算过程。由于二维卷积的计算比较复杂不易优化,因此在 AI 框架早期,Caffe 使用 Im2col 方法将三维张量转换为二维矩阵,从而充分利用已经优化好的 GEMM 库来为各个平台加速卷积计算。最后,再将矩阵乘得到的二维矩阵结果使用 Col2Im 将转换为三维矩阵输出。
Img2col 算法主要包含两个步骤,首先使用 Im2col 将输入矩阵展开一个大矩阵,矩阵每一列表示卷积核需要的一个输入数据,其次使用上面转换的矩阵进行 Matmul 运算,得到的数据就是最终卷积计算的结果。
卷积默认采用数据排布方式为 NHWC,输入维度为 4 维 (N, IH, IW, IC),卷积核维度为(OC, KH, KW , IC),输出维度为(N, OH, OW , OC)。
![image.png](https://blog.zs-fighting.cn/upload/2024/06/image-6bbd00284a1f464883b08d042dea32d4.png)
通过 Im2col,输入数据被重排成一个大矩阵,而卷积权重(即卷积核)也被转换为另一个矩阵。这样,原本的卷积运算就转化为了这两个矩阵的乘法操作,如图上所示。这种转换后的矩阵乘法可以利用现代计算架构(如 Tensor Core)的强大计算能力,从而实现高效的计算加速。
而 GEMM(General Matrix Multiply,通用矩阵乘法)是一种高效的矩阵乘法算法,它特别适合于处理大规模的矩阵运算。在将卷积转换为矩阵乘法之后,多个这样的矩阵乘法计算可以被组织成单个更大的矩阵乘法运算来执行。这种方法称为批量处理,它可以进一步提升计算效率,因为它允许同时处理多个数据样本,从而更好地利用 GPU 等并行计算资源。
通过 Im2col 操作和利用 GEMM 进行批量处理,卷积神经网络中的卷积层计算可以得到显著加速。这种加速不仅提高了模型训练的效率,也使得在实际应用中的推理过程更为迅速,为深度学习模型的开发和部署带来了实质性的好处。
### 混合精度训练
---
混合精度训练实际上是一种优化技术,它通过在模型训练过程中灵活地使用不同的数值精度来达到加速训练和减少内存消耗的目的。具体来说,混合精度训练涉及到两个关键操作:
- 计算的精度分配:在模型的前向传播和反向传播过程中,使用较低的精度(如 FP16)进行计算,以加快计算速度和降低内存使用量。由于 FP16 格式所需的内存和带宽均低于 FP32,这可以显著提高数据处理的效率。
- 参数更新的精度保持:尽管计算使用了较低的精度,但在更新模型参数时,仍然使用较高的精度(如 FP32)来保持训练过程的稳定性和模型的最终性能。这是因为直接使用 FP16 进行参数更新可能会导致训练不稳定,甚至模型无法收敛,由于 FP16 的表示范围和精度有限,容易出现梯度消失或溢出的问题。
![image.png](https://blog.zs-fighting.cn/upload/2024/06/image-7d4624f936d9427cb4e155d3bfe54be9.png)
而在混合精度的实现上,其通常需要特定的硬件支持和软件优化。例如,NVIDIA 的 Tensor Core 就是专门设计来加速 FP16 计算的,同时保持 FP32 的累加精度,从而使得混合精度训练成为可能。在软件层面,深度学习框架如 PyTorch 和 MindSpore 等也提供了混合精度训练的支持,通过自动化的工具简化了实现过程。可以从上图看出 FP16 相比于 FP32,不管是从整数位还是小数位来看,它所表示的范围要小很多。
## 卡型比较
### V100 vs A100 vs H100
在了解了 GPU 的核心参数和架构后,接下来的对比理解起来就简单多了。
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-3d213b6dba584e118f7027c7856fdd2d.png)
### A100 vs H100
NVIDIA H100 采用 NVIDIA Hopper GPU 架构,使 NVIDIA 数据中心平台的加速计算性能再次实现了重大飞跃。H100 采用专为 NVIDIA 定制的 TSMC 4N 工艺制造,拥有 800 亿个 [晶体管],并包含多项架构改进。
H100 是 NVIDIA 的第 9 代数据中心 GPU,旨在为大规模 AI 和 HPC 实现相比于上一代 NVIDIA A100 Tensor Core GPU 数量级的性能飞跃。H100 延续了 A100 的主要设计重点,可提升 AI 和 HPC 工作负载的强大扩展能力,并显著提升架构效率。
### A800 vs H800
从数字上来看,800 比 100 数字要大,其实是为了合规对 A100 和 H100 的某些参数做了调整。A800 相对比 A100 而言,仅限制了 GPU 之间的互联带宽,从 A100 的 600GB/s 降至 400GB/s,算力参数无变化。而 H800 则对算力和[互联带宽]都进行了调整。
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-d9b42addabfb44699c93319a3d127fe6.png)
A800 虽然在互联带宽上有所降低,但和 A100 在双精方面算力一致.
### H800 VS H100
作为 H100 的替代品,中国特供版 H800,PCIe 版本 SXM 版本都是在双精度(FP64)和 nvlink 传输速率的削减,其他其他参数和 H100 都是一模一样的。
FP64 上的削弱主要影响的是 H800 在科学计算,深度学习等应用主要看单精度的浮点性能,大部分场景下性能不受影响。而受到影响较大的还是 NVlink 上的削减,但是因为架构上的升级,虽然比不上同为 Hopper 架构的 H100,但是比 ampere 架构的 A800 还是要强上不少的。
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-888b0402d5444fd7b564211adcb91ccf.png)
### A100 vs H100G细解
**新的 SM 架构**
H100 SM 基于 NVIDIA A100 Tensor Core GPU SM 架构而构建。由于引入了 FP8,与 A100 相比,H100 SM 将每 SM 浮点计算能力峰值提升了 4 倍,并且对于之前所有的 Tensor Core 和 FP32 / FP64 数据类型,将各个时钟频率下的原始 SM 计算能力增加了一倍。
与上一代 A100 相比,采用 Hopper 的 FP8 Tensor Core 的新 Transformer 引擎使大型语言模型的 AI 训练速度提升 9 倍,AI 推理速度提升 30 倍。
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-ef779a6d7c0f4dd1a06e54b825db9a2e.png)
**第四代 Tensor Core 架构**
Hopper 新的第四代 Tensor Core、Tensor 内存加速器以及许多其他新 SM 和 H100 架构的总体改进,在许多其他情况下可令 HPC 和 AI 性能获得最高 3 倍的提升。
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-b2325230221f4f809a42805b1bb5db5b.png)
与 A100 相比,H100 中新的第四代 Tensor Core 架构可使每时钟每个 SM 的原始密集计算和[稀疏矩阵]运算吞吐量提升一倍,考虑到 H100 比 A100 拥有更高的 GPU 加速频率,其甚至会达到更高的吞吐量。其支持 FP8、FP16、BF16、TF32、FP64 和 INT8 MMA 数据类型。新的 Tensor Core 还能够实现更高效的数据管理,最高可节省 30% 的操作数传输功耗。
**目前主流四款GPU详解[A100、H100 、L40S、H200(2024)]**
![image.png](https://blog.zs-fighting.cn/upload/2024/05/image-a5ccf65749fd49b2b4100982e6dacc7e.png)
GPU常见故障及排查方法