Skip to content

Commit cf35099

Browse files
committed
Merge branch 'main' into binyli/allgather-fix-rocm
2 parents 8bd9d7e + ef4168d commit cf35099

61 files changed

Lines changed: 2826 additions & 193 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.azure-pipelines/codecov.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
gpuArch: '90'
7676

7777
- job: CodeCoverageMI300X
78-
timeoutInMinutes: 40
78+
timeoutInMinutes: 60
7979
pool:
8080
name: msccl-ci-mi300x
8181
variables:
@@ -84,8 +84,6 @@ jobs:
8484
matrix:
8585
rocm6_2:
8686
containerImage: ghcr.io/microsoft/mscclpp/mscclpp:base-dev-rocm6.2
87-
rocm7_2:
88-
containerImage: ghcr.io/microsoft/mscclpp/mscclpp:base-dev-rocm7.2
8987

9088
container:
9189
image: $(containerImage)

.azure-pipelines/mnnvl-test.yml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
trigger:
2+
branches:
3+
include:
4+
- main
5+
- release/*
6+
paths:
7+
exclude:
8+
- .devcontainer/**
9+
- .github/**
10+
- docker/**
11+
- docs/**
12+
- '**/*.md'
13+
14+
# Do not run multi-nodes-test for PR, we can trigger it manually
15+
pr: none
16+
17+
parameters:
18+
- name: vmssName
19+
type: string
20+
default: 'mnnvl' # unused on pilot (StartVMSS gated off); kept only to satisfy deploy.yml
21+
- name: hostEntries
22+
type: string
23+
default: |
24+
10.0.5.145 DSM121082302011
25+
10.0.5.150 DSM121082302014
26+
10.0.5.177 DSM121082301013
27+
10.0.5.225 DSM121082301032
28+
# Subnet (or interface name) passed to Open MPI's btl_tcp_if_include so every
29+
# rank selects the routable interface matching the node IPs in hostEntries.
30+
- name: mpiTcpIfInclude
31+
type: string
32+
default: '10.0.5.0/24'
33+
34+
variables:
35+
- group: mscclpp
36+
37+
jobs:
38+
- job: MultiNodesTest
39+
displayName: Multi nodes test
40+
strategy:
41+
matrix:
42+
cuda13:
43+
containerImage: ghcr.io/microsoft/mscclpp/mscclpp:base-dev-cuda13.0
44+
pool:
45+
name: msccl-ci-gb200
46+
container:
47+
image: $[ variables['containerImage'] ]
48+
49+
steps:
50+
- task: Bash@3
51+
displayName: Node connectivity check
52+
inputs:
53+
targetType: 'inline'
54+
script: |
55+
set -x
56+
echo "Agent egress IP:"; curl -s -m 5 ifconfig.me; echo
57+
while IFS= read -r line; do
58+
ip=$(awk 'NF>=1{print $1}' <<< "$line")
59+
[ -z "$ip" ] && continue
60+
timeout 10 bash -c "cat < /dev/null > /dev/tcp/${ip}/22" \
61+
&& echo "${ip}:22 OPEN" || echo "${ip}:22 UNREACHABLE"
62+
done <<< "${{ parameters.hostEntries }}"
63+
64+
- task: Bash@3
65+
displayName: Add HostEntry
66+
inputs:
67+
targetType: 'inline'
68+
script: |
69+
while IFS= read -r line; do
70+
[ -z "$line" ] && continue
71+
if ! grep -qxF "$line" /etc/hosts; then
72+
echo "Adding to /etc/hosts: $line"
73+
echo "$line" | sudo tee -a /etc/hosts
74+
else
75+
echo "Entry already exists: $line"
76+
fi
77+
done <<< "${{ parameters.hostEntries }}"
78+
79+
- task: Bash@3
80+
displayName: Generate deploy files
81+
inputs:
82+
targetType: 'inline'
83+
script: |
84+
set -e
85+
DEPLOY_DIR="$(System.DefaultWorkingDirectory)/test/deploy"
86+
# First NVLink pair (2 nodes) from hostEntries; use $1 (the IP) so the
87+
# names resolve inside the container too (the DSM hostnames are only in
88+
# the agent's /etc/hosts). Bump to more nodes by parsing further lines.
89+
NODE0=$(awk 'NF>=2{print $1; exit}' <<< "${{ parameters.hostEntries }}")
90+
NODE1=$(awk 'NF>=2{c++} c==2{print $1; exit}' <<< "${{ parameters.hostEntries }}")
91+
92+
echo "Host ${NODE0}
93+
Port 22345
94+
IdentityFile /root/mscclpp/sshkey
95+
StrictHostKeyChecking no
96+
Host ${NODE1}
97+
Port 22345
98+
IdentityFile /root/mscclpp/sshkey
99+
StrictHostKeyChecking no" > "${DEPLOY_DIR}/config"
100+
101+
printf '%s\n%s\n' "azhpcuser@${NODE0}" "azhpcuser@${NODE1}" > "${DEPLOY_DIR}/hostfile"
102+
103+
printf '%s\n%s\n' "${NODE0}" "${NODE1}" > "${DEPLOY_DIR}/hostfile_mpi"
104+
105+
# Publish the head node so the run steps can target it without hardcoding.
106+
echo "##vso[task.setvariable variable=headNode]${NODE0}"
107+
108+
- template: templates/deploy.yml
109+
parameters:
110+
subscription: mscclpp-ci-h100
111+
vmssName: ${{ parameters.vmssName }}
112+
pilot: true
113+
resourceGroup: mscclpp
114+
gpuArch: '100a'
115+
cmakeArgs: '-DMSCCLPP_USE_IB=OFF'
116+
deployArgs: 'multi-node-test false cuda'
117+
118+
- template: templates/ut-gb200.yml
119+
parameters:
120+
user: azhpcuser
121+
headNode: $(headNode)
122+
hostfile: $(System.DefaultWorkingDirectory)/test/deploy/hostfile
123+
gpuArch: '100a'
124+
mpiTcpIfInclude: ${{ parameters.mpiTcpIfInclude }}
125+
126+
- template: templates/run-remote-task.yml
127+
parameters:
128+
name: RunCollectivebenchmarks
129+
displayName: Run Collective Benchmarks
130+
runRemoteArgs: '--hostfile $(System.DefaultWorkingDirectory)/test/deploy/hostfile --host $(headNode) --user azhpcuser'
131+
remoteScript: |
132+
mpirun --allow-run-as-root --bind-to numa -hostfile /root/mscclpp/test/deploy/hostfile_mpi -mca btl_tcp_if_include ${{ parameters.mpiTcpIfInclude }} -np 8 -npernode 4 \
133+
-x MSCCLPP_DEBUG=WARN -x LD_LIBRARY_PATH=/root/mscclpp/build/lib:$LD_LIBRARY_PATH -x MSCCLPP_HOME=/root/mscclpp \
134+
/root/venv/bin/python3 -m mscclpp_benchmark.bench_collective --collective allreduce --dtype float16 --symmetric-memory
135+
mpirun --allow-run-as-root --bind-to numa -hostfile /root/mscclpp/test/deploy/hostfile_mpi -mca btl_tcp_if_include ${{ parameters.mpiTcpIfInclude }} -np 8 -npernode 4 \
136+
-x MSCCLPP_DEBUG=WARN -x LD_LIBRARY_PATH=/root/mscclpp/build/lib:$LD_LIBRARY_PATH -x MSCCLPP_HOME=/root/mscclpp \
137+
/root/venv/bin/python3 -m mscclpp_benchmark.bench_collective --collective allgather --dtype float16 --symmetric-memory
138+
mpirun --allow-run-as-root --bind-to numa -hostfile /root/mscclpp/test/deploy/hostfile_mpi -mca btl_tcp_if_include ${{ parameters.mpiTcpIfInclude }} -np 8 -npernode 4 \
139+
-x MSCCLPP_DEBUG=WARN -x LD_LIBRARY_PATH=/root/mscclpp/build/lib:$LD_LIBRARY_PATH -x MSCCLPP_HOME=/root/mscclpp \
140+
/root/venv/bin/python3 -m mscclpp_benchmark.bench_collective --collective allgather --dtype float16 --symmetric-memory --buffer-mode out-of-place

.azure-pipelines/templates/codecov.yml

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,26 @@ steps:
3232
export GCOV_PREFIX=/root/mscclpp
3333
export GCOV_PREFIX_STRIP=$STRIP_COUNT
3434
35+
UNIT_TEST_ARGS=""
36+
MP_UNIT_TEST_ARGS="--exclude-perf-tests"
37+
# Debug coverage makes the GDRCopy host-side atomic signaling tests
38+
# prohibitively slow on SM90. A100 coverage continues to exercise them;
39+
# ROCm runs its separate HostNoAtomic implementation with the longer timeout.
40+
if [ "${{ parameters.gpuArch }}" = "90" ]; then
41+
UNIT_TEST_ARGS="--filter=-GdrMapTest.AtomicStoreCounterPingPong"
42+
MP_UNIT_TEST_ARGS="${MP_UNIT_TEST_ARGS} --filter=-IbHostNoAtomicMode"
43+
fi
44+
3545
echo "Running unit_tests..."
36-
./build/bin/unit_tests
46+
./build/bin/unit_tests ${UNIT_TEST_ARGS}
3747
echo "unit_tests: PASSED"
3848
3949
echo "Running mp_unit_tests -np 2..."
40-
mpirun --allow-run-as-root -tag-output -np 2 ./build/bin/mp_unit_tests --exclude-perf-tests
50+
mpirun --allow-run-as-root -tag-output -np 2 ./build/bin/mp_unit_tests ${MP_UNIT_TEST_ARGS}
4151
echo "mp_unit_tests -np 2: PASSED"
4252
4353
echo "Running mp_unit_tests -np 4..."
44-
mpirun --allow-run-as-root -tag-output -np 4 ./build/bin/mp_unit_tests --exclude-perf-tests
54+
mpirun --allow-run-as-root -tag-output -np 4 ./build/bin/mp_unit_tests ${MP_UNIT_TEST_ARGS}
4555
echo "mp_unit_tests -np 4: PASSED"
4656
4757
- template: run-remote-task.yml
@@ -50,6 +60,27 @@ steps:
5060
displayName: Capture coverage data with lcov
5161
remoteScript: |
5262
BUILD_PREFIX=$(cat build/BUILD_PREFIX)
63+
CURRENT_PREFIX=$(pwd -P)
64+
65+
# Coverage metadata embeds the Azure build path, so restore that path
66+
# after the source tree and build artifacts are copied to the remote VM.
67+
if [ "${BUILD_PREFIX}" != "${CURRENT_PREFIX}" ]; then
68+
mkdir -p "$(dirname "${BUILD_PREFIX}")"
69+
if [ -L "${BUILD_PREFIX}" ]; then
70+
rm "${BUILD_PREFIX}"
71+
ln -s "${CURRENT_PREFIX}" "${BUILD_PREFIX}"
72+
elif [ -e "${BUILD_PREFIX}" ]; then
73+
echo "ERROR: ${BUILD_PREFIX} exists and cannot be mapped to ${CURRENT_PREFIX}."
74+
exit 1
75+
else
76+
ln -s "${CURRENT_PREFIX}" "${BUILD_PREFIX}"
77+
fi
78+
fi
79+
80+
if [ ! -r "${BUILD_PREFIX}/CMakeLists.txt" ]; then
81+
echo "ERROR: coverage source root ${BUILD_PREFIX} is not readable."
82+
exit 1
83+
fi
5384
5485
GCOV_TOOL_ARG=""
5586
if [ "${{ parameters.platform }}" = "rocm" ]; then
@@ -60,20 +91,22 @@ steps:
6091
GCOV_TOOL_ARG="--gcov-tool ${GCOV_WRAPPER}"
6192
fi
6293
63-
lcov --version
64-
LCOV_CAPTURE_ARGS=""
65-
if lcov --help 2>&1 | grep -q "inconsistent"; then
66-
LCOV_CAPTURE_ARGS="--ignore-errors inconsistent"
94+
LCOV_VERSION=$(lcov --version 2>&1)
95+
echo "${LCOV_VERSION}"
96+
LCOV_MAJOR_VERSION=$(echo "${LCOV_VERSION}" | sed -n 's/.*LCOV version \([0-9][0-9]*\).*/\1/p')
97+
LCOV_COMMON_ARGS=""
98+
if [ "${LCOV_MAJOR_VERSION:-0}" -ge 2 ]; then
99+
LCOV_COMMON_ARGS="--ignore-errors inconsistent"
67100
fi
68101
69-
lcov ${GCOV_TOOL_ARG} --directory . --capture --output-file coverage.info ${LCOV_CAPTURE_ARGS}
102+
lcov ${GCOV_TOOL_ARG} --directory . --capture --output-file coverage.info ${LCOV_COMMON_ARGS}
70103
if [ ! -s coverage.info ]; then
71104
echo "ERROR: coverage.info was not generated."
72105
exit 1
73106
fi
74107
75-
lcov ${GCOV_TOOL_ARG} --extract coverage.info "${BUILD_PREFIX}/src/*" "${BUILD_PREFIX}/include/mscclpp/*" --output-file coverage.info
76-
lcov --list coverage.info
108+
lcov ${GCOV_TOOL_ARG} --extract coverage.info "${BUILD_PREFIX}/src/*" "${BUILD_PREFIX}/include/mscclpp/*" --output-file coverage.info ${LCOV_COMMON_ARGS}
109+
lcov --summary coverage.info ${LCOV_COMMON_ARGS}
77110
ls -la coverage.info
78111
79112
- task: Bash@3

.azure-pipelines/templates/deploy.yml

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ parameters:
66
- name: resourceGroup
77
type: string
88
default: mscclpp
9+
- name: pilot
10+
type: boolean
11+
default: false
912
# Build parameters
1013
- name: platform
1114
type: string
@@ -136,15 +139,16 @@ steps:
136139
sudo apt-get update -y
137140
sudo apt-get install pssh -y
138141
139-
- task: AzureCLI@2
140-
name: StartVMSS
141-
displayName: Start VMSS
142-
inputs:
143-
azureSubscription: ${{ parameters.subscription }}
144-
scriptType: bash
145-
scriptLocation: inlineScript
146-
inlineScript: |
147-
az vmss start --name ${{ parameters.vmssName }} --resource-group ${{ parameters.resourceGroup }}
142+
- ${{ if not(parameters.pilot) }}:
143+
- task: AzureCLI@2
144+
name: StartVMSS
145+
displayName: Start VMSS
146+
inputs:
147+
azureSubscription: ${{ parameters.subscription }}
148+
scriptType: bash
149+
scriptLocation: inlineScript
150+
inlineScript: |
151+
az vmss start --name ${{ parameters.vmssName }} --resource-group ${{ parameters.resourceGroup }}
148152
149153
# 4. Deploy test environment
150154
- task: Bash@3
@@ -153,5 +157,5 @@ steps:
153157
inputs:
154158
targetType: filePath
155159
filePath: test/deploy/deploy.sh
156-
arguments: ${{ parameters.deployArgs }} ${{ parameters.containerName }} ${{ parameters.sglangImage }}
160+
arguments: ${{ parameters.deployArgs }} "${{ parameters.containerName }}" "${{ parameters.sglangImage }}" ${{ parameters.pilot }}
157161
workingDirectory: '$(System.DefaultWorkingDirectory)'
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
parameters:
2+
- name: user
3+
type: string
4+
default: 'azhpcuser'
5+
- name: headNode
6+
type: string
7+
- name: hostfile
8+
type: string
9+
default: '$(System.DefaultWorkingDirectory)/test/deploy/hostfile'
10+
- name: gpuArch
11+
type: string
12+
default: '100a'
13+
- name: mpiTcpIfInclude
14+
type: string
15+
default: '10.0.5.0/24'
16+
- name: singleNodeNps
17+
type: string
18+
default: '2 4'
19+
- name: filter
20+
type: string
21+
default: '-Ib'
22+
- name: runCrossNodeBootstrap
23+
type: boolean
24+
default: true
25+
- name: crossNodeFilter
26+
type: string
27+
default: '-Communicator,Ib'
28+
- name: bootstrapPort
29+
type: number
30+
default: 50053
31+
- name: runUnitTests
32+
type: boolean
33+
default: true
34+
35+
steps:
36+
# Rebuild the C++ tests natively on every node so the binaries are aarch64.
37+
# The x86-64 CMakeCache.txt shipped from the agent is discarded (rm -rf build).
38+
- template: run-remote-task.yml
39+
parameters:
40+
name: BuildGb200Tests
41+
displayName: Build unit tests on GB200 nodes
42+
runRemoteArgs: '--hostfile ${{ parameters.hostfile }} --user ${{ parameters.user }}'
43+
remoteScript: |
44+
rm -rf build
45+
mkdir -p build && cd build
46+
cmake \
47+
-DCMAKE_BUILD_TYPE=Release \
48+
-DMSCCLPP_BYPASS_GPU_CHECK=ON \
49+
-DMSCCLPP_USE_CUDA=ON \
50+
-DMSCCLPP_BUILD_TESTS=ON \
51+
-DMSCCLPP_GPU_ARCHS=${{ parameters.gpuArch }} \
52+
-DMSCCLPP_USE_IB=OFF ..
53+
make -j unit_tests mp_unit_tests
54+
55+
- ${{ if parameters.runUnitTests }}:
56+
- template: run-remote-task.yml
57+
parameters:
58+
name: Gb200UnitTests
59+
displayName: Run mscclpp unit tests
60+
runRemoteArgs: '--host ${{ parameters.headNode }} --user ${{ parameters.user }}'
61+
remoteScript: |
62+
./build/bin/unit_tests
63+
64+
# Run mp_unit_tests single-node on the head node across the rank ladder. No
65+
# hostfile / ip_port needed: all ranks are local, so loopback bootstrap works and
66+
# every fixture has a working intra-node transport (IPC / NVLink).
67+
- template: run-remote-task.yml
68+
parameters:
69+
name: Gb200MpUnitTests
70+
displayName: Run mscclpp multi-process unit tests (single-node)
71+
runRemoteArgs: '--host ${{ parameters.headNode }} --user ${{ parameters.user }}'
72+
remoteScript: |
73+
for np in ${{ parameters.singleNodeNps }}; do
74+
echo "=== mp_unit_tests -np ${np} (single-node) ==="
75+
timeout -k 10 300 mpirun --allow-run-as-root -tag-output --bind-to numa -np ${np} \
76+
-x MSCCLPP_DEBUG=WARN -x LD_LIBRARY_PATH=/root/mscclpp/build/lib:$LD_LIBRARY_PATH -x MSCCLPP_HOME=/root/mscclpp \
77+
./build/bin/mp_unit_tests --filter=${{ parameters.filter }}
78+
done
79+
80+
# Cross-node pass: validate the multi-node TcpBootstrap rendezvous. mpirun spans
81+
# both nodes via the container hostfile; --ip_port points every rank at rank 0 on
82+
# the head node (the mp_unit_tests default of 127.0.0.1 only works single-node
83+
# and makes the *IpPortPair tests time out across nodes). crossNodeFilter keeps
84+
# this to the fixtures that work without cross-node IB.
85+
- ${{ if parameters.runCrossNodeBootstrap }}:
86+
- template: run-remote-task.yml
87+
parameters:
88+
name: Gb200MpBootstrapMultiNode
89+
displayName: Run mscclpp multi-process bootstrap tests (cross-node)
90+
runRemoteArgs: '--host ${{ parameters.headNode }} --user ${{ parameters.user }}'
91+
remoteScript: |
92+
timeout -k 10 300 mpirun --allow-run-as-root -tag-output --bind-to numa -hostfile /root/mscclpp/test/deploy/hostfile_mpi -mca btl_tcp_if_include ${{ parameters.mpiTcpIfInclude }} -np 8 -npernode 4 \
93+
-x MSCCLPP_DEBUG=WARN -x LD_LIBRARY_PATH=/root/mscclpp/build/lib:$LD_LIBRARY_PATH -x MSCCLPP_HOME=/root/mscclpp \
94+
./build/bin/mp_unit_tests --ip_port=${{ parameters.headNode }}:${{ parameters.bootstrapPort }} --filter=${{ parameters.crossNodeFilter }}

0 commit comments

Comments
 (0)