PPU多卡ID映射
1. 背景
在驱动在初始化 PPU 的时候会按照一定的顺序给每个 PPU 配置 PPU-id,这个 id 的顺序就是 ppudbg、ppu-smi 和 CUDA_VISIBLE_DEVICES 这些上层工具应用看到的 PPU 顺序。
以 ppu-smi 截图为例,红框中的数字就是 PPU-id。

而在 16卡 810E 机型中,通常存在两个机尾,每个机尾的 8 张 PPU 在物理距离上是更近的,但是驱动默认的初始化顺序不是按照相同机尾的顺序而是 os 枚举的顺序(通常是 lspci 看到的 PCIE 设备顺序)来配置 PPU-id。
这就造成上层应用很多时候需要通过 CUDA_VISIBLE_DEVICES 来指定 PPU 执行程序,为了更好的提升 PCCL 通信库和其他应用在驱动默认配置下的性能,驱动会在 16 卡机型上面对 PPU 进行一次排序,来保证同一个机尾的 PPU 被分配到的 PPU-id 是连续的。
2. 哪些驱动版本会做这个排序
排序只在这些 KMD 驱动版本上生效:1.3.0-63f79b 或 1.3.1-xxxx。
目前会有两种排序方法,section 4 会详细介绍
1.3.0-63f79b 采用 排序方法1
1.3.1-xxxx 采用 排序方法2
3. 哪些机型会做这个排序
驱动当且仅当在 16 卡 810E 机型上面对 PPU 进行一次排序,来保证同一个机尾的 PPU 被分配到的 PPU-id 是连续的。8 卡多卡机型不受影响。
4. 排序规则
驱动会按照 UNIQUE-id 从小到大排序之后的顺依次配置 PPU-id,n 卡机器对应的 PPU-id 是 [0, n-1]。
UNIQUE-id 在不同的排序规则中格式不同,下面将分别介绍。
4.1 排序方法1
4.1.1 REAR-id
首先 16 卡机型目前的 PCIE BDF 都是固定的,如下图所示:

驱动在初始化 PPU 的时候,会根据图中 BDF 来确定这个 PPU 的机尾 id(REARid),例如 0000:c7:00.0 对应的 REARid 就是 1 ,其他的以此类推。按照图中 PCIE-bdf 来确定机尾 id,如果不属于图中机尾 2 列出来的 8 个 PCIE-bdf,机尾 id 就会默认是 1。
4.1.2 UNIQUE-id
随后驱动会根据 REAR-id,PCIE-domain-id,PCIE-bus-id,PCIE-slot-id,PCIE-func-id 生成一个 UNIQUE-id 来对 PPU 进行从小到大排序,UNIQUE-id 的格式如下:
union {
struct {
uint64_t PCIE-func-id : 3;
uint64_t PCIE-slot-id : 5;
uint64_t PCIE-bus-id : 8;
uint64_t PCIE-domain-id : 16;
uint64_t REAR-id : 32;
};
uint64_t UNIQUE-id;
};4.2 排序方法2
排序方法 1 有很大的局限性,那就是认为 16 卡 PCIE BDF 是不会变化的,这在新机型或者 vm passthrough 的时候就会打破这个规则,因此这里引入一种新的排序方式,将 PPU-id 和真正的 PCIE 物理槽位对应起来,来确保不同的 16 卡场景也能拥有相同的 PPU-id 配置。
4.2.1 MODULE-id
还是下面这张图:

图中从右数第二列对应的 OAMx 编号叫做 MODULE-id,例如 0000:c7:00.0 的 MODULE-id 就是 6,PPU 可以通过读取寄存器的方式获取 MODULE-id,就不会和 PCIE BDF 绑定在一起了,也就是说这个图中 PCIE-bdf 再如何变更,MODULE-id 是不变的。
4.2.2 REAR-id
随后我们需要通过另一种方式获取 REAR-id,如下图:

在 PCIE config space 内部,有一个 slot capability 的字段,这个字段对应的 [31:19] 是 BOX-id 和 SLOT-number 的组合,我们读取 BOX-id 作为 REAR-id。
需要额外注意的是,PCIE EP 通常是没有 slot capability 的,必须读取 EP 上一级 bridge 的 slot capability,具体的说明见 PCIE 规范:

驱动通过读取 PPU 上一级 bridge 的 config space 获取到 REAR-id。
4.2.3 UNIQUE-id
现在我们拥有了两个和 PCIE 物理槽位强绑定的 id
随后驱动会根据 REAR-id,MODULE-id 生成一个 UNIQUE-id 来对 PPU 进行从小到大排序,UNIQUE-id 的格式如下:
union {
struct {
uint64_t MODULE-id : 32;
uint64_t REAR-id : 32;
};
uint64_t UNIQUE-id;
};5. PCIE-bdf 和 Module-id PPU-id 的对应关系
PCIE-bdf | Moudle-id | PPU-id | PPU-id | PPU-id |
0000:08:00.0 | 4 | 0 | 8 | 12 |
0000:09:00.0 | 5 | 1 | 9 | 13 |
0000:7e:00.0 | 4 | 2 | 0 | 4 |
0000:7f:00.0 | 5 | 3 | 1 | 5 |
0000:a2:00.0 | 7 | 4 | 10 | 15 |
0000:a3:00.0 | 6 | 5 | 11 | 14 |
0000:c6:00.0 | 7 | 6 | 2 | 7 |
0000:c7:00.0 | 6 | 7 | 3 | 6 |
0001:0a:00.0 | 2 | 8 | 12 | 10 |
0001:0b:00.0 | 3 | 9 | 13 | 11 |
0001:80:00.0 | 2 | 10 | 4 | 2 |
0001:81:00.0 | 3 | 11 | 5 | 3 |
0001:a4:00.0 | 1 | 12 | 14 | 9 |
0001:a5:00.0 | 0 | 13 | 15 | 8 |
0001:c8:00.0 | 1 | 14 | 6 | 1 |
0001:c9:00.0 | 0 | 15 | 7 | 0 |
5.1 排序前拓扑图

5.2 排序后拓扑图
5.2.1 排序方法1

5.2.2 排序方法2
