MikroTik CRS812 breakout 400G sang DGX Spark: link 200G kịch trần ở 106 Gb/s và NCCL rơi về Socket
Chúng tôi đang dựng bốn node DGX Spark cho distributed training và treo chúng vào một MikroTik CRS812-8DS-2DQ-2DDQ. Kế hoạch là một port 400G QSFP-DD trên switch cấp cho hai node ở 200G mỗi node, nên một vài sợi breakout là phủ hết cả cluster.
- MikroTik CRS812-8DS-2DQ-2DDQ, port QSFP-DD dùng ở chế độ breakout
- NADDOD Q2Q56-400G-CU2, DAC passive QSFP-DD 400G sang 2x QSFP56 200G
- node DGX Spark với ConnectX-7 on-board
- validate bằng iperf3 và nccl-tests all_reduce_perf
Cả hai đầu đều báo link 200GbE sạch, nhưng throughput chỉ nhỉnh hơn một nửa con số đó một chút:
# iperf3 -c <peer> -P 8
[SUM] 0.00-10.00 sec ... 106 Gbits/sec
single stream: ~30 Gbits/sec
# ip -br link
enp1s0f1np1 UP
enP2p1s0f1np1 UP
NCCL còn tệ hơn thế: all_reduce_perf báo Socket transport và bus bandwidth chỉ khoảng 2 GB/s trên cả bốn node, nên RDMA rõ ràng hoàn toàn không được dùng.
Những gì đã kiểm tra:
- tháo lắp lại và đổi cáp breakout giữa các port switch, số liệu y hệt
- tăng số stream lên, tổng vẫn ghim gần 106 Gb/s
- xác nhận switch báo port ở 200G, không phải 100G
Điều tôi cứ quay lại nghĩ là một port QSFP56 vật lý lại hiện thành hai interface logic trên node. Breakout chỉ đang cấp một nửa số lane cho mỗi node, hay một port 200G trên phần cứng này vốn phải trông như vậy?
Comments 7
Đúng chính xác là vậy, và cáp breakout hoàn toàn vô tội. Trên platform này port ConnectX-7 được gắn qua PCIe x4 và lộ ra thành hai nửa logic, mỗi nửa mang khoảng 100 Gb/s. Đủ 200G chỉ xuất hiện khi cả hai nửa cùng được tải một lúc, nên một lần chạy iperf3 với một địa chỉ duy nhất dừng lại ngay trên 100 Gb/s một chút là kết quả đúng như dự kiến chứ không phải lỗi.
Cách làm nó chạy được ở đây:
Khi cả hai nửa cùng mang traffic, bạn sẽ đạt gần line rate trên cặp đó, và nccl-tests all_reduce_perf sẽ báo một đẳng cấp bus bandwidth hoàn toàn khác một khi nó thôi không đi qua socket nữa.
Trước khi đổ lỗi cho cáp, bạn đang điều khiển hai interface đó chính xác thế nào? Bạn dán enp1s0f1np1 và enP2p1s0f1np1 đều là UP, nhưng iperf3 có nhắm vào cả hai không, hay chỉ cái nào đang mang địa chỉ?
Cũng đáng đăng thêm: MTU trên node và trên port CRS812, vì 1500 gây hại nặng ở tốc độ này, và nội dung của /etc/nccl.conf. Khi NCCL chọn Socket transport thì hầu như luôn là vì có gì đó trong file đó bảo nó đừng đụng vào đường IB, chứ không phải vì fabric hỏng.
Câu hỏi hợp lý. Chỉ enp1s0f1np1 có địa chỉ, nửa enP2p1s0f1np1 thì up nhưng chưa cấu hình, và mọi lần chạy iperf3 từ trước tới giờ đều nhắm vào đúng một địa chỉ đó. MTU là 1500 trên node và tôi cũng chưa đụng vào L2 MTU phía switch. Và đúng vậy, đây rồi:
Cái đó đã có sẵn trong image và tôi chưa từng nghi ngờ nó. Vậy 106 Gb/s có khả năng chỉ là một nửa port cộng thêm chút headroom?
Stack khác, nhưng kiểu bất ngờ giống nhau. Phía tôi là một ConnectX-6 (MT28908) chạy dưới RHEL 8.4, MLNX_OFED 5.7, firmware 20.32.2004, MFT 4.21; đầu xa là một Switch-IB 2 SB7800, và giữa hai bên là một splitter LinkX MCP7H50-H002R26 tách 200G xuống 2x100G. Port lên với
và cả mlxlink -d mlx5_0 -p 1 --speeds edr lẫn --speeds hdr đều chẳng thay đổi được gì. Hóa ra là một trần cứng trong silicon chứ không phải lỗi cấu hình: hàng EDR chỉ tạo được link rộng 1x hoặc 4x, còn splitter kiểu đó dựa vào nhóm 2x, thứ chỉ xuất hiện cùng với HDR. Nên hoặc là dùng một cáp EDR 4x thường vào switch đó, hoặc chuyển lên HDR nếu bắt buộc phải split.
Bài học cho breakout nói chung: xác định trước mỗi đầu thực sự tạo được nhóm lane nào trước khi đo bất cứ thứ gì.
Có một điều trong công thức ở trên đáng nói rõ ra, vì đó là chỗ người ta hay đánh mất thành quả lần nữa: MTU cũng phải khớp trên switch. Set 9000 trên host trong khi port vẫn cho qua frame 1500 byte chỉ mua cho bạn drop chứ không phải throughput. Set L2 MTU trên port CRS812 và xác nhận bằng một ping payload lớn trước khi chạy lại bất kỳ test nào.
Điểm về IPv6 cũng là câu chuyện tương tự. Khi cả hai nửa đều có địa chỉ và IPv6 vẫn để bật, bạn có thêm các entry GID trên mỗi port, và index mà test của bạn được bảo dùng chưa chắc là cái bạn nghĩ. Tắt IPv6 trên interface CX7 giữ cho bảng đó nhỏ và ổn định qua các lần reboot, điều này quan trọng hơn vẻ ngoài của nó khi bạn so sánh các lần chạy.
Đáng nhớ là một port breakout cứ nằm im ở trạng thái down là một con thú hoàn toàn khác so với của bạn. Trên một Arista DCS-7060CX-32S cũ (EOS 4.16.8FX-7060X), bốn sub-interface của tôi không hề có lỗi nào cả mà đơn giản là chẳng bao giờ lên link. Máy đang ở transceiver qsfp default-mode 4x10G trong khi đầu xa lại đưa ra 25G, và Et17/1 cứ nằm ở errdisabled cho tới khi rate được set bằng tay:
Trong cùng phiên đó một cáp Mellanox bị từ chối vì là transceiver chưa qualify và phải đổi sang một DAC QSFP28 100GBASE-CR4 tương thích Arista. Ở thái cực khác, một đồng nghiệp chưa bao giờ đưa được một breakout QDD-4X100G-2P5M lên trên một QFX5220-32CD chạy Junos 23.2R1-S1.8-EVO hướng tới một switch Mellanox, dù đã có một port profile được Port Checker validate và thử mọi biến thể FEC. Ít nhất của bạn còn negotiate và truyền được traffic.
Xác nhận đúng, và port chưa bao giờ hỏng cả. Tôi gán địa chỉ cho enP2p1s0f1np1 như một interface riêng, set MTU 9000 trên node và trên port switch, tắt IPv6 trên cả hai interface CX7 và bỏ NCCL_IB_DISABLE=1 ra khỏi /etc/nccl.conf.
Hai phiên iperf3 chạy song song, mỗi nửa một phiên, giờ cho tổng 196-198 Gb/s. all_reduce_perf trên cả bốn node báo bus bandwidth 23.76 GB/s và NCCL đang đi trên đường RDMA, không còn Socket transport trong log nữa. NADDOD Q2Q56-400G-CU2 hóa ra đã làm đúng việc của nó suốt từ đầu.