feat: add Ampere (A100/A800) support and generalize project naming
- Expand GPU specs database to include A100/A800 with Ampere architecture parameters - Rename h200_tester.py to gpu_tester.py for architecture-neutral branding - Add driver/CUDA compatibility validation per GPU generation - Enhance report module with HTML and Markdown output formats - Improve nvbandwidth binary discovery (system paths, DCGM locations) - Add pyproject.toml with uv for dependency management - Update install_deps.sh, configs, and README for multi-architecture support 🤖 Generated with [Qoder][https://qoder.com]
This commit is contained in:
parent
07250af845
commit
3e967dd34a
162
README.md
162
README.md
@ -1,9 +1,9 @@
|
|||||||
# GPU Training Server Test Suite
|
# GPU Training Server Test Suite
|
||||||
|
|
||||||
面向 NVIDIA 数据中心 GPU(H100 / H200 / B200 / B300)训练服务器的自动化测试与基准测试工具集。
|
面向 NVIDIA 数据中心 GPU(A100 / A800 / H100 / H200 / B200 / B300)训练服务器的自动化测试与基准测试工具集。
|
||||||
涵盖硬件检测、健康诊断、带宽基准、计算吞吐、多卡通信、压力稳定性、RDMA 网络和训练模拟。
|
涵盖硬件检测、健康诊断、带宽基准、计算吞吐、多卡通信、压力稳定性、RDMA 网络和训练模拟。
|
||||||
|
|
||||||
> **支持 GPU 架构:** Hopper (H100/H200) · Blackwell (B200/B300)
|
> **支持 GPU 架构:** Ampere (A100/A800) · Hopper (H100/H200) · Blackwell (B200/B300)
|
||||||
> 系统自动检测 GPU 型号并使用对应的规格参数进行基准对比。
|
> 系统自动检测 GPU 型号并使用对应的规格参数进行基准对比。
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -27,12 +27,12 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
servertest/
|
servertest/
|
||||||
├── h200_tester.py # 主入口:CLI + 交互式菜单
|
├── gpu_tester.py # 主入口:CLI + 交互式菜单
|
||||||
├── install_deps.sh # 一键安装三方工具
|
├── install_deps.sh # 一键安装三方工具
|
||||||
├── configs/
|
├── configs/
|
||||||
│ └── default.yaml # 默认配置
|
│ └── default.yaml # 默认配置
|
||||||
├── modules/
|
├── modules/
|
||||||
│ ├── gpu_specs.py # GPU 规格数据库 (H100/H200/B200/B300)
|
│ ├── gpu_specs.py # GPU 规格数据库 (A100/A800/H100/H200/B200/B300)
|
||||||
│ ├── gpu_info.py # GPU 检测 & 信息
|
│ ├── gpu_info.py # GPU 检测 & 信息
|
||||||
│ ├── health_check.py # 健康诊断
|
│ ├── health_check.py # 健康诊断
|
||||||
│ ├── benchmark.py # 内存带宽 + 计算吞吐
|
│ ├── benchmark.py # 内存带宽 + 计算吞吐
|
||||||
@ -55,7 +55,7 @@ servertest/
|
|||||||
|---|---|
|
|---|---|
|
||||||
| OS | Ubuntu 22.04 / RHEL 8+ / Rocky 8+ |
|
| OS | Ubuntu 22.04 / RHEL 8+ / Rocky 8+ |
|
||||||
| Python | 3.10+ |
|
| Python | 3.10+ |
|
||||||
| NVIDIA Driver | ≥ 535(H200 支持) |
|
| NVIDIA Driver | ≥ 470(Ampere)/ ≥ 535(Hopper)/ ≥ 550(Blackwell) |
|
||||||
| CUDA | ≥ 12.1 |
|
| CUDA | ≥ 12.1 |
|
||||||
| nvidia-smi | 必须可用 |
|
| nvidia-smi | 必须可用 |
|
||||||
| pip 包 | rich, pyyaml |
|
| pip 包 | rich, pyyaml |
|
||||||
@ -64,7 +64,7 @@ servertest/
|
|||||||
|
|
||||||
| 项目 | 要求 |
|
| 项目 | 要求 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| GPU | ≥ 1 张 NVIDIA 数据中心 GPU(H100/H200/B200/B300 SXM) |
|
| GPU | ≥ 1 张 NVIDIA 数据中心 GPU(A100/A800/H100/H200/B200/B300 SXM) |
|
||||||
| MPI | OpenMPI ≥ 4.1 |
|
| MPI | OpenMPI ≥ 4.1 |
|
||||||
| RDMA | Mellanox ConnectX-7 / BlueField |
|
| RDMA | Mellanox ConnectX-7 / BlueField |
|
||||||
| nvbandwidth | 源码编译安装 |
|
| nvbandwidth | 源码编译安装 |
|
||||||
@ -86,13 +86,13 @@ cd test_gpu_scripts
|
|||||||
sudo bash install_deps.sh
|
sudo bash install_deps.sh
|
||||||
|
|
||||||
# 3. 运行交互式测试(自动检测 GPU 型号)
|
# 3. 运行交互式测试(自动检测 GPU 型号)
|
||||||
python3 h200_tester.py
|
python3 gpu_tester.py
|
||||||
|
|
||||||
# 4. 或一键全量测试
|
# 4. 或一键全量测试
|
||||||
python3 h200_tester.py --test all
|
python3 gpu_tester.py --test all
|
||||||
|
|
||||||
# 5. 手动指定 GPU 型号(跳过自动检测)
|
# 5. 手动指定 GPU 型号(跳过自动检测)
|
||||||
python3 h200_tester.py --gpu-type b200 --test all
|
python3 gpu_tester.py --gpu-type b200 --test all
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -113,18 +113,18 @@ sudo bash install_deps.sh
|
|||||||
5. 安装 Python 包(rich, pyyaml)
|
5. 安装 Python 包(rich, pyyaml)
|
||||||
6. 检查 DCGM 和 RDMA 工具状态
|
6. 检查 DCGM 和 RDMA 工具状态
|
||||||
|
|
||||||
默认安装目录 `/opt/h200-test-tools`,可通过环境变量自定义。
|
默认安装目录 `/opt/gpu-test-tools`,可通过环境变量自定义。
|
||||||
|
|
||||||
### 自定义安装目录
|
### 自定义安装目录
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo H200_TOOLS_DIR=/data/tools bash install_deps.sh
|
sudo GPU_TOOLS_DIR=/data/tools bash install_deps.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### 手动安装单项
|
### 手动安装单项
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
TOOLS=/opt/h200-test-tools
|
TOOLS=/opt/gpu-test-tools
|
||||||
|
|
||||||
# nvbandwidth
|
# nvbandwidth
|
||||||
git clone https://github.com/NVIDIA/nvbandwidth.git $TOOLS/nvbandwidth
|
git clone https://github.com/NVIDIA/nvbandwidth.git $TOOLS/nvbandwidth
|
||||||
@ -148,7 +148,7 @@ cd $TOOLS/gpu-burn && make
|
|||||||
### 交互式菜单(默认模式)
|
### 交互式菜单(默认模式)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 h200_tester.py
|
python3 gpu_tester.py
|
||||||
```
|
```
|
||||||
|
|
||||||
显示带编号的测试菜单,输入数字选择测试:
|
显示带编号的测试菜单,输入数字选择测试:
|
||||||
@ -171,25 +171,25 @@ python3 h200_tester.py
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 单项测试
|
# 单项测试
|
||||||
python3 h200_tester.py --test gpu-info
|
python3 gpu_tester.py --test gpu-info
|
||||||
python3 h200_tester.py --test health
|
python3 gpu_tester.py --test health
|
||||||
python3 h200_tester.py --test benchmark --type memory
|
python3 gpu_tester.py --test benchmark --type memory
|
||||||
python3 h200_tester.py --test benchmark --type compute --dtype bf16
|
python3 gpu_tester.py --test benchmark --type compute --dtype bf16
|
||||||
python3 h200_tester.py --test nccl
|
python3 gpu_tester.py --test nccl
|
||||||
python3 h200_tester.py --test stress
|
python3 gpu_tester.py --test stress
|
||||||
python3 h200_tester.py --test rdma
|
python3 gpu_tester.py --test rdma
|
||||||
python3 h200_tester.py --test training
|
python3 gpu_tester.py --test training
|
||||||
|
|
||||||
# 全量测试
|
# 全量测试
|
||||||
python3 h200_tester.py --test all
|
python3 gpu_tester.py --test all
|
||||||
|
|
||||||
# GPU 型号控制
|
# GPU 型号控制
|
||||||
python3 h200_tester.py --gpu-type auto --test all # 自动检测(默认)
|
python3 gpu_tester.py --gpu-type auto --test all # 自动检测(默认)
|
||||||
python3 h200_tester.py --gpu-type h200 --test all # 强制指定 H200
|
python3 gpu_tester.py --gpu-type h200 --test all # 强制指定 H200
|
||||||
python3 h200_tester.py --gpu-type b300 --test benchmark # 强制指定 B300
|
python3 gpu_tester.py --gpu-type b300 --test benchmark # 强制指定 B300
|
||||||
|
|
||||||
# 指定自定义配置
|
# 指定自定义配置
|
||||||
python3 h200_tester.py --config /path/to/config.yaml --test all
|
python3 gpu_tester.py --config /path/to/config.yaml --test all
|
||||||
```
|
```
|
||||||
|
|
||||||
### GPU 自动检测
|
### GPU 自动检测
|
||||||
@ -198,6 +198,8 @@ python3 h200_tester.py --config /path/to/config.yaml --test all
|
|||||||
|
|
||||||
| GPU 名称关键词 | 识别为 | 使用规格 |
|
| GPU 名称关键词 | 识别为 | 使用规格 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| `A100` | A100 SXM | Ampere, 80GB HBM2e, 2.0 TB/s |
|
||||||
|
| `A800` | A800 SXM | Ampere, 80GB HBM2e, 2.0 TB/s |
|
||||||
| `H100` | H100 SXM5 | Hopper, 80GB HBM3, 3.4 TB/s |
|
| `H100` | H100 SXM5 | Hopper, 80GB HBM3, 3.4 TB/s |
|
||||||
| `H200` | H200 SXM | Hopper, 141GB HBM3e, 4.8 TB/s |
|
| `H200` | H200 SXM | Hopper, 141GB HBM3e, 4.8 TB/s |
|
||||||
| `B200` | B200 SXM | Blackwell, 180GB HBM3e, 8 TB/s |
|
| `B200` | B200 SXM | Blackwell, 180GB HBM3e, 8 TB/s |
|
||||||
@ -221,12 +223,12 @@ python3 h200_tester.py --config /path/to/config.yaml --test all
|
|||||||
|
|
||||||
| 指标 | 说明 |
|
| 指标 | 说明 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 型号 | 自动检测并确认 GPU 型号(H100/H200/B200/B300) |
|
| 型号 | 自动检测并确认 GPU 型号(A100/A800/H100/H200/B200/B300) |
|
||||||
| VRAM | 总量 / 已用 / 空闲 |
|
| VRAM | 总量 / 已用 / 空闲 |
|
||||||
| 温度 | 实时温度 |
|
| 温度 | 实时温度 |
|
||||||
| 功耗 | 实时功耗 / 功耗上限 |
|
| 功耗 | 实时功耗 / 功耗上限 |
|
||||||
| 时钟频率 | SM 时钟 / 内存时钟 |
|
| 时钟频率 | SM 时钟 / 内存时钟 |
|
||||||
| PCIe | 链路代数和宽度(期望 Gen5 x16) |
|
| PCIe | 链路代数和宽度(Ampere: Gen4, Hopper/Blackwell: Gen5) |
|
||||||
| Persistence Mode | 应开启 |
|
| Persistence Mode | 应开启 |
|
||||||
| ECC 错误 | 单比特 / 双比特计数 |
|
| ECC 错误 | 单比特 / 双比特计数 |
|
||||||
| NVLink 拓扑 | 显示 `nvidia-smi topo -m` 输出 |
|
| NVLink 拓扑 | 显示 `nvidia-smi topo -m` 输出 |
|
||||||
@ -262,7 +264,7 @@ python3 h200_tester.py --config /path/to/config.yaml --test all
|
|||||||
- `device_to_device_memcpy_read_ce` — D2D 读带宽
|
- `device_to_device_memcpy_read_ce` — D2D 读带宽
|
||||||
- `device_to_device_bidirectional_sm` — D2D 双向带宽
|
- `device_to_device_bidirectional_sm` — D2D 双向带宽
|
||||||
|
|
||||||
**GPU 参考值(D2D 峰值带宽):** H100: 3,400 GB/s | H200: 4,800 GB/s | B200/B300: 8,000 GB/s
|
**GPU 参考值(D2D 峰值带宽):** A100/A800: 2,039 GB/s | H100: 3,400 GB/s | H200: 4,800 GB/s | B200/B300: 8,000 GB/s
|
||||||
|
|
||||||
**效率评级:** ≥ 80% 绿色, 50-80% 黄色, < 50% 红色
|
**效率评级:** ≥ 80% 绿色, 50-80% 黄色, < 50% 红色
|
||||||
|
|
||||||
@ -270,13 +272,13 @@ python3 h200_tester.py --config /path/to/config.yaml --test all
|
|||||||
|
|
||||||
使用 PyTorch matmul 测试各精度 GEMM 吞吐量。峰值 TFLOPS 根据 GPU 型号自动匹配。
|
使用 PyTorch matmul 测试各精度 GEMM 吞吐量。峰值 TFLOPS 根据 GPU 型号自动匹配。
|
||||||
|
|
||||||
| 精度 | H100/H200 峰值 | B200 峰值 | B300 峰值 |
|
| 精度 | A100/A800 峰值 | H100/H200 峰值 | B200 峰值 | B300 峰值 |
|
||||||
|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| FP32 | 67 TFLOPS | 90 TFLOPS | 125 TFLOPS |
|
| FP32 | 19.5 TFLOPS | 67 TFLOPS | 90 TFLOPS | 125 TFLOPS |
|
||||||
| TF32 | 495 TFLOPS | 1,125 TFLOPS | 1,750 TFLOPS |
|
| TF32 | 156 TFLOPS | 495 TFLOPS | 1,125 TFLOPS | 1,750 TFLOPS |
|
||||||
| FP16 | 990 TFLOPS | 2,250 TFLOPS | 3,500 TFLOPS |
|
| FP16 | 312 TFLOPS | 990 TFLOPS | 2,250 TFLOPS | 3,500 TFLOPS |
|
||||||
| BF16 | 990 TFLOPS | 2,250 TFLOPS | 3,500 TFLOPS |
|
| BF16 | 312 TFLOPS | 990 TFLOPS | 2,250 TFLOPS | 3,500 TFLOPS |
|
||||||
| FP8 | 1,979 TFLOPS | 4,500 TFLOPS | 7,000 TFLOPS |
|
| FP8 | N/A | 1,979 TFLOPS | 4,500 TFLOPS | 7,000 TFLOPS |
|
||||||
|
|
||||||
默认配置:4096×4096 矩阵,10 次 warmup,100 次迭代。
|
默认配置:4096×4096 矩阵,10 次 warmup,100 次迭代。
|
||||||
|
|
||||||
@ -295,7 +297,7 @@ python3 h200_tester.py --config /path/to/config.yaml --test all
|
|||||||
|
|
||||||
默认测试数据量范围 8B ~ 256MB,5 次 warmup,20 次迭代。
|
默认测试数据量范围 8B ~ 256MB,5 次 warmup,20 次迭代。
|
||||||
|
|
||||||
**NVLink 参考带宽:** H100/H200 ≥ 360 GB/s | B200/B300 ≥ 720 GB/s(40% NVLink 峰值)
|
**NVLink 参考带宽:** A100/A800 ≥ 240 GB/s | H100/H200 ≥ 360 GB/s | B200/B300 ≥ 720 GB/s(40% NVLink 峰值)
|
||||||
|
|
||||||
### 6. GPU Stress Test(压力测试)
|
### 6. GPU Stress Test(压力测试)
|
||||||
|
|
||||||
@ -338,11 +340,11 @@ python3 h200_tester.py --config /path/to/config.yaml --test all
|
|||||||
配置文件路径:`configs/default.yaml`
|
配置文件路径:`configs/default.yaml`
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# GPU type: auto-detect or override to h100/h200/b200/b300
|
# GPU type: auto-detect or override to a100/a800/h100/h200/b200/b300
|
||||||
gpu_type: auto
|
gpu_type: auto
|
||||||
|
|
||||||
tools:
|
tools:
|
||||||
install_dir: /opt/h200-test-tools # 三方工具安装目录
|
install_dir: /opt/gpu-test-tools # 三方工具安装目录
|
||||||
|
|
||||||
benchmark:
|
benchmark:
|
||||||
memory:
|
memory:
|
||||||
@ -392,7 +394,7 @@ report:
|
|||||||
|
|
||||||
### SOP-1: 新服务器到货验收
|
### SOP-1: 新服务器到货验收
|
||||||
|
|
||||||
**适用场景:** GPU 服务器首次上架,需要确认硬件完整可用。支持 H100/H200/B200/B300。
|
**适用场景:** GPU 服务器首次上架,需要确认硬件完整可用。支持 A100/A800/H100/H200/B200/B300。
|
||||||
|
|
||||||
```
|
```
|
||||||
步骤 1: 环境准备
|
步骤 1: 环境准备
|
||||||
@ -402,16 +404,16 @@ report:
|
|||||||
└── 确认所有工具安装成功
|
└── 确认所有工具安装成功
|
||||||
|
|
||||||
步骤 2: GPU 信息核对
|
步骤 2: GPU 信息核对
|
||||||
├── python3 h200_tester.py --test gpu-info
|
├── python3 gpu_tester.py --test gpu-info
|
||||||
├── 确认: 系统自动检测到 GPU 型号
|
├── 确认: 系统自动检测到 GPU 型号
|
||||||
├── 核对: GPU 数量是否与采购规格一致
|
├── 核对: GPU 数量是否与采购规格一致
|
||||||
├── 核对: 型号与预期一致(H100/H200/B200/B300)
|
├── 核对: 型号与预期一致(A100/A800/H100/H200/B200/B300)
|
||||||
├── 核对: VRAM 总量符合规格(H100: 80GB, H200: 141GB, B200: 180GB, B300: 288GB)
|
├── 核对: VRAM 总量符合规格(A100: 80GB, A800: 80GB, H100: 80GB, H200: 141GB, B200: 180GB, B300: 288GB)
|
||||||
├── 核对: PCIe Gen5 x16
|
├── 核对: PCIe 链路正常(Ampere Gen4 x16, Hopper/Blackwell Gen5 x16)
|
||||||
└── 核对: NVLink 拓扑显示正确
|
└── 核对: NVLink 拓扑显示正确
|
||||||
|
|
||||||
步骤 3: 健康诊断
|
步骤 3: 健康诊断
|
||||||
├── python3 h200_tester.py --test health
|
├── python3 gpu_tester.py --test health
|
||||||
├── 确认: 所有检查项 PASS
|
├── 确认: 所有检查项 PASS
|
||||||
├── 重点关注: ECC 双比特错误 = 0
|
├── 重点关注: ECC 双比特错误 = 0
|
||||||
├── 重点关注: 温度 < 80°C(空载)
|
├── 重点关注: 温度 < 80°C(空载)
|
||||||
@ -419,29 +421,29 @@ report:
|
|||||||
└── 如有 WARN/FAIL: 记录问题,联系供应商
|
└── 如有 WARN/FAIL: 记录问题,联系供应商
|
||||||
|
|
||||||
步骤 4: 内存带宽基准
|
步骤 4: 内存带宽基准
|
||||||
├── python3 h200_tester.py --test benchmark --type memory
|
├── python3 gpu_tester.py --test benchmark --type memory
|
||||||
├── 确认: D2D 带宽效率 ≥ 90%(自动与 GPU 峰值对比)
|
├── 确认: D2D 带宽效率 ≥ 90%(自动与 GPU 峰值对比)
|
||||||
└── 低于 80%: 检查散热/ECC/固件版本
|
└── 低于 80%: 检查散热/ECC/固件版本
|
||||||
|
|
||||||
步骤 5: 计算吞吐基准
|
步骤 5: 计算吞吐基准
|
||||||
├── python3 h200_tester.py --test benchmark --type compute
|
├── python3 gpu_tester.py --test benchmark --type compute
|
||||||
├── 确认: 各精度 TFLOPS ≥ 峰值的 80%(自动与 GPU 规格对比)
|
├── 确认: 各精度 TFLOPS ≥ 峰值的 80%(自动与 GPU 规格对比)
|
||||||
└── 异常低: 检查功耗限制、时钟频率、驱动版本
|
└── 异常低: 检查功耗限制、时钟频率、驱动版本
|
||||||
|
|
||||||
步骤 6: NCCL 多卡通信
|
步骤 6: NCCL 多卡通信
|
||||||
├── python3 h200_tester.py --test nccl
|
├── python3 gpu_tester.py --test nccl
|
||||||
├── 确认: AllReduce/AllToAll bus bandwidth ≥ 最低阈值(自动根据 NVLink 带宽计算)
|
├── 确认: AllReduce/AllToAll bus bandwidth ≥ 最低阈值(自动根据 NVLink 带宽计算)
|
||||||
└── 异常低: 检查 NVLink 连接、NVSwitch 状态
|
└── 异常低: 检查 NVLink 连接、NVSwitch 状态
|
||||||
|
|
||||||
步骤 7: 压力稳定性
|
步骤 7: 压力稳定性
|
||||||
├── 修改 configs/default.yaml: stress.duration_sec = 600(10分钟)
|
├── 修改 configs/default.yaml: stress.duration_sec = 600(10分钟)
|
||||||
├── python3 h200_tester.py --test stress
|
├── python3 gpu_tester.py --test stress
|
||||||
├── 确认: 所有 GPU PASS
|
├── 确认: 所有 GPU PASS
|
||||||
├── 测试期间观察: 温度不超 90°C
|
├── 测试期间观察: 温度不超 90°C
|
||||||
└── 测试期间观察: 无 ECC 错误增长
|
└── 测试期间观察: 无 ECC 错误增长
|
||||||
|
|
||||||
步骤 8: 生成验收报告
|
步骤 8: 生成验收报告
|
||||||
├── python3 h200_tester.py --test all
|
├── python3 gpu_tester.py --test all
|
||||||
├── 检查 reports/ 目录下的报告文件
|
├── 检查 reports/ 目录下的报告文件
|
||||||
└── 保存报告作为验收依据
|
└── 保存报告作为验收依据
|
||||||
```
|
```
|
||||||
@ -463,7 +465,7 @@ report:
|
|||||||
频率: 每周一次 或 维护窗口
|
频率: 每周一次 或 维护窗口
|
||||||
|
|
||||||
步骤:
|
步骤:
|
||||||
1. python3 h200_tester.py --test health
|
1. python3 gpu_tester.py --test health
|
||||||
2. 重点关注:
|
2. 重点关注:
|
||||||
- ECC 错误是否增长
|
- ECC 错误是否增长
|
||||||
- 温度是否异常升高
|
- 温度是否异常升高
|
||||||
@ -489,7 +491,7 @@ report:
|
|||||||
└── 确保所有单节点测试通过
|
└── 确保所有单节点测试通过
|
||||||
|
|
||||||
步骤 2: RDMA 网络测试
|
步骤 2: RDMA 网络测试
|
||||||
├── python3 h200_tester.py --test rdma
|
├── python3 gpu_tester.py --test rdma
|
||||||
├── 确认: IB 设备被识别
|
├── 确认: IB 设备被识别
|
||||||
├── 确认: 端口状态 Active
|
├── 确认: 端口状态 Active
|
||||||
├── 确认: 写带宽 ≥ 50 GB/s
|
├── 确认: 写带宽 ≥ 50 GB/s
|
||||||
@ -504,12 +506,12 @@ report:
|
|||||||
│ export NCCL_DEBUG=INFO
|
│ export NCCL_DEBUG=INFO
|
||||||
├── 运行 nccl-tests 手动测试:
|
├── 运行 nccl-tests 手动测试:
|
||||||
│ mpirun -np <总GPU数> -hostfile hosts \
|
│ mpirun -np <总GPU数> -hostfile hosts \
|
||||||
│ /opt/h200-test-tools/nccl-tests/build/all_reduce_perf \
|
│ /opt/gpu-test-tools/nccl-tests/build/all_reduce_perf \
|
||||||
│ -b 8 -e 256M -f 2 -g 1 -w 5 -n 20
|
│ -b 8 -e 256M -f 2 -g 1 -w 5 -n 20
|
||||||
└── 确认: 多节点 AllReduce 带宽正常
|
└── 确认: 多节点 AllReduce 带宽正常
|
||||||
|
|
||||||
步骤 4: 训练验证
|
步骤 4: 训练验证
|
||||||
├── python3 h200_tester.py --test training
|
├── python3 gpu_tester.py --test training
|
||||||
├── 可选: 加载更大模型(如 llama 模型)
|
├── 可选: 加载更大模型(如 llama 模型)
|
||||||
└── 确认: 训练 loss 正常下降
|
└── 确认: 训练 loss 正常下降
|
||||||
```
|
```
|
||||||
@ -522,29 +524,29 @@ report:
|
|||||||
|
|
||||||
```
|
```
|
||||||
步骤 1: 快速诊断
|
步骤 1: 快速诊断
|
||||||
├── python3 h200_tester.py --test health
|
├── python3 gpu_tester.py --test health
|
||||||
├── python3 h200_tester.py --test gpu-info
|
├── python3 gpu_tester.py --test gpu-info
|
||||||
└── 记录所有 WARN/FAIL 项
|
└── 记录所有 WARN/FAIL 项
|
||||||
|
|
||||||
步骤 2: 定位故障 GPU
|
步骤 2: 定位故障 GPU
|
||||||
├── 检查 nvidia-smi 输出
|
├── 检查 nvidia-smi 输出
|
||||||
├── 关注: 温度、ECC、功耗异常的 GPU
|
├── 关注: 温度、ECC、功耗异常的 GPU
|
||||||
└── 对故障 GPU 执行:
|
└── 对故障 GPU 执行:
|
||||||
python3 h200_tester.py --test stress
|
python3 gpu_tester.py --test stress
|
||||||
(stress.gpus 设为故障 GPU 编号)
|
(stress.gpus 设为故障 GPU 编号)
|
||||||
|
|
||||||
步骤 3: 通信排查
|
步骤 3: 通信排查
|
||||||
├── python3 h200_tester.py --test nccl
|
├── python3 gpu_tester.py --test nccl
|
||||||
├── 如果 AllReduce 带宽异常低:
|
├── 如果 AllReduce 带宽异常低:
|
||||||
│ - 检查 NVLink 连接: nvidia-smi nvlink -s
|
│ - 检查 NVLink 连接: nvidia-smi nvlink -s
|
||||||
│ - 检查 NVSwitch: nvidia-smi nvswitch -a
|
│ - 检查 NVSwitch: nvidia-smi nvswitch -a
|
||||||
│ - 重置 GPU: nvidia-smi -i <id> -r
|
│ - 重置 GPU: nvidia-smi -i <id> -r
|
||||||
└── 如果多节点异常:
|
└── 如果多节点异常:
|
||||||
python3 h200_tester.py --test rdma
|
python3 gpu_tester.py --test rdma
|
||||||
|
|
||||||
步骤 4: 固件/驱动排查
|
步骤 4: 固件/驱动排查
|
||||||
├── nvidia-smi -q | head -20 (查看驱动/CUDA 版本)
|
├── nvidia-smi -q | head -20 (查看驱动/CUDA 版本)
|
||||||
├── 确认驱动版本满足要求(Hopper ≥ 535, Blackwell ≥ 550)
|
├── 确认驱动版本满足要求(Ampere ≥ 470, Hopper ≥ 535, Blackwell ≥ 550)
|
||||||
├── 确认固件版本与集群一致
|
├── 确认固件版本与集群一致
|
||||||
└── 必要时更新: apt upgrade nvidia-driver-*
|
└── 必要时更新: apt upgrade nvidia-driver-*
|
||||||
```
|
```
|
||||||
@ -560,12 +562,12 @@ report:
|
|||||||
|
|
||||||
步骤:
|
步骤:
|
||||||
1. 变更前运行全量测试,保存基线报告:
|
1. 变更前运行全量测试,保存基线报告:
|
||||||
python3 h200_tester.py --test all
|
python3 gpu_tester.py --test all
|
||||||
|
|
||||||
2. 执行变更(驱动升级/固件更新等)
|
2. 执行变更(驱动升级/固件更新等)
|
||||||
|
|
||||||
3. 变更后再次运行:
|
3. 变更后再次运行:
|
||||||
python3 h200_tester.py --test all
|
python3 gpu_tester.py --test all
|
||||||
|
|
||||||
4. 对比两份报告:
|
4. 对比两份报告:
|
||||||
- 内存带宽偏差 < 5%
|
- 内存带宽偏差 < 5%
|
||||||
@ -587,7 +589,7 @@ report:
|
|||||||
### JSON 格式
|
### JSON 格式
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 h200_tester.py --test all
|
python3 gpu_tester.py --test all
|
||||||
# 报告位置: ./reports/gpu_report_<timestamp>.json
|
# 报告位置: ./reports/gpu_report_<timestamp>.json
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -596,7 +598,7 @@ python3 h200_tester.py --test all
|
|||||||
### HTML 格式
|
### HTML 格式
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 h200_tester.py --test all --format html --output report.html
|
python3 gpu_tester.py --test all --format html --output report.html
|
||||||
```
|
```
|
||||||
|
|
||||||
生成深色主题的可视化报告,包含:
|
生成深色主题的可视化报告,包含:
|
||||||
@ -612,7 +614,7 @@ python3 h200_tester.py --test all --format html --output report.html
|
|||||||
|
|
||||||
| 问题 | 原因 | 解决方案 |
|
| 问题 | 原因 | 解决方案 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `nvidia-smi not found` | 驱动未安装 | 安装 NVIDIA 驱动(Hopper ≥ 535, Blackwell ≥ 550) |
|
| `nvidia-smi not found` | 驱动未安装 | 安装 NVIDIA 驱动(Ampere ≥ 470, Hopper ≥ 535, Blackwell ≥ 550) |
|
||||||
| `nvbandwidth not found` | 未编译安装 | 运行 `install_deps.sh` 或手动编译 |
|
| `nvbandwidth not found` | 未编译安装 | 运行 `install_deps.sh` 或手动编译 |
|
||||||
| `nccl-tests not found` | 未编译安装 | 运行 `install_deps.sh`,确认 CUDA_HOME 正确 |
|
| `nccl-tests not found` | 未编译安装 | 运行 `install_deps.sh`,确认 CUDA_HOME 正确 |
|
||||||
| `mpirun not found` | MPI 未安装 | `apt install openmpi-bin libopenmpi-dev` |
|
| `mpirun not found` | MPI 未安装 | `apt install openmpi-bin libopenmpi-dev` |
|
||||||
@ -631,18 +633,18 @@ python3 h200_tester.py --test all --format html --output report.html
|
|||||||
|
|
||||||
系统自动检测 GPU 型号,以下为各型号参考规格(dense TFLOPS):
|
系统自动检测 GPU 型号,以下为各型号参考规格(dense TFLOPS):
|
||||||
|
|
||||||
| 参数 | H100 SXM5 | H200 SXM | B200 SXM | B300 SXM |
|
| 参数 | A100 SXM | A800 SXM | H100 SXM5 | H200 SXM | B200 SXM | B300 SXM |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|---|---|
|
||||||
| 架构 | Hopper | Hopper | Blackwell | Blackwell Ultra |
|
| 架构 | Ampere | Ampere | Hopper | Hopper | Blackwell | Blackwell Ultra |
|
||||||
| 计算能力 | 9.0 | 9.0 | 10.0 | 10.0 |
|
| 计算能力 | 8.0 | 8.0 | 9.0 | 9.0 | 10.0 | 10.0 |
|
||||||
| HBM 容量 | 80 GB (HBM3) | 141 GB (HBM3e) | 180 GB (HBM3e) | 288 GB (HBM3e) |
|
| HBM 容量 | 80 GB (HBM2e) | 80 GB (HBM2e) | 80 GB (HBM3) | 141 GB (HBM3e) | 180 GB (HBM3e) | 288 GB (HBM3e) |
|
||||||
| 内存带宽 | 3,400 GB/s | 4,800 GB/s | 8,000 GB/s | 8,000 GB/s |
|
| 内存带宽 | 2,039 GB/s | 2,039 GB/s | 3,400 GB/s | 4,800 GB/s | 8,000 GB/s | 8,000 GB/s |
|
||||||
| TDP | 700W | 700W | 1,000W | 1,200W |
|
| TDP | 400W | 400W | 700W | 700W | 1,000W | 1,200W |
|
||||||
| FP32 | 67 TFLOPS | 67 TFLOPS | 90 TFLOPS | 125 TFLOPS |
|
| FP32 | 19.5 TFLOPS | 19.5 TFLOPS | 67 TFLOPS | 67 TFLOPS | 90 TFLOPS | 125 TFLOPS |
|
||||||
| TF32 (dense) | 495 TFLOPS | 495 TFLOPS | 1,125 TFLOPS | 1,750 TFLOPS |
|
| TF32 (dense) | 156 TFLOPS | 156 TFLOPS | 495 TFLOPS | 495 TFLOPS | 1,125 TFLOPS | 1,750 TFLOPS |
|
||||||
| FP16/BF16 (dense) | 990 TFLOPS | 990 TFLOPS | 2,250 TFLOPS | 3,500 TFLOPS |
|
| FP16/BF16 (dense) | 312 TFLOPS | 312 TFLOPS | 990 TFLOPS | 990 TFLOPS | 2,250 TFLOPS | 3,500 TFLOPS |
|
||||||
| FP8 (dense) | 1,979 TFLOPS | 1,979 TFLOPS | 4,500 TFLOPS | 7,000 TFLOPS |
|
| FP8 (dense) | N/A | N/A | 1,979 TFLOPS | 1,979 TFLOPS | 4,500 TFLOPS | 7,000 TFLOPS |
|
||||||
| NVLink | 第 4 代, 900 GB/s | 第 4 代, 900 GB/s | 第 5 代, 1,800 GB/s | 第 5 代, 1,800 GB/s |
|
| NVLink | 第 3 代, 600 GB/s | 第 3 代, 600 GB/s | 第 4 代, 900 GB/s | 第 4 代, 900 GB/s | 第 5 代, 1,800 GB/s | 第 5 代, 1,800 GB/s |
|
||||||
| PCIe | Gen5 x16 | Gen5 x16 | Gen5 x16 | Gen5 x16 |
|
| PCIe | Gen4 x16 | Gen4 x16 | Gen5 x16 | Gen5 x16 | Gen5 x16 | Gen5 x16 |
|
||||||
| 最低驱动 | 535 | 535 | 550 | 550 |
|
| 最低驱动 | 470 | 470 | 535 | 535 | 550 | 550 |
|
||||||
| 最低 CUDA | 12.1 | 12.1 | 12.4 | 12.4 |
|
| 最低 CUDA | 11.0 | 11.0 | 12.1 | 12.1 | 12.4 | 12.4 |
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# GPU type: auto-detect or override to h100/h200/b200/b300
|
# GPU type: auto-detect or override to a100/a800/h100/h200/b200/b300
|
||||||
gpu_type: auto
|
gpu_type: auto
|
||||||
|
|
||||||
benchmark:
|
benchmark:
|
||||||
@ -21,7 +21,7 @@ benchmark:
|
|||||||
health:
|
health:
|
||||||
temp_warning: 80
|
temp_warning: 80
|
||||||
temp_critical: 90
|
temp_critical: 90
|
||||||
power_limit: null # null = auto-detect from GPU TDP (H100/H200: 700W, B200: 1000W, B300: 1200W)
|
power_limit: null # null = auto-detect from GPU TDP per gpu_specs.py
|
||||||
|
|
||||||
nccl:
|
nccl:
|
||||||
min_bandwidth_gbps: null # null = auto-detect (40% of GPU NVLink BW)
|
min_bandwidth_gbps: null # null = auto-detect (40% of GPU NVLink BW)
|
||||||
@ -59,4 +59,4 @@ report:
|
|||||||
format: json
|
format: json
|
||||||
|
|
||||||
tools:
|
tools:
|
||||||
install_dir: /opt/h200-test-tools
|
install_dir: /opt/gpu-test-tools
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""GPU Training Server Test Suite (H100/H200/B200/B300) - Main CLI Entry Point."""
|
"""GPU Training Server Test Suite (A100/A800/H100/H200/B200/B300) - Main CLI Entry Point."""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
@ -26,7 +26,7 @@ from modules.training_sim import TrainingSim
|
|||||||
from modules.stress_test import StressTest
|
from modules.stress_test import StressTest
|
||||||
from modules.rdma_test import RDMATest
|
from modules.rdma_test import RDMATest
|
||||||
from modules.report import ReportGenerator
|
from modules.report import ReportGenerator
|
||||||
from modules.gpu_specs import detect_gpu_type, get_gpu_specs, get_gpu_label, get_supported_gpus
|
from modules.gpu_specs import detect_gpu_type, get_gpu_specs, get_gpu_label, get_supported_gpus, validate_driver_compatibility
|
||||||
|
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
"benchmark": {
|
"benchmark": {
|
||||||
@ -71,18 +71,18 @@ DEFAULT_CONFIG = {
|
|||||||
"dtype": "bf16",
|
"dtype": "bf16",
|
||||||
},
|
},
|
||||||
"report": {"output_dir": "./reports", "format": "json"},
|
"report": {"output_dir": "./reports", "format": "json"},
|
||||||
"tools": {"install_dir": "/opt/h200-test-tools"},
|
"tools": {"install_dir": "/opt/gpu-test-tools"},
|
||||||
}
|
}
|
||||||
|
|
||||||
BANNER = r"""
|
BANNER = r"""
|
||||||
[bold cyan]
|
[bold cyan]
|
||||||
╔══════════════════════════════════════════════════╗
|
╔══════════════════════════════════════════════════════╗
|
||||||
║ ║
|
║ ║
|
||||||
║ GPU Training Server Test Suite ║
|
║ GPU Training Server Test Suite ║
|
||||||
║ Diagnostics & Benchmarking Tool ║
|
║ Diagnostics & Benchmarking Tool ║
|
||||||
║ Supports: H100 / H200 / B200 / B300 ║
|
║ Supports: A100 / A800 / H100 / H200 / B200 / B300 ║
|
||||||
║ ║
|
║ ║
|
||||||
╚══════════════════════════════════════════════════╝
|
╚══════════════════════════════════════════════════════════╝
|
||||||
[/bold cyan]
|
[/bold cyan]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -121,6 +121,11 @@ def interactive_menu(config: dict):
|
|||||||
else:
|
else:
|
||||||
console.print("[yellow]GPU type could not be auto-detected. Using default thresholds.[/yellow]\n")
|
console.print("[yellow]GPU type could not be auto-detected. Using default thresholds.[/yellow]\n")
|
||||||
|
|
||||||
|
# Driver / CUDA compatibility check
|
||||||
|
compat_warnings = validate_driver_compatibility(gpu_type)
|
||||||
|
for w in compat_warnings:
|
||||||
|
console.print(f"[bold yellow]\u26a0 {w}[/bold yellow]")
|
||||||
|
|
||||||
if not check_prerequisites(console):
|
if not check_prerequisites(console):
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -314,20 +319,20 @@ def _run_full_suite(config: dict, console: Console) -> dict:
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="GPU Training Server Test Suite (H100/H200/B200/B300)",
|
description="GPU Training Server Test Suite (A100/A800/H100/H200/B200/B300)",
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
epilog="""
|
epilog="""
|
||||||
Examples:
|
Examples:
|
||||||
python h200_tester.py # Interactive menu
|
python gpu_tester.py # Interactive menu
|
||||||
python h200_tester.py --gpu-type h200 # Override GPU type
|
python gpu_tester.py --gpu-type a800 # Override GPU type
|
||||||
python h200_tester.py --test gpu-info # GPU info
|
python gpu_tester.py --test gpu-info # GPU info
|
||||||
python h200_tester.py --test health # Health check
|
python gpu_tester.py --test health # Health check
|
||||||
python h200_tester.py --test benchmark --type memory
|
python gpu_tester.py --test benchmark --type memory
|
||||||
python h200_tester.py --test benchmark --type compute --dtype fp16
|
python gpu_tester.py --test benchmark --type compute --dtype fp16
|
||||||
python h200_tester.py --test nccl # NCCL test
|
python gpu_tester.py --test nccl # NCCL test
|
||||||
python h200_tester.py --test training # Training sim
|
python gpu_tester.py --test training # Training sim
|
||||||
python h200_tester.py --test all # Full suite
|
python gpu_tester.py --test all # Full suite
|
||||||
python h200_tester.py --report --format json --output report.json
|
python gpu_tester.py --report --format json --output report.json
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
parser.add_argument("--test", choices=["gpu-info", "health", "benchmark", "nccl", "stress", "rdma", "training", "all"],
|
parser.add_argument("--test", choices=["gpu-info", "health", "benchmark", "nccl", "stress", "rdma", "training", "all"],
|
||||||
@ -337,11 +342,15 @@ Examples:
|
|||||||
help="Compute benchmark dtype (with --test benchmark --type compute)")
|
help="Compute benchmark dtype (with --test benchmark --type compute)")
|
||||||
parser.add_argument("--interactive", action="store_true", help="Force interactive mode")
|
parser.add_argument("--interactive", action="store_true", help="Force interactive mode")
|
||||||
parser.add_argument("--report", action="store_true", help="Generate report from last results")
|
parser.add_argument("--report", action="store_true", help="Generate report from last results")
|
||||||
parser.add_argument("--format", choices=["json", "html"], default="json", help="Report format")
|
parser.add_argument("--format", choices=["json", "html", "md"], default="json", help="Report format")
|
||||||
parser.add_argument("--output", default=None, help="Report output file path")
|
parser.add_argument("--output", default=None, help="Report output file path")
|
||||||
parser.add_argument("--config", default=None, help="Path to config YAML file")
|
parser.add_argument("--config", default=None, help="Path to config YAML file")
|
||||||
parser.add_argument("--gpu-type", choices=["auto", "h100", "h200", "b200", "b300"],
|
parser.add_argument(
|
||||||
default="auto", help="Override GPU type detection")
|
"--gpu-type",
|
||||||
|
choices=["auto", "a100", "a800", "h100", "h200", "b200", "b300"],
|
||||||
|
default="auto",
|
||||||
|
help="Override GPU type detection",
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
config = load_config()
|
config = load_config()
|
||||||
@ -359,6 +368,11 @@ Examples:
|
|||||||
|
|
||||||
console = Console()
|
console = Console()
|
||||||
|
|
||||||
|
# Driver / CUDA compatibility check
|
||||||
|
compat_warnings = validate_driver_compatibility(config["gpu_type"])
|
||||||
|
for w in compat_warnings:
|
||||||
|
console.print(f"[bold yellow]\u26a0 {w}[/bold yellow]")
|
||||||
|
|
||||||
# Handle --report standalone
|
# Handle --report standalone
|
||||||
if args.report and not args.test:
|
if args.report and not args.test:
|
||||||
console.print("[yellow]Run tests first to generate a report.[/yellow]")
|
console.print("[yellow]Run tests first to generate a report.[/yellow]")
|
||||||
@ -396,17 +410,19 @@ Examples:
|
|||||||
result = bench.run()
|
result = bench.run()
|
||||||
Benchmark.print_results(result)
|
Benchmark.print_results(result)
|
||||||
if args.report:
|
if args.report:
|
||||||
ReportGenerator(config).generate({"benchmark": result, "timestamp": datetime.now().isoformat()})
|
ReportGenerator(config).generate({"benchmark": result, "timestamp": datetime.now().isoformat()},
|
||||||
|
fmt=args.format, output=args.output)
|
||||||
elif args.test == "all":
|
elif args.test == "all":
|
||||||
results = _run_full_suite(config, console)
|
results = _run_full_suite(config, console)
|
||||||
if args.report:
|
if args.report:
|
||||||
ReportGenerator(config).generate(results)
|
ReportGenerator(config).generate(results, fmt=args.format, output=args.output)
|
||||||
has_errors = any("error" in v for v in results.values() if isinstance(v, dict))
|
has_errors = any("error" in v for v in results.values() if isinstance(v, dict))
|
||||||
sys.exit(1 if has_errors else 0)
|
sys.exit(1 if has_errors else 0)
|
||||||
else:
|
else:
|
||||||
result = _run_test(test_map[args.test], config, console)
|
result = _run_test(test_map[args.test], config, console)
|
||||||
if args.report and result:
|
if args.report and result:
|
||||||
ReportGenerator(config).generate({args.test: result, "timestamp": datetime.now().isoformat()})
|
ReportGenerator(config).generate({args.test: result, "timestamp": datetime.now().isoformat()},
|
||||||
|
fmt=args.format, output=args.output)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
INSTALL_DIR="${GPU_TOOLS_DIR:-${H200_TOOLS_DIR:-/opt/h200-test-tools}}"
|
INSTALL_DIR="${GPU_TOOLS_DIR:-/opt/gpu-test-tools}"
|
||||||
JOBS="${MAKE_JOBS:-$(nproc)}"
|
JOBS="${MAKE_JOBS:-$(nproc)}"
|
||||||
VERBOSE="${VERBOSE:-0}"
|
VERBOSE="${VERBOSE:-0}"
|
||||||
|
|
||||||
@ -203,8 +203,8 @@ print_summary() {
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " Usage:"
|
echo " Usage:"
|
||||||
echo " python3 h200_tester.py # Interactive menu"
|
echo " python3 gpu_tester.py # Interactive menu"
|
||||||
echo " python3 h200_tester.py --test all # Full suite"
|
echo " python3 gpu_tester.py --test all # Full suite"
|
||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
"""GPU benchmark module — nvbandwidth + PyTorch compute throughput."""
|
"""GPU benchmark module — nvbandwidth + PyTorch compute throughput."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
@ -11,7 +12,7 @@ from rich.console import Console
|
|||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn, TimeElapsedColumn
|
from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn, TimeElapsedColumn
|
||||||
|
|
||||||
from modules.gpu_specs import detect_gpu_type, get_gpu_specs, get_gpu_label
|
from modules.gpu_specs import detect_gpu_type, get_gpu_specs, get_gpu_label, resolve_tools_dir
|
||||||
|
|
||||||
TORCH_AVAILABLE = False
|
TORCH_AVAILABLE = False
|
||||||
try:
|
try:
|
||||||
@ -28,7 +29,7 @@ class Benchmark:
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.console = Console()
|
self.console = Console()
|
||||||
self.bench_cfg = config.get("benchmark", {})
|
self.bench_cfg = config.get("benchmark", {})
|
||||||
self.tools_dir = config.get("tools", {}).get("install_dir", "/opt/h200-test-tools")
|
self.tools_dir = resolve_tools_dir(config)
|
||||||
self.gpu_type = detect_gpu_type()
|
self.gpu_type = detect_gpu_type()
|
||||||
self.specs = get_gpu_specs(self.gpu_type)
|
self.specs = get_gpu_specs(self.gpu_type)
|
||||||
self.gpu_label = get_gpu_label(self.gpu_type)
|
self.gpu_label = get_gpu_label(self.gpu_type)
|
||||||
@ -40,12 +41,24 @@ class Benchmark:
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
def _find_nvbandwidth(self) -> Optional[str]:
|
def _find_nvbandwidth(self) -> Optional[str]:
|
||||||
|
# 1. System PATH
|
||||||
p = shutil.which("nvbandwidth")
|
p = shutil.which("nvbandwidth")
|
||||||
if p:
|
if p:
|
||||||
return p
|
return p
|
||||||
local = shutil.os.path.join(self.tools_dir, "nvbandwidth", "nvbandwidth")
|
# 2. tools_dir
|
||||||
if shutil.os.path.isfile(local) and shutil.os.access(local, shutil.os.X_OK):
|
local = os.path.join(self.tools_dir, "nvbandwidth", "nvbandwidth")
|
||||||
|
if os.path.isfile(local) and os.access(local, os.X_OK):
|
||||||
return local
|
return local
|
||||||
|
# 3. Common DCGM / system locations
|
||||||
|
extra_paths = [
|
||||||
|
"/usr/libexec/datacenter-gpu-manager-4/plugins/cuda12/nvbandwidth",
|
||||||
|
"/usr/libexec/datacenter-gpu-manager/plugins/cuda12/nvbandwidth",
|
||||||
|
"/usr/local/bin/nvbandwidth",
|
||||||
|
"/opt/nvidia/nvbandwidth/nvbandwidth",
|
||||||
|
]
|
||||||
|
for ep in extra_paths:
|
||||||
|
if os.path.isfile(ep) and os.access(ep, os.X_OK):
|
||||||
|
return ep
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def run_memory_benchmark(self) -> dict:
|
def run_memory_benchmark(self) -> dict:
|
||||||
@ -140,7 +153,10 @@ class Benchmark:
|
|||||||
)
|
)
|
||||||
h2d_bw = results_by_test.get("host_to_device_memcpy_read_ce", 0)
|
h2d_bw = results_by_test.get("host_to_device_memcpy_read_ce", 0)
|
||||||
d2h_bw = results_by_test.get("device_to_host_memcpy_write_ce", 0)
|
d2h_bw = results_by_test.get("device_to_host_memcpy_write_ce", 0)
|
||||||
efficiency = (d2d_bw / self.specs["memory_bandwidth_gbps"]) * 100 if d2d_bw else 0
|
peak_bw = self.specs["memory_bandwidth_gbps"]
|
||||||
|
efficiency = (
|
||||||
|
(d2d_bw / peak_bw) * 100 if (d2d_bw and peak_bw) else 0
|
||||||
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"memory": {
|
"memory": {
|
||||||
@ -216,7 +232,8 @@ class Benchmark:
|
|||||||
progress.advance(task)
|
progress.advance(task)
|
||||||
|
|
||||||
best_d2d = max(v["d2d_gbps"] for v in bandwidth_by_size.values())
|
best_d2d = max(v["d2d_gbps"] for v in bandwidth_by_size.values())
|
||||||
efficiency = (best_d2d / self.specs["memory_bandwidth_gbps"]) * 100
|
peak_bw = self.specs["memory_bandwidth_gbps"]
|
||||||
|
efficiency = (best_d2d / peak_bw) * 100 if peak_bw else 0.0
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"memory": {
|
"memory": {
|
||||||
@ -269,6 +286,14 @@ class Benchmark:
|
|||||||
progress.advance(task)
|
progress.advance(task)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Skip FP8 if GPU architecture doesn't support it
|
||||||
|
if dtype_name == "fp8" and self.specs.get("fp8_tflops", 0) == 0:
|
||||||
|
arch = self.specs.get("architecture", "unknown")
|
||||||
|
results_by_dtype["fp8"] = f"skipped ({arch} does not support FP8)"
|
||||||
|
self.console.print(f"[dim] fp8: skipped - {arch} architecture has no FP8 support[/dim]")
|
||||||
|
progress.advance(task)
|
||||||
|
continue
|
||||||
|
|
||||||
dtype_val, peak_tflops = dtype_map[dtype_name]
|
dtype_val, peak_tflops = dtype_map[dtype_name]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -321,7 +346,9 @@ class Benchmark:
|
|||||||
efficiency = {}
|
efficiency = {}
|
||||||
for dt, achieved in results_by_dtype.items():
|
for dt, achieved in results_by_dtype.items():
|
||||||
if isinstance(achieved, (int, float)) and dt in dtype_map:
|
if isinstance(achieved, (int, float)) and dt in dtype_map:
|
||||||
efficiency[dt] = round((achieved / dtype_map[dt][1]) * 100, 1)
|
peak_tp = dtype_map[dt][1]
|
||||||
|
if peak_tp:
|
||||||
|
efficiency[dt] = round((achieved / peak_tp) * 100, 1)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"compute": {
|
"compute": {
|
||||||
@ -382,10 +409,13 @@ class Benchmark:
|
|||||||
t2.add_column("D2D (GB/s)", justify="right")
|
t2.add_column("D2D (GB/s)", justify="right")
|
||||||
for sz, vals in sorted(by_size.items(), key=lambda x: int(x[0])):
|
for sz, vals in sorted(by_size.items(), key=lambda x: int(x[0])):
|
||||||
peak = mem["peak_bandwidth_gbps"]
|
peak = mem["peak_bandwidth_gbps"]
|
||||||
|
if peak:
|
||||||
d2d_eff = (vals["d2d_gbps"] / peak) * 100
|
d2d_eff = (vals["d2d_gbps"] / peak) * 100
|
||||||
ec = "green" if d2d_eff >= 80 else ("yellow" if d2d_eff >= 50 else "red")
|
ec = "green" if d2d_eff >= 80 else ("yellow" if d2d_eff >= 50 else "red")
|
||||||
t2.add_row(sz, f"{vals['h2d_gbps']:.1f}", f"{vals['d2h_gbps']:.1f}",
|
d2d_cell = f"[{ec}]{vals['d2d_gbps']:.1f}[/{ec}]"
|
||||||
f"[{ec}]{vals['d2d_gbps']:.1f}[/{ec}]")
|
else:
|
||||||
|
d2d_cell = f"{vals['d2d_gbps']:.1f}"
|
||||||
|
t2.add_row(sz, f"{vals['h2d_gbps']:.1f}", f"{vals['d2h_gbps']:.1f}", d2d_cell)
|
||||||
c.print(t2)
|
c.print(t2)
|
||||||
|
|
||||||
if "compute" in results and "error" not in results["compute"]:
|
if "compute" in results and "error" not in results["compute"]:
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
"""GPU information detection module for NVIDIA datacenter GPUs (H100/H200/B200/B300)."""
|
"""GPU information detection module for NVIDIA datacenter GPUs (A100/A800/H100/H200/B200/B300)."""
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
@ -48,8 +48,8 @@ class GPUInfo:
|
|||||||
names = self._run_smi("name").split("\n") if self._run_smi("name") else []
|
names = self._run_smi("name").split("\n") if self._run_smi("name") else []
|
||||||
uuids = self._run_smi("uuid").split("\n") if self._run_smi("uuid") else []
|
uuids = self._run_smi("uuid").split("\n") if self._run_smi("uuid") else []
|
||||||
pcie_bus = self._run_smi("pci.bus_id").split("\n") if self._run_smi("pci.bus_id") else []
|
pcie_bus = self._run_smi("pci.bus_id").split("\n") if self._run_smi("pci.bus_id") else []
|
||||||
pcie_gen = self._run_smi("pcie_link.gen").split("\n") if self._run_smi("pcie_link.gen") else []
|
pcie_gen = self._run_smi("pcie.link.gen.current").split("\n") if self._run_smi("pcie.link.gen.current") else []
|
||||||
pcie_width = self._run_smi("pcie_link.width").split("\n") if self._run_smi("pcie_link.width") else []
|
pcie_width = self._run_smi("pcie.link.width.current").split("\n") if self._run_smi("pcie.link.width.current") else []
|
||||||
vram_total = self._run_smi("memory.total").split("\n") if self._run_smi("memory.total") else []
|
vram_total = self._run_smi("memory.total").split("\n") if self._run_smi("memory.total") else []
|
||||||
vram_used = self._run_smi("memory.used").split("\n") if self._run_smi("memory.used") else []
|
vram_used = self._run_smi("memory.used").split("\n") if self._run_smi("memory.used") else []
|
||||||
vram_free = self._run_smi("memory.free").split("\n") if self._run_smi("memory.free") else []
|
vram_free = self._run_smi("memory.free").split("\n") if self._run_smi("memory.free") else []
|
||||||
@ -166,7 +166,7 @@ class GPUInfo:
|
|||||||
|
|
||||||
for g in gpus:
|
for g in gpus:
|
||||||
name = g["name"]
|
name = g["name"]
|
||||||
if any(k in name for k in ("H100", "H200", "B200", "B300")):
|
if any(k in name for k in ("A100", "A800", "H100", "H200", "B200", "B300")):
|
||||||
name = f"[bold green]{name}[/bold green]"
|
name = f"[bold green]{name}[/bold green]"
|
||||||
vram = f"{g['vram_used_mb']}/{g['vram_total_mb']} MB"
|
vram = f"{g['vram_used_mb']}/{g['vram_total_mb']} MB"
|
||||||
temp = f"{g['temperature']}°C"
|
temp = f"{g['temperature']}°C"
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
"""GPU specifications database for NVIDIA datacenter GPUs."""
|
"""GPU specifications database for NVIDIA datacenter GPUs (A100/A800/H100/H200/B200/B300)."""
|
||||||
|
|
||||||
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
# GPU name patterns -> internal key mapping
|
# GPU name patterns -> internal key mapping
|
||||||
GPU_NAME_PATTERNS = {
|
GPU_NAME_PATTERNS = {
|
||||||
|
"A100": "a100",
|
||||||
|
"A800": "a800",
|
||||||
"H100": "h100",
|
"H100": "h100",
|
||||||
"H200": "h200",
|
"H200": "h200",
|
||||||
"B200": "b200",
|
"B200": "b200",
|
||||||
@ -70,6 +74,44 @@ GPU_SPECS = {
|
|||||||
"min_driver_version": "550",
|
"min_driver_version": "550",
|
||||||
"min_cuda_version": "12.4",
|
"min_cuda_version": "12.4",
|
||||||
},
|
},
|
||||||
|
"a100": {
|
||||||
|
"full_name": "NVIDIA A100 SXM",
|
||||||
|
"architecture": "Ampere",
|
||||||
|
"compute_capability": 8.0,
|
||||||
|
"hbm_capacity_gb": 80,
|
||||||
|
"hbm_type": "HBM2e",
|
||||||
|
"memory_bandwidth_gbps": 2039, # GB/s (~2.0 TB/s)
|
||||||
|
"fp32_tflops": 19.5,
|
||||||
|
"tf32_tflops": 156, # dense
|
||||||
|
"fp16_tflops": 312, # dense
|
||||||
|
"bf16_tflops": 312, # dense
|
||||||
|
"fp8_tflops": 0, # Ampere has no FP8
|
||||||
|
"tdp_watts": 400,
|
||||||
|
"nvlink_gen": 3,
|
||||||
|
"nvlink_bandwidth_gbps": 600, # bidirectional
|
||||||
|
"pcie_gen": 4,
|
||||||
|
"min_driver_version": "470",
|
||||||
|
"min_cuda_version": "11.0",
|
||||||
|
},
|
||||||
|
"a800": {
|
||||||
|
"full_name": "NVIDIA A800 SXM",
|
||||||
|
"architecture": "Ampere",
|
||||||
|
"compute_capability": 8.0,
|
||||||
|
"hbm_capacity_gb": 80,
|
||||||
|
"hbm_type": "HBM2e",
|
||||||
|
"memory_bandwidth_gbps": 2039, # GB/s (~2.0 TB/s)
|
||||||
|
"fp32_tflops": 19.5,
|
||||||
|
"tf32_tflops": 156, # dense
|
||||||
|
"fp16_tflops": 312, # dense
|
||||||
|
"bf16_tflops": 312, # dense
|
||||||
|
"fp8_tflops": 0, # Ampere has no FP8
|
||||||
|
"tdp_watts": 400,
|
||||||
|
"nvlink_gen": 3,
|
||||||
|
"nvlink_bandwidth_gbps": 600, # bidirectional (NVLink 3, limited vs A100)
|
||||||
|
"pcie_gen": 4,
|
||||||
|
"min_driver_version": "470",
|
||||||
|
"min_cuda_version": "11.0",
|
||||||
|
},
|
||||||
"b300": {
|
"b300": {
|
||||||
"full_name": "NVIDIA B300 SXM (Blackwell Ultra)",
|
"full_name": "NVIDIA B300 SXM (Blackwell Ultra)",
|
||||||
"architecture": "Blackwell Ultra",
|
"architecture": "Blackwell Ultra",
|
||||||
@ -162,3 +204,92 @@ def get_gpu_label(gpu_type: str) -> str:
|
|||||||
# Strip the "NVIDIA " prefix for display
|
# Strip the "NVIDIA " prefix for display
|
||||||
return full.replace("NVIDIA ", "")
|
return full.replace("NVIDIA ", "")
|
||||||
return "Unknown GPU"
|
return "Unknown GPU"
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Tools path resolution
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def resolve_tools_dir(config: dict) -> str:
|
||||||
|
"""Resolve tools installation directory with smart fallback.
|
||||||
|
|
||||||
|
Priority: GPU_TOOLS_DIR env > config value > /opt/gpu-test-tools > /tmp/gpu-test-tools
|
||||||
|
"""
|
||||||
|
# 1. Env var override
|
||||||
|
env_dir = os.environ.get("GPU_TOOLS_DIR")
|
||||||
|
if env_dir:
|
||||||
|
return env_dir
|
||||||
|
# 2. Config value if explicitly set
|
||||||
|
cfg_dir = config.get("tools", {}).get("install_dir", "")
|
||||||
|
if cfg_dir:
|
||||||
|
return cfg_dir
|
||||||
|
# 3. /opt/gpu-test-tools if it already exists or /opt is writable
|
||||||
|
default = "/opt/gpu-test-tools"
|
||||||
|
if os.path.isdir(default) or os.access("/opt", os.W_OK):
|
||||||
|
return default
|
||||||
|
# 4. Fallback to /tmp
|
||||||
|
return "/tmp/gpu-test-tools"
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Driver / CUDA compatibility validation
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _query_nvidia_smi(field: str) -> Optional[str]:
|
||||||
|
"""Query a single nvidia-smi field, return value string or None."""
|
||||||
|
nvidia_smi = shutil.which("nvidia-smi")
|
||||||
|
if not nvidia_smi:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
r = subprocess.run(
|
||||||
|
[nvidia_smi, f"--query-gpu={field}", "--format=csv,noheader,nounits"],
|
||||||
|
capture_output=True, text=True, timeout=10,
|
||||||
|
)
|
||||||
|
if r.returncode == 0 and r.stdout.strip():
|
||||||
|
return r.stdout.strip().splitlines()[0].strip()
|
||||||
|
except (subprocess.TimeoutExpired, FileNotFoundError, OSError):
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _version_lt(actual: str, minimum: str) -> bool:
|
||||||
|
"""Return True if actual version < minimum (numeric dotted comparison)."""
|
||||||
|
def to_tuple(v: str):
|
||||||
|
parts = []
|
||||||
|
for p in v.split("."):
|
||||||
|
try:
|
||||||
|
parts.append(int(p))
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
return tuple(parts) if parts else (0,)
|
||||||
|
return to_tuple(actual) < to_tuple(minimum)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_driver_compatibility(gpu_type: str) -> List[str]:
|
||||||
|
"""Check if current driver/CUDA meets minimum requirements for the detected GPU.
|
||||||
|
|
||||||
|
Returns a list of warning strings (empty if everything is fine).
|
||||||
|
"""
|
||||||
|
specs = get_gpu_specs(gpu_type)
|
||||||
|
warnings: List[str] = []
|
||||||
|
|
||||||
|
min_driver = specs.get("min_driver_version", "")
|
||||||
|
min_cuda = specs.get("min_cuda_version", "")
|
||||||
|
if not min_driver and not min_cuda:
|
||||||
|
return warnings
|
||||||
|
|
||||||
|
actual_driver = _query_nvidia_smi("driver_version")
|
||||||
|
# nvidia-smi reports the highest CUDA version supported by the driver
|
||||||
|
actual_cuda = _query_nvidia_smi("cuda_version")
|
||||||
|
|
||||||
|
gpu_label = get_gpu_label(gpu_type)
|
||||||
|
|
||||||
|
if actual_driver and min_driver and _version_lt(actual_driver, min_driver):
|
||||||
|
warnings.append(
|
||||||
|
f"Driver {actual_driver} < minimum {min_driver} required for {gpu_label}"
|
||||||
|
)
|
||||||
|
if actual_cuda and min_cuda and _version_lt(actual_cuda, min_cuda):
|
||||||
|
warnings.append(
|
||||||
|
f"CUDA {actual_cuda} < minimum {min_cuda} required for {gpu_label}"
|
||||||
|
)
|
||||||
|
return warnings
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
"""Hardware health monitoring module for NVIDIA datacenter GPUs (H100/H200/B200/B300)."""
|
"""Hardware health monitoring module for NVIDIA datacenter GPUs (A100/A800/H100/H200/B200/B300)."""
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import shutil
|
import shutil
|
||||||
@ -72,8 +72,8 @@ class HealthCheck:
|
|||||||
power_limits = query_lines("power.limit")
|
power_limits = query_lines("power.limit")
|
||||||
ecc_single = query_lines("ecc.errors.single_bit.total.volatile")
|
ecc_single = query_lines("ecc.errors.single_bit.total.volatile")
|
||||||
ecc_double = query_lines("ecc.errors.double_bit.total.volatile")
|
ecc_double = query_lines("ecc.errors.double_bit.total.volatile")
|
||||||
pcie_gens = query_lines("pcie_link.gen.current")
|
pcie_gens = query_lines("pcie.link.gen.current")
|
||||||
pcie_widths = query_lines("pcie_link.width.current")
|
pcie_widths = query_lines("pcie.link.width.current")
|
||||||
clock_sms = query_lines("clocks.sm")
|
clock_sms = query_lines("clocks.sm")
|
||||||
clock_mems = query_lines("clocks.mem")
|
clock_mems = query_lines("clocks.mem")
|
||||||
persistence = query_lines("persistence_mode")
|
persistence = query_lines("persistence_mode")
|
||||||
|
|||||||
@ -12,7 +12,7 @@ from rich.console import Console
|
|||||||
from rich.table import Table
|
from rich.table import Table
|
||||||
from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
|
from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
|
||||||
|
|
||||||
from modules.gpu_specs import detect_gpu_type, get_gpu_specs
|
from modules.gpu_specs import detect_gpu_type, get_gpu_specs, resolve_tools_dir
|
||||||
|
|
||||||
TORCH_AVAILABLE = False
|
TORCH_AVAILABLE = False
|
||||||
try:
|
try:
|
||||||
@ -29,7 +29,7 @@ class NCCLTest:
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.console = Console()
|
self.console = Console()
|
||||||
self.nccl_cfg = config.get("nccl", {})
|
self.nccl_cfg = config.get("nccl", {})
|
||||||
self.tools_dir = config.get("tools", {}).get("install_dir", "/opt/h200-test-tools")
|
self.tools_dir = resolve_tools_dir(config)
|
||||||
self.gpu_type = detect_gpu_type()
|
self.gpu_type = detect_gpu_type()
|
||||||
self.specs = get_gpu_specs(self.gpu_type)
|
self.specs = get_gpu_specs(self.gpu_type)
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
"""Report generation module - export test results to JSON/HTML."""
|
"""Report generation module - export test results to JSON/HTML/Markdown."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@ -73,6 +73,8 @@ class ReportGenerator:
|
|||||||
return self._generate_json(results, output)
|
return self._generate_json(results, output)
|
||||||
elif fmt == "html":
|
elif fmt == "html":
|
||||||
return self._generate_html(results, output)
|
return self._generate_html(results, output)
|
||||||
|
elif fmt == "md":
|
||||||
|
return self._generate_markdown(results, output)
|
||||||
else:
|
else:
|
||||||
self.console.print(f"[red]Unsupported format: {fmt}[/red]")
|
self.console.print(f"[red]Unsupported format: {fmt}[/red]")
|
||||||
return ""
|
return ""
|
||||||
@ -163,3 +165,314 @@ class ReportGenerator:
|
|||||||
f.write(html)
|
f.write(html)
|
||||||
self.console.print(f"[green]HTML report saved to: {output}[/green]")
|
self.console.print(f"[green]HTML report saved to: {output}[/green]")
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Markdown report
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _generate_markdown(self, results: dict, output: str) -> str:
|
||||||
|
import socket
|
||||||
|
hostname = socket.gethostname()
|
||||||
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
lines: list[str] = []
|
||||||
|
|
||||||
|
# --- Header ---
|
||||||
|
lines.append("# GPU Test Report\n")
|
||||||
|
lines.append(f"- **Date:** {timestamp}")
|
||||||
|
lines.append(f"- **Host:** {hostname}")
|
||||||
|
|
||||||
|
# Extract GPU info for header
|
||||||
|
gpu_info = results.get("gpu_info")
|
||||||
|
if gpu_info and not gpu_info.get("error"):
|
||||||
|
gpus = gpu_info.get("gpus", [])
|
||||||
|
gpu_name = gpus[0]["name"] if gpus else "Unknown"
|
||||||
|
lines.append(f"- **GPU:** {gpu_name} x{gpu_info.get('gpu_count', len(gpus))}")
|
||||||
|
lines.append(f"- **Driver:** {gpu_info.get('driver_version', 'N/A')} | "
|
||||||
|
f"**CUDA:** {gpu_info.get('cuda_version', 'N/A')}")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# --- Summary table ---
|
||||||
|
summary_items = self._build_summary(results)
|
||||||
|
if summary_items:
|
||||||
|
lines.append("## Summary\n")
|
||||||
|
lines.append("| Test | Result |")
|
||||||
|
lines.append("|------|--------|")
|
||||||
|
for name, verdict in summary_items:
|
||||||
|
lines.append(f"| {name} | {verdict} |")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# --- GPU Information ---
|
||||||
|
if gpu_info and not gpu_info.get("error"):
|
||||||
|
lines.append("## GPU Information\n")
|
||||||
|
gpus = gpu_info.get("gpus", [])
|
||||||
|
lines.append("| GPU | Model | VRAM | Temp | Power | SM Clock |")
|
||||||
|
lines.append("|-----|-------|------|------|-------|----------|")
|
||||||
|
for g in gpus:
|
||||||
|
vram = f"{g.get('vram_total_mb', 0)} MB"
|
||||||
|
temp = f"{g.get('temperature', 'N/A')}C"
|
||||||
|
power = f"{g.get('power_draw', 0):.0f}/{g.get('power_limit', 0):.0f}W"
|
||||||
|
clock = f"{g.get('clock_sm', 0)} MHz"
|
||||||
|
lines.append(f"| {g['index']} | {g['name']} | {vram} | {temp} | {power} | {clock} |")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# --- Health Check ---
|
||||||
|
health = results.get("health")
|
||||||
|
if health and not health.get("error"):
|
||||||
|
lines.append("## Health Check\n")
|
||||||
|
passed = health.get("passed", False)
|
||||||
|
lines.append(f"**Overall: {'PASS' if passed else 'FAIL'}**\n")
|
||||||
|
gpu_health = health.get("gpu_health", [])
|
||||||
|
if gpu_health:
|
||||||
|
lines.append("| GPU | Temp | Power | ECC | PCIe | Throttle | Status |")
|
||||||
|
lines.append("|-----|------|-------|-----|------|----------|--------|")
|
||||||
|
for gh in gpu_health:
|
||||||
|
checks = gh.get("checks", {})
|
||||||
|
temp_c = checks.get("temperature", {})
|
||||||
|
pwr = checks.get("power", {})
|
||||||
|
ecc = checks.get("ecc_errors", {})
|
||||||
|
pcie = checks.get("pcie_link", {})
|
||||||
|
throttle = checks.get("throttling", {})
|
||||||
|
temp_str = f"{temp_c.get('value', '?')}C {temp_c.get('status', '')}"
|
||||||
|
pwr_str = f"{pwr.get('value', 0):.0f}W {pwr.get('status', '')}"
|
||||||
|
ecc_str = f"S:{ecc.get('single', 0)} D:{ecc.get('double', 0)}"
|
||||||
|
pcie_str = f"Gen{pcie.get('gen', '?')}x{pcie.get('width', '?')}"
|
||||||
|
throt_str = throttle.get("status", "?")
|
||||||
|
status = gh.get("status", "?")
|
||||||
|
lines.append(f"| {gh['index']} | {temp_str} | {pwr_str} | "
|
||||||
|
f"{ecc_str} | {pcie_str} | {throt_str} | **{status}** |")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# --- Memory Bandwidth ---
|
||||||
|
mem_data = self._extract_memory_results(results)
|
||||||
|
if mem_data and not mem_data.get("error"):
|
||||||
|
lines.append("## Memory Bandwidth\n")
|
||||||
|
lines.append(f"Source: {mem_data.get('source', 'unknown')}\n")
|
||||||
|
lines.append("| Metric | Value | Peak | Efficiency |")
|
||||||
|
lines.append("|--------|-------|------|------------|")
|
||||||
|
d2d = mem_data.get("d2d_bandwidth_gbps", 0)
|
||||||
|
h2d = mem_data.get("h2d_bandwidth_gbps", 0)
|
||||||
|
d2h = mem_data.get("d2h_bandwidth_gbps", 0)
|
||||||
|
peak = mem_data.get("peak_bandwidth_gbps", 0)
|
||||||
|
eff = mem_data.get("efficiency_pct", 0)
|
||||||
|
lines.append(f"| D2D (HBM) | {d2d:.1f} GB/s | {peak:.0f} GB/s | {eff:.1f}% |")
|
||||||
|
lines.append(f"| H2D | {h2d:.1f} GB/s | - | - |")
|
||||||
|
lines.append(f"| D2H | {d2h:.1f} GB/s | - | - |")
|
||||||
|
lines.append("")
|
||||||
|
verdict = "PASS" if eff >= 80 else ("WARN" if eff >= 50 else "FAIL")
|
||||||
|
lines.append(f"**Verdict: {verdict}** (D2D efficiency {eff:.1f}%)\n")
|
||||||
|
|
||||||
|
# --- Compute Throughput ---
|
||||||
|
comp_data = self._extract_compute_results(results)
|
||||||
|
if comp_data and not comp_data.get("error"):
|
||||||
|
lines.append("## Compute Throughput\n")
|
||||||
|
per_dtype = comp_data.get("per_dtype_tflops", {})
|
||||||
|
peak_tflops = comp_data.get("peak_tflops", {})
|
||||||
|
eff_pct = comp_data.get("efficiency_pct", {})
|
||||||
|
lines.append("| DType | Achieved (TFLOPS) | Peak | Efficiency | Status |")
|
||||||
|
lines.append("|-------|-------------------|------|------------|--------|")
|
||||||
|
worst_eff = 100.0
|
||||||
|
for dt, val in per_dtype.items():
|
||||||
|
if isinstance(val, str):
|
||||||
|
# skipped or error
|
||||||
|
lines.append(f"| {dt.upper()} | {val} | - | N/A | SKIP |")
|
||||||
|
else:
|
||||||
|
pk = peak_tflops.get(dt, 0)
|
||||||
|
ef = eff_pct.get(dt, 0)
|
||||||
|
if isinstance(ef, (int, float)) and ef > 0:
|
||||||
|
worst_eff = min(worst_eff, ef)
|
||||||
|
status = "PASS" if ef >= 80 else ("WARN" if ef >= 50 else "FAIL")
|
||||||
|
lines.append(f"| {dt.upper()} | {val:.1f} | {pk:.0f} | {ef:.1f}% | {status} |")
|
||||||
|
lines.append("")
|
||||||
|
overall = "PASS" if worst_eff >= 80 else ("WARN" if worst_eff >= 50 else "FAIL")
|
||||||
|
lines.append(f"**Verdict: {overall}** (worst efficiency {worst_eff:.1f}%)\n")
|
||||||
|
|
||||||
|
# --- NCCL ---
|
||||||
|
nccl = results.get("nccl")
|
||||||
|
if nccl and not nccl.get("error"):
|
||||||
|
lines.append("## NCCL Multi-GPU\n")
|
||||||
|
lines.append(f"Source: {nccl.get('source', 'unknown')} | "
|
||||||
|
f"GPUs: {nccl.get('gpu_count', '?')}\n")
|
||||||
|
tests = nccl.get("tests", {})
|
||||||
|
if tests:
|
||||||
|
lines.append("| Operation | Bus BW (GB/s) | Threshold | Status |")
|
||||||
|
lines.append("|-----------|---------------|-----------|--------|")
|
||||||
|
for op, data in tests.items():
|
||||||
|
if isinstance(data, dict) and not data.get("error"):
|
||||||
|
bw = data.get("best_busbw_gbps", 0)
|
||||||
|
req = data.get("min_required_gbps", 0)
|
||||||
|
status = data.get("status", "?")
|
||||||
|
lines.append(f"| {op} | {bw:.1f} | >= {req:.0f} | {status} |")
|
||||||
|
elif isinstance(data, dict) and data.get("error"):
|
||||||
|
lines.append(f"| {op} | - | - | ERROR: {data['error']} |")
|
||||||
|
lines.append("")
|
||||||
|
passed = nccl.get("passed", False)
|
||||||
|
lines.append(f"**Overall: {'PASS' if passed else 'FAIL'}**\n")
|
||||||
|
|
||||||
|
# --- Stress Test ---
|
||||||
|
stress = results.get("stress")
|
||||||
|
if stress and not stress.get("error"):
|
||||||
|
lines.append("## Stress Test\n")
|
||||||
|
passed = stress.get("passed", False)
|
||||||
|
duration = stress.get("duration_sec", 0)
|
||||||
|
elapsed = stress.get("elapsed_sec", 0)
|
||||||
|
source = stress.get("source", "unknown")
|
||||||
|
lines.append(f"- **Source:** {source}")
|
||||||
|
lines.append(f"- **Duration:** {elapsed:.0f}s (requested {duration}s)")
|
||||||
|
lines.append(f"- **Result: {'PASS' if passed else 'FAIL'}**")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# --- RDMA ---
|
||||||
|
rdma = results.get("rdma")
|
||||||
|
if rdma and not rdma.get("error"):
|
||||||
|
lines.append("## RDMA/InfiniBand\n")
|
||||||
|
bw_tests = rdma.get("bandwidth_tests", [])
|
||||||
|
lat_tests = rdma.get("latency_tests", [])
|
||||||
|
if bw_tests or lat_tests:
|
||||||
|
lines.append("| Test | Value | Threshold | Status |")
|
||||||
|
lines.append("|------|-------|-----------|--------|")
|
||||||
|
for bt in bw_tests:
|
||||||
|
if not bt.get("error"):
|
||||||
|
lines.append(f"| {bt['test']} | {bt.get('bandwidth_gbps', 0):.1f} GB/s | "
|
||||||
|
f">= {bt.get('min_required_gbps', 0)} GB/s | {bt.get('status', '?')} |")
|
||||||
|
for lt in lat_tests:
|
||||||
|
if not lt.get("error"):
|
||||||
|
lines.append(f"| {lt['test']} | {lt.get('latency_us', 0):.2f} us | "
|
||||||
|
f"<= {lt.get('max_allowed_us', 0)} us | {lt.get('status', '?')} |")
|
||||||
|
lines.append("")
|
||||||
|
passed = rdma.get("passed", False)
|
||||||
|
lines.append(f"**Overall: {'PASS' if passed else 'FAIL'}**\n")
|
||||||
|
|
||||||
|
# --- Training ---
|
||||||
|
training = results.get("training")
|
||||||
|
if training and not training.get("error"):
|
||||||
|
lines.append("## Training Simulation\n")
|
||||||
|
lines.append("| Metric | Value |")
|
||||||
|
lines.append("|--------|-------|")
|
||||||
|
lines.append(f"| Model | {training.get('model', 'N/A')} |")
|
||||||
|
lines.append(f"| Params | {training.get('total_params_m', 0):.1f}M |")
|
||||||
|
lines.append(f"| Throughput | {training.get('throughput_tokens_per_sec', 0):.0f} tokens/sec |")
|
||||||
|
lines.append(f"| Avg Step Time | {training.get('avg_step_time_ms', 0):.1f} ms |")
|
||||||
|
lines.append(f"| Peak Memory | {training.get('peak_memory_gb', 0):.1f} GB |")
|
||||||
|
lines.append(f"| Final Loss | {training.get('final_loss', 'N/A')} |")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# --- Footer ---
|
||||||
|
lines.append("---")
|
||||||
|
lines.append(f"*Generated by GPU Test Suite v0.2.0*")
|
||||||
|
|
||||||
|
content = "\n".join(lines)
|
||||||
|
with open(output, "w") as f:
|
||||||
|
f.write(content)
|
||||||
|
self.console.print(f"[green]Markdown report saved to: {output}[/green]")
|
||||||
|
return output
|
||||||
|
|
||||||
|
def _extract_memory_results(self, results: dict) -> dict:
|
||||||
|
"""Extract memory benchmark data from either full-suite or single-test format."""
|
||||||
|
if "memory_bench" in results:
|
||||||
|
data = results["memory_bench"]
|
||||||
|
return data.get("memory", data) if isinstance(data, dict) else {}
|
||||||
|
if "benchmark" in results:
|
||||||
|
bench = results["benchmark"]
|
||||||
|
if isinstance(bench, dict) and "memory" in bench:
|
||||||
|
return bench["memory"]
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def _extract_compute_results(self, results: dict) -> dict:
|
||||||
|
"""Extract compute benchmark data from either full-suite or single-test format."""
|
||||||
|
if "compute_bench" in results:
|
||||||
|
data = results["compute_bench"]
|
||||||
|
return data.get("compute", data) if isinstance(data, dict) else {}
|
||||||
|
if "benchmark" in results:
|
||||||
|
bench = results["benchmark"]
|
||||||
|
if isinstance(bench, dict) and "compute" in bench:
|
||||||
|
return bench["compute"]
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def _build_summary(self, results: dict) -> list[tuple[str, str]]:
|
||||||
|
"""Build summary verdict list from results."""
|
||||||
|
items = []
|
||||||
|
|
||||||
|
# GPU Info
|
||||||
|
if "gpu_info" in results:
|
||||||
|
gi = results["gpu_info"]
|
||||||
|
if gi.get("error"):
|
||||||
|
items.append(("GPU Info", f"ERROR: {gi['error']}"))
|
||||||
|
else:
|
||||||
|
items.append(("GPU Info", f"PASS ({gi.get('gpu_count', '?')} GPUs detected)"))
|
||||||
|
|
||||||
|
# Health
|
||||||
|
if "health" in results:
|
||||||
|
h = results["health"]
|
||||||
|
if h.get("error"):
|
||||||
|
items.append(("Health Check", f"ERROR: {h['error']}"))
|
||||||
|
elif h.get("passed"):
|
||||||
|
items.append(("Health Check", "PASS"))
|
||||||
|
else:
|
||||||
|
items.append(("Health Check", "FAIL"))
|
||||||
|
|
||||||
|
# Memory Bandwidth
|
||||||
|
mem = self._extract_memory_results(results)
|
||||||
|
if mem:
|
||||||
|
if mem.get("error"):
|
||||||
|
items.append(("Memory Bandwidth", f"ERROR: {mem['error']}"))
|
||||||
|
else:
|
||||||
|
eff = mem.get("efficiency_pct", 0)
|
||||||
|
verdict = "PASS" if eff >= 80 else ("WARN" if eff >= 50 else "FAIL")
|
||||||
|
items.append(("Memory Bandwidth", f"{verdict} ({eff:.1f}%)"))
|
||||||
|
|
||||||
|
# Compute
|
||||||
|
comp = self._extract_compute_results(results)
|
||||||
|
if comp:
|
||||||
|
if comp.get("error"):
|
||||||
|
items.append(("Compute Throughput", f"ERROR: {comp['error']}"))
|
||||||
|
else:
|
||||||
|
eff_pct = comp.get("efficiency_pct", {})
|
||||||
|
valid_effs = [v for v in eff_pct.values() if isinstance(v, (int, float)) and v > 0]
|
||||||
|
if valid_effs:
|
||||||
|
worst = min(valid_effs)
|
||||||
|
verdict = "PASS" if worst >= 80 else ("WARN" if worst >= 50 else "FAIL")
|
||||||
|
items.append(("Compute Throughput", f"{verdict} (worst {worst:.1f}%)"))
|
||||||
|
else:
|
||||||
|
items.append(("Compute Throughput", "N/A"))
|
||||||
|
|
||||||
|
# NCCL
|
||||||
|
if "nccl" in results:
|
||||||
|
n = results["nccl"]
|
||||||
|
if n.get("error"):
|
||||||
|
items.append(("NCCL", f"ERROR: {n['error']}"))
|
||||||
|
elif n.get("passed"):
|
||||||
|
items.append(("NCCL", "PASS"))
|
||||||
|
else:
|
||||||
|
items.append(("NCCL", "FAIL"))
|
||||||
|
|
||||||
|
# Stress
|
||||||
|
if "stress" in results:
|
||||||
|
s = results["stress"]
|
||||||
|
if s.get("error"):
|
||||||
|
items.append(("Stress Test", f"ERROR: {s['error']}"))
|
||||||
|
elif s.get("passed"):
|
||||||
|
items.append(("Stress Test", "PASS"))
|
||||||
|
else:
|
||||||
|
items.append(("Stress Test", "FAIL"))
|
||||||
|
|
||||||
|
# RDMA
|
||||||
|
if "rdma" in results:
|
||||||
|
r = results["rdma"]
|
||||||
|
if r.get("error"):
|
||||||
|
items.append(("RDMA", f"ERROR: {r['error']}"))
|
||||||
|
elif r.get("passed"):
|
||||||
|
items.append(("RDMA", "PASS"))
|
||||||
|
else:
|
||||||
|
items.append(("RDMA", "FAIL"))
|
||||||
|
|
||||||
|
# Training
|
||||||
|
if "training" in results:
|
||||||
|
t = results["training"]
|
||||||
|
if t.get("error"):
|
||||||
|
items.append(("Training", f"ERROR: {t['error']}"))
|
||||||
|
else:
|
||||||
|
tps = t.get("throughput_tokens_per_sec", 0)
|
||||||
|
items.append(("Training", f"PASS ({tps:.0f} tokens/sec)"))
|
||||||
|
|
||||||
|
return items
|
||||||
|
|||||||
@ -12,6 +12,8 @@ from rich.table import Table
|
|||||||
from rich.live import Live
|
from rich.live import Live
|
||||||
from rich.text import Text
|
from rich.text import Text
|
||||||
|
|
||||||
|
from modules.gpu_specs import resolve_tools_dir
|
||||||
|
|
||||||
|
|
||||||
class StressTest:
|
class StressTest:
|
||||||
|
|
||||||
@ -19,7 +21,7 @@ class StressTest:
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.console = Console()
|
self.console = Console()
|
||||||
self.stress_cfg = config.get("stress", {})
|
self.stress_cfg = config.get("stress", {})
|
||||||
self.tools_dir = config.get("tools", {}).get("install_dir", "/opt/h200-test-tools")
|
self.tools_dir = resolve_tools_dir(config)
|
||||||
|
|
||||||
def _find_gpu_burn(self) -> str:
|
def _find_gpu_burn(self) -> str:
|
||||||
p = shutil.which("gpu_burn")
|
p = shutil.which("gpu_burn")
|
||||||
@ -123,7 +125,8 @@ class StressTest:
|
|||||||
tensors = {}
|
tensors = {}
|
||||||
for i in range(gpu_count):
|
for i in range(gpu_count):
|
||||||
with torch.cuda.device(i):
|
with torch.cuda.device(i):
|
||||||
total_mem = torch.cuda.get_device_properties(i).total_mem
|
props = torch.cuda.get_device_properties(i)
|
||||||
|
total_mem = getattr(props, "total_memory", None) or getattr(props, "total_mem", 0)
|
||||||
alloc_size = int(total_mem * 0.9) // 4
|
alloc_size = int(total_mem * 0.9) // 4
|
||||||
tensors[i] = torch.randn(alloc_size, device=f"cuda:{i}", dtype=torch.float32)
|
tensors[i] = torch.randn(alloc_size, device=f"cuda:{i}", dtype=torch.float32)
|
||||||
|
|
||||||
|
|||||||
57
pyproject.toml
Normal file
57
pyproject.toml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
[project]
|
||||||
|
name = "gpu-server-test-suite"
|
||||||
|
version = "0.2.0"
|
||||||
|
description = "GPU training server diagnostics & benchmarks (A100/A800/H100/H200/B200/B300)."
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.10,<3.13"
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
"rich>=13.0",
|
||||||
|
"pyyaml>=6.0",
|
||||||
|
"numpy>=1.24",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
# Install ONE matching your system CUDA version:
|
||||||
|
# uv sync --extra torch-cu118
|
||||||
|
# uv sync --extra torch-cu121
|
||||||
|
# uv sync --extra torch-cu124 (recommended for CUDA 12.x + Driver 535+)
|
||||||
|
# uv sync --extra torch-cu128 (for CUDA 12.8+ / Driver 570+)
|
||||||
|
torch-cu118 = ["torch>=2.1.0"]
|
||||||
|
torch-cu121 = ["torch>=2.1.0"]
|
||||||
|
torch-cu124 = ["torch>=2.1.0"]
|
||||||
|
torch-cu128 = ["torch>=2.1.0"]
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
# PyTorch wheel indexes — one per CUDA version
|
||||||
|
[[tool.uv.index]]
|
||||||
|
name = "pytorch-cu118"
|
||||||
|
url = "https://download.pytorch.org/whl/cu118"
|
||||||
|
explicit = true
|
||||||
|
|
||||||
|
[[tool.uv.index]]
|
||||||
|
name = "pytorch-cu121"
|
||||||
|
url = "https://download.pytorch.org/whl/cu121"
|
||||||
|
explicit = true
|
||||||
|
|
||||||
|
[[tool.uv.index]]
|
||||||
|
name = "pytorch-cu124"
|
||||||
|
url = "https://download.pytorch.org/whl/cu124"
|
||||||
|
explicit = true
|
||||||
|
|
||||||
|
[[tool.uv.index]]
|
||||||
|
name = "pytorch-cu128"
|
||||||
|
url = "https://download.pytorch.org/whl/cu128"
|
||||||
|
explicit = true
|
||||||
|
|
||||||
|
# Default: resolve torch from cu124 index (most broadly compatible with 535+ drivers)
|
||||||
|
# To use a different CUDA version, override:
|
||||||
|
# uv pip install torch --index-url https://download.pytorch.org/whl/cu128
|
||||||
|
[tool.uv.sources]
|
||||||
|
torch = { index = "pytorch-cu124" }
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel]
|
||||||
|
packages = ["modules"]
|
||||||
510
uv.lock
generated
Normal file
510
uv.lock
generated
Normal file
@ -0,0 +1,510 @@
|
|||||||
|
version = 1
|
||||||
|
revision = 3
|
||||||
|
requires-python = ">=3.10, <3.13"
|
||||||
|
resolution-markers = [
|
||||||
|
"python_full_version >= '3.12'",
|
||||||
|
"python_full_version == '3.11.*'",
|
||||||
|
"python_full_version < '3.11'",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filelock"
|
||||||
|
version = "3.29.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fsspec"
|
||||||
|
version = "2026.4.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d5/8d/1c51c094345df128ca4a990d633fe1a0ff28726c9e6b3c41ba65087bba1d/fsspec-2026.4.0.tar.gz", hash = "sha256:301d8ac70ae90ef3ad05dcf94d6c3754a097f9b5fe4667d2787aa359ec7df7e4", size = 312760, upload-time = "2026-04-29T20:42:38.635Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d5/0c/043d5e551459da400957a1395e0febbf771446ff34291afcbe3d8be2a279/fsspec-2026.4.0-py3-none-any.whl", hash = "sha256:11ef7bb35dab8a394fde6e608221d5cf3e8499401c249bebaeaad760a1a8dec2", size = 203402, upload-time = "2026-04-29T20:42:36.842Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gpu-server-test-suite"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = { editable = "." }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
||||||
|
{ name = "numpy", version = "2.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
|
||||||
|
{ name = "pyyaml" },
|
||||||
|
{ name = "rich" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.optional-dependencies]
|
||||||
|
torch-cu118 = [
|
||||||
|
{ name = "torch" },
|
||||||
|
]
|
||||||
|
torch-cu121 = [
|
||||||
|
{ name = "torch" },
|
||||||
|
]
|
||||||
|
torch-cu124 = [
|
||||||
|
{ name = "torch" },
|
||||||
|
]
|
||||||
|
torch-cu128 = [
|
||||||
|
{ name = "torch" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [
|
||||||
|
{ name = "numpy", specifier = ">=1.24" },
|
||||||
|
{ name = "pyyaml", specifier = ">=6.0" },
|
||||||
|
{ name = "rich", specifier = ">=13.0" },
|
||||||
|
{ name = "torch", marker = "extra == 'torch-cu118'", specifier = ">=2.1.0", index = "https://download.pytorch.org/whl/cu124" },
|
||||||
|
{ name = "torch", marker = "extra == 'torch-cu121'", specifier = ">=2.1.0", index = "https://download.pytorch.org/whl/cu124" },
|
||||||
|
{ name = "torch", marker = "extra == 'torch-cu124'", specifier = ">=2.1.0", index = "https://download.pytorch.org/whl/cu124" },
|
||||||
|
{ name = "torch", marker = "extra == 'torch-cu128'", specifier = ">=2.1.0", index = "https://download.pytorch.org/whl/cu124" },
|
||||||
|
]
|
||||||
|
provides-extras = ["torch-cu118", "torch-cu121", "torch-cu124", "torch-cu128"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jinja2"
|
||||||
|
version = "3.1.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "markupsafe" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markdown-it-py"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "mdurl" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markupsafe"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mdurl"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mpmath"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106, upload-time = "2023-03-07T16:47:11.061Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198, upload-time = "2023-03-07T16:47:09.197Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "networkx"
|
||||||
|
version = "3.4.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
resolution-markers = [
|
||||||
|
"python_full_version < '3.11'",
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/fd/1d/06475e1cd5264c0b870ea2cc6fdb3e37177c1e565c43f56ff17a10e3937f/networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1", size = 2151368, upload-time = "2024-10-21T12:39:38.695Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b9/54/dd730b32ea14ea797530a4479b2ed46a6fb250f682a9cfb997e968bf0261/networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f", size = 1723263, upload-time = "2024-10-21T12:39:36.247Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "networkx"
|
||||||
|
version = "3.6.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
resolution-markers = [
|
||||||
|
"python_full_version >= '3.12'",
|
||||||
|
"python_full_version == '3.11.*'",
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9e/c9/b2622292ea83fbb4ec318f5b9ab867d0a28ab43c5717bb85b0a5f6b3b0a4/networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762", size = 2068504, upload-time = "2025-12-08T17:02:38.159Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "2.2.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
resolution-markers = [
|
||||||
|
"python_full_version < '3.11'",
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "2.4.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
resolution-markers = [
|
||||||
|
"python_full_version >= '3.12'",
|
||||||
|
"python_full_version == '3.11.*'",
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d7/9f/b8cef5bffa569759033adda9481211426f12f53299629b410340795c2514/numpy-2.4.4.tar.gz", hash = "sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0", size = 20731587, upload-time = "2026-03-29T13:22:01.298Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ef/c6/4218570d8c8ecc9704b5157a3348e486e84ef4be0ed3e38218ab473c83d2/numpy-2.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db", size = 16976799, upload-time = "2026-03-29T13:18:15.438Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dd/92/b4d922c4a5f5dab9ed44e6153908a5c665b71acf183a83b93b690996e39b/numpy-2.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0", size = 14971552, upload-time = "2026-03-29T13:18:18.606Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8a/dc/df98c095978fa6ee7b9a9387d1d58cbb3d232d0e69ad169a4ce784bde4fd/numpy-2.4.4-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015", size = 5476566, upload-time = "2026-03-29T13:18:21.532Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/28/34/b3fdcec6e725409223dd27356bdf5a3c2cc2282e428218ecc9cb7acc9763/numpy-2.4.4-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40", size = 6806482, upload-time = "2026-03-29T13:18:23.634Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/68/62/63417c13aa35d57bee1337c67446761dc25ea6543130cf868eace6e8157b/numpy-2.4.4-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d", size = 15973376, upload-time = "2026-03-29T13:18:26.677Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cf/c5/9fcb7e0e69cef59cf10c746b84f7d58b08bc66a6b7d459783c5a4f6101a6/numpy-2.4.4-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502", size = 16925137, upload-time = "2026-03-29T13:18:30.14Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/43/80020edacb3f84b9efdd1591120a4296462c23fd8db0dde1666f6ef66f13/numpy-2.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd", size = 17329414, upload-time = "2026-03-29T13:18:33.733Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fd/06/af0658593b18a5f73532d377188b964f239eb0894e664a6c12f484472f97/numpy-2.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5", size = 18658397, upload-time = "2026-03-29T13:18:37.511Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e6/ce/13a09ed65f5d0ce5c7dd0669250374c6e379910f97af2c08c57b0608eee4/numpy-2.4.4-cp311-cp311-win32.whl", hash = "sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e", size = 6239499, upload-time = "2026-03-29T13:18:40.372Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bd/63/05d193dbb4b5eec1eca73822d80da98b511f8328ad4ae3ca4caf0f4db91d/numpy-2.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e", size = 12614257, upload-time = "2026-03-29T13:18:42.95Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/87/c5/8168052f080c26fa984c413305012be54741c9d0d74abd7fbeeccae3889f/numpy-2.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e", size = 10486775, upload-time = "2026-03-29T13:18:45.835Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/28/05/32396bec30fb2263770ee910142f49c1476d08e8ad41abf8403806b520ce/numpy-2.4.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b", size = 16689272, upload-time = "2026-03-29T13:18:49.223Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c5/f3/a983d28637bfcd763a9c7aafdb6d5c0ebf3d487d1e1459ffdb57e2f01117/numpy-2.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e", size = 14699573, upload-time = "2026-03-29T13:18:52.629Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9b/fd/e5ecca1e78c05106d98028114f5c00d3eddb41207686b2b7de3e477b0e22/numpy-2.4.4-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842", size = 5204782, upload-time = "2026-03-29T13:18:55.579Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/de/2f/702a4594413c1a8632092beae8aba00f1d67947389369b3777aed783fdca/numpy-2.4.4-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8", size = 6552038, upload-time = "2026-03-29T13:18:57.769Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7f/37/eed308a8f56cba4d1fdf467a4fc67ef4ff4bf1c888f5fc980481890104b1/numpy-2.4.4-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121", size = 15670666, upload-time = "2026-03-29T13:19:00.341Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0a/0d/0e3ecece05b7a7e87ab9fb587855548da437a061326fff64a223b6dcb78a/numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e", size = 16645480, upload-time = "2026-03-29T13:19:03.63Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/34/49/f2312c154b82a286758ee2f1743336d50651f8b5195db18cdb63675ff649/numpy-2.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44", size = 17020036, upload-time = "2026-03-29T13:19:07.428Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7b/e9/736d17bd77f1b0ec4f9901aaec129c00d59f5d84d5e79bba540ef12c2330/numpy-2.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d", size = 18368643, upload-time = "2026-03-29T13:19:10.775Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/63/f6/d417977c5f519b17c8a5c3bc9e8304b0908b0e21136fe43bf628a1343914/numpy-2.4.4-cp312-cp312-win32.whl", hash = "sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827", size = 5961117, upload-time = "2026-03-29T13:19:13.464Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2d/5b/e1deebf88ff431b01b7406ca3583ab2bbb90972bbe1c568732e49c844f7e/numpy-2.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a", size = 12320584, upload-time = "2026-03-29T13:19:16.155Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/58/89/e4e856ac82a68c3ed64486a544977d0e7bdd18b8da75b78a577ca31c4395/numpy-2.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec", size = 10221450, upload-time = "2026-03-29T13:19:18.994Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/33/8fae8f964a4f63ed528264ddf25d2b683d0b663e3cba26961eb838a7c1bd/numpy-2.4.4-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4", size = 16854491, upload-time = "2026-03-29T13:21:38.03Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bc/d0/1aabee441380b981cf8cdda3ae7a46aa827d1b5a8cce84d14598bc94d6d9/numpy-2.4.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e", size = 14895830, upload-time = "2026-03-29T13:21:41.509Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a5/b8/aafb0d1065416894fccf4df6b49ef22b8db045187949545bced89c034b8e/numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c", size = 5400927, upload-time = "2026-03-29T13:21:44.747Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/77/063baa20b08b431038c7f9ff5435540c7b7265c78cf56012a483019ca72d/numpy-2.4.4-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3", size = 6715557, upload-time = "2026-03-29T13:21:47.406Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c7/a8/379542d45a14f149444c5c4c4e7714707239ce9cc1de8c2803958889da14/numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7", size = 15804253, upload-time = "2026-03-29T13:21:50.753Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a2/c8/f0a45426d6d21e7ea3310a15cf90c43a14d9232c31a837702dba437f3373/numpy-2.4.4-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f", size = 16753552, upload-time = "2026-03-29T13:21:54.344Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/04/74/f4c001f4714c3ad9ce037e18cf2b9c64871a84951eaa0baf683a9ca9301c/numpy-2.4.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119", size = 12509075, upload-time = "2026-03-29T13:21:57.644Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-cublas-cu12"
|
||||||
|
version = "12.4.5.8"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/71/1c91302526c45ab494c23f61c7a84aa568b8c1f9d196efa5993957faf906/nvidia_cublas_cu12-12.4.5.8-py3-none-manylinux2014_x86_64.whl", hash = "sha256:2fc8da60df463fdefa81e323eef2e36489e1c94335b5358bcb38360adf75ac9b", size = 363438805, upload-time = "2024-04-03T20:57:06.025Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-cuda-cupti-cu12"
|
||||||
|
version = "12.4.127"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/67/42/f4f60238e8194a3106d06a058d494b18e006c10bb2b915655bd9f6ea4cb1/nvidia_cuda_cupti_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:9dec60f5ac126f7bb551c055072b69d85392b13311fcc1bcda2202d172df30fb", size = 13813957, upload-time = "2024-04-03T20:55:01.564Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-cuda-nvrtc-cu12"
|
||||||
|
version = "12.4.127"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2c/14/91ae57cd4db3f9ef7aa99f4019cfa8d54cb4caa7e00975df6467e9725a9f/nvidia_cuda_nvrtc_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a178759ebb095827bd30ef56598ec182b85547f1508941a3d560eb7ea1fbf338", size = 24640306, upload-time = "2024-04-03T20:56:01.463Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-cuda-runtime-cu12"
|
||||||
|
version = "12.4.127"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ea/27/1795d86fe88ef397885f2e580ac37628ed058a92ed2c39dc8eac3adf0619/nvidia_cuda_runtime_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:64403288fa2136ee8e467cdc9c9427e0434110899d07c779f25b5c068934faa5", size = 883737, upload-time = "2024-04-03T20:54:51.355Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-cudnn-cu12"
|
||||||
|
version = "9.1.0.70"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "nvidia-cublas-cu12" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/fd/713452cd72343f682b1c7b9321e23829f00b842ceaedcda96e742ea0b0b3/nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl", hash = "sha256:165764f44ef8c61fcdfdfdbe769d687e06374059fbb388b6c89ecb0e28793a6f", size = 664752741, upload-time = "2024-04-22T15:24:15.253Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-cufft-cu12"
|
||||||
|
version = "11.2.1.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "nvidia-nvjitlink-cu12" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/94/3266821f65b92b3138631e9c8e7fe1fb513804ac934485a8d05776e1dd43/nvidia_cufft_cu12-11.2.1.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:f083fc24912aa410be21fa16d157fed2055dab1cc4b6934a0e03cba69eb242b9", size = 211459117, upload-time = "2024-04-03T20:57:40.402Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-curand-cu12"
|
||||||
|
version = "10.3.5.147"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8a/6d/44ad094874c6f1b9c654f8ed939590bdc408349f137f9b98a3a23ccec411/nvidia_curand_cu12-10.3.5.147-py3-none-manylinux2014_x86_64.whl", hash = "sha256:a88f583d4e0bb643c49743469964103aa59f7f708d862c3ddb0fc07f851e3b8b", size = 56305206, upload-time = "2024-04-03T20:58:08.722Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-cusolver-cu12"
|
||||||
|
version = "11.6.1.9"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "nvidia-cublas-cu12" },
|
||||||
|
{ name = "nvidia-cusparse-cu12" },
|
||||||
|
{ name = "nvidia-nvjitlink-cu12" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3a/e1/5b9089a4b2a4790dfdea8b3a006052cfecff58139d5a4e34cb1a51df8d6f/nvidia_cusolver_cu12-11.6.1.9-py3-none-manylinux2014_x86_64.whl", hash = "sha256:19e33fa442bcfd085b3086c4ebf7e8debc07cfe01e11513cc6d332fd918ac260", size = 127936057, upload-time = "2024-04-03T20:58:28.735Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-cusparse-cu12"
|
||||||
|
version = "12.3.1.170"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "nvidia-nvjitlink-cu12" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/db/f7/97a9ea26ed4bbbfc2d470994b8b4f338ef663be97b8f677519ac195e113d/nvidia_cusparse_cu12-12.3.1.170-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ea4f11a2904e2a8dc4b1833cc1b5181cde564edd0d5cd33e3c168eff2d1863f1", size = 207454763, upload-time = "2024-04-03T20:58:59.995Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-cusparselt-cu12"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/a8/bcbb63b53a4b1234feeafb65544ee55495e1bb37ec31b999b963cbccfd1d/nvidia_cusparselt_cu12-0.6.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:df2c24502fd76ebafe7457dbc4716b2fec071aabaed4fb7691a201cde03704d9", size = 150057751, upload-time = "2024-07-23T02:35:53.074Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-nccl-cu12"
|
||||||
|
version = "2.21.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/df/99/12cd266d6233f47d00daf3a72739872bdc10267d0383508b0b9c84a18bb6/nvidia_nccl_cu12-2.21.5-py3-none-manylinux2014_x86_64.whl", hash = "sha256:8579076d30a8c24988834445f8d633c697d42397e92ffc3f63fa26766d25e0a0", size = 188654414, upload-time = "2024-04-03T15:32:57.427Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-nvjitlink-cu12"
|
||||||
|
version = "12.4.127"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/ff/847841bacfbefc97a00036e0fce5a0f086b640756dc38caea5e1bb002655/nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57", size = 21066810, upload-time = "2024-04-03T20:59:46.957Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nvidia-nvtx-cu12"
|
||||||
|
version = "12.4.127"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/87/20/199b8713428322a2f22b722c62b8cc278cc53dffa9705d744484b5035ee9/nvidia_nvtx_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:781e950d9b9f60d8241ccea575b32f5105a5baf4c2351cab5256a24869f12a1a", size = 99144, upload-time = "2024-04-03T20:56:12.406Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pygments"
|
||||||
|
version = "2.20.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyyaml"
|
||||||
|
version = "6.0.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rich"
|
||||||
|
version = "15.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "markdown-it-py" },
|
||||||
|
{ name = "pygments" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "setuptools"
|
||||||
|
version = "81.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/0d/1c/73e719955c59b8e424d015ab450f51c0af856ae46ea2da83eba51cc88de1/setuptools-81.0.0.tar.gz", hash = "sha256:487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a", size = 1198299, upload-time = "2026-02-06T21:10:39.601Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e1/e3/c164c88b2e5ce7b24d667b9bd83589cf4f3520d97cad01534cd3c4f55fdb/setuptools-81.0.0-py3-none-any.whl", hash = "sha256:fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6", size = 1062021, upload-time = "2026-02-06T21:10:37.175Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sympy"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "mpmath" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ca/99/5a5b6f19ff9f083671ddf7b9632028436167cd3d33e11015754e41b249a4/sympy-1.13.1.tar.gz", hash = "sha256:9cebf7e04ff162015ce31c9c6c9144daa34a93bd082f54fd8f12deca4f47515f", size = 7533040, upload-time = "2024-07-19T09:26:51.238Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b2/fe/81695a1aa331a842b582453b605175f419fe8540355886031328089d840a/sympy-1.13.1-py3-none-any.whl", hash = "sha256:db36cdc64bf61b9b24578b6f7bab1ecdd2452cf008f34faa33776680c26d66f8", size = 6189177, upload-time = "2024-07-19T09:26:48.863Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "torch"
|
||||||
|
version = "2.6.0+cu124"
|
||||||
|
source = { registry = "https://download.pytorch.org/whl/cu124" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "filelock" },
|
||||||
|
{ name = "fsspec" },
|
||||||
|
{ name = "jinja2" },
|
||||||
|
{ name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
|
||||||
|
{ name = "networkx", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
|
||||||
|
{ name = "nvidia-cublas-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-cuda-cupti-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-cuda-nvrtc-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-cuda-runtime-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-cudnn-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-cufft-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-curand-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-cusolver-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-cusparse-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-cusparselt-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-nccl-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-nvjitlink-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "nvidia-nvtx-cu12", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "setuptools", marker = "python_full_version >= '3.12'" },
|
||||||
|
{ name = "sympy" },
|
||||||
|
{ name = "triton", marker = "platform_machine == 'x86_64' and sys_platform == 'linux'" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://download-r2.pytorch.org/whl/cu124/torch-2.6.0%2Bcu124-cp310-cp310-linux_x86_64.whl", hash = "sha256:7f2ba7f7c0459320a521696f6b5bccc187f59890b23c9dfb6c49b0b87c6bfc97", upload-time = "2025-01-30T00:53:02Z" },
|
||||||
|
{ url = "https://download-r2.pytorch.org/whl/cu124/torch-2.6.0%2Bcu124-cp310-cp310-win_amd64.whl", hash = "sha256:7cc45c5b39d74875cfafe908b7f55c544147cc16b01e795feb2fe766583efe78", upload-time = "2025-01-30T00:53:32Z" },
|
||||||
|
{ url = "https://download-r2.pytorch.org/whl/cu124/torch-2.6.0%2Bcu124-cp311-cp311-linux_x86_64.whl", hash = "sha256:d4c3e9a8d31a7c0fcbb9da17c31a1917e1fac26c566a4cfbd8c9568ad7cade79", upload-time = "2025-01-30T00:55:01Z" },
|
||||||
|
{ url = "https://download-r2.pytorch.org/whl/cu124/torch-2.6.0%2Bcu124-cp311-cp311-win_amd64.whl", hash = "sha256:6a1fb2714e9323f11edb6e8abf7aad5f79e45ad25c081cde87681a18d99c29eb", upload-time = "2025-01-30T00:55:31Z" },
|
||||||
|
{ url = "https://download-r2.pytorch.org/whl/cu124/torch-2.6.0%2Bcu124-cp312-cp312-linux_x86_64.whl", hash = "sha256:a393b506844035c0dac2f30ea8478c343b8e95a429f06f3b3cadfc7f53adb597", upload-time = "2025-01-30T00:57:08Z" },
|
||||||
|
{ url = "https://download-r2.pytorch.org/whl/cu124/torch-2.6.0%2Bcu124-cp312-cp312-win_amd64.whl", hash = "sha256:3313061c1fec4c7310cf47944e84513dcd27b6173b72a349bb7ca68d0ee6e9c0", upload-time = "2025-01-30T00:57:40Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "triton"
|
||||||
|
version = "3.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/01/65/3ffa90e158a2c82f0716eee8d26a725d241549b7d7aaf7e4f44ac03ebd89/triton-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3e54983cd51875855da7c68ec05c05cf8bb08df361b1d5b69e05e40b0c9bd62", size = 253090354, upload-time = "2025-01-22T19:12:21.872Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a7/2e/757d2280d4fefe7d33af7615124e7e298ae7b8e3bc4446cdb8e88b0f9bab/triton-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8009a1fb093ee8546495e96731336a33fb8856a38e45bb4ab6affd6dbc3ba220", size = 253157636, upload-time = "2025-01-22T19:12:51.322Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/06/00/59500052cb1cf8cf5316be93598946bc451f14072c6ff256904428eaf03c/triton-3.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d9b215efc1c26fa7eefb9a157915c92d52e000d2bf83e5f69704047e63f125c", size = 253159365, upload-time = "2025-01-22T19:13:24.648Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.15.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||||
|
]
|
||||||
Loading…
x
Reference in New Issue
Block a user