Skip to content

Commit 76f9001

Browse files
authored
[CRL] Support pool-only registration and optimize regpool containers (#482)
1 parent 5cc6c42 commit 76f9001

11 files changed

Lines changed: 817 additions & 316 deletions

File tree

.github/workflows/test.yml

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Run Container and Execute Tests
1+
name: Perf Tests in Container
22

33
on:
44
push:
@@ -8,8 +8,12 @@ on:
88
branches:
99
- main
1010

11+
env:
12+
MPI_HOME: /usr/local/mpi
13+
PERF_BIN: /__w/FlagCX/FlagCX/test/perf/host_api/build/bin
14+
1115
jobs:
12-
test-in-container:
16+
perf-test:
1317
runs-on: [self-hosted, cx-build]
1418
container:
1519
image: localhost:5000/flagscale:cuda12.8.1-cudnn9.7.1-python3.12-torch2.7.0-time2507111538
@@ -32,42 +36,70 @@ jobs:
3236
submodules: true
3337
set-safe-directory: true
3438

35-
- name: Set up Python and Install Dependencies
39+
- name: Build FlagCX
3640
run: |
37-
apt update -y
38-
apt-get install -y python3 python3-pip python3-venv git
39-
python3 -m venv venv
40-
. venv/bin/activate
4141
cd /__w/FlagCX/FlagCX
42-
git config --global --add safe.directory /__w/FlagCX/FlagCX
43-
pip install setuptools pre-commit
44-
pre-commit install
42+
make -j$(nproc) USE_NVIDIA=1
43+
44+
- name: Build perf tests
45+
run: |
46+
cd /__w/FlagCX/FlagCX/test/perf
47+
make -j$(nproc) USE_NVIDIA=1
4548
46-
- name: Run Code Format Check with pre-commit
49+
- name: Wait for GPU
50+
shell: bash
4751
run: |
4852
cd /__w/FlagCX/FlagCX
49-
. venv/bin/activate
50-
apt update -y
51-
apt-get install clang-format -y
52-
git fetch --all
53-
if [ -n "$GITHUB_HEAD_REF" ] && [ -n "$GITHUB_BASE_REF" ]; then
54-
from_ref="origin/$GITHUB_HEAD_REF"
55-
to_ref="origin/$GITHUB_BASE_REF"
56-
echo "From reference: $from_ref; To reference: $to_ref"
57-
pre-commit run --from-ref "$from_ref" --to-ref "$to_ref"
58-
fi
59-
continue-on-error: false
53+
source test/script/_gpu_check.sh
54+
wait_for_gpu
55+
56+
- name: "Perf tests (homoRunner)"
57+
run: |
58+
export PATH=$MPI_HOME/bin:$PATH
59+
export LD_LIBRARY_PATH=/__w/FlagCX/FlagCX/build/lib:$LD_LIBRARY_PATH
60+
set -e
61+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_alltoall -b 128M -e 1G -f 2 -p 1
62+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_alltoallv -b 128M -e 1G -f 2 -p 1
63+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_sendrecv -b 128M -e 1G -f 2 -p 1
64+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_allreduce -b 128M -e 1G -f 2 -p 1
65+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_allgather -b 128M -e 1G -f 2 -p 1
66+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_reducescatter -b 128M -e 1G -f 2 -p 1
67+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_broadcast -b 128M -e 1G -f 2 -r 0 -p 1
68+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_gather -b 128M -e 1G -f 2 -r 0 -p 1
69+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_scatter -b 128M -e 1G -f 2 -r 0 -p 1
70+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_reduce -b 128M -e 1G -f 2 -r 0 -p 1
6071
61-
- name: Check the current working directory
72+
- name: "Perf tests (uniRunner)"
6273
run: |
63-
echo "Current directory: $(pwd)"
64-
ls -l ./test/script
74+
export PATH=$MPI_HOME/bin:$PATH
75+
export LD_LIBRARY_PATH=/__w/FlagCX/FlagCX/build/lib:$LD_LIBRARY_PATH
76+
set -e
77+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_USE_HETERO_COMM=1 $PERF_BIN/perf_alltoall -b 128M -e 1G -f 2 -p 1
78+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_USE_HETERO_COMM=1 $PERF_BIN/perf_alltoallv -b 128M -e 1G -f 2 -p 1
79+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_USE_HETERO_COMM=1 $PERF_BIN/perf_sendrecv -b 128M -e 1G -f 2 -p 1
80+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_USE_HETERO_COMM=1 $PERF_BIN/perf_allgather -b 128M -e 1G -f 2 -p 1
81+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_USE_HETERO_COMM=1 $PERF_BIN/perf_broadcast -b 128M -e 1G -f 2 -r 0 -p 1
82+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_USE_HETERO_COMM=1 $PERF_BIN/perf_gather -b 128M -e 1G -f 2 -r 0 -p 1
83+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_USE_HETERO_COMM=1 $PERF_BIN/perf_scatter -b 128M -e 1G -f 2 -r 0 -p 1
6584
66-
- name: Ensure script has execute permissions
67-
run: chmod +x /__w/FlagCX/FlagCX/test/script/auto_script.sh
85+
- name: "Registration -R 1 (homoRunner)"
86+
run: |
87+
export PATH=$MPI_HOME/bin:$PATH
88+
export LD_LIBRARY_PATH=/__w/FlagCX/FlagCX/build/lib:$LD_LIBRARY_PATH
89+
mpirun -np 8 --allow-run-as-root $PERF_BIN/perf_allreduce -b 128M -e 1G -f 2 -p 1 -R 1
6890
69-
- name: Run Auto Test Script in Container
91+
- name: "Registration -R 1 (uniRunner P2P)"
7092
run: |
71-
cd /__w/FlagCX/FlagCX
72-
./test/script/auto_script.sh
93+
export PATH=$MPI_HOME/bin:$PATH
94+
export LD_LIBRARY_PATH=/__w/FlagCX/FlagCX/build/lib:$LD_LIBRARY_PATH
95+
set -e
96+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_VMM_ENABLE=0 -x FLAGCX_USE_HETERO_COMM=1 $PERF_BIN/perf_sendrecv -b 128M -e 1G -f 2 -p 1 -R 1
97+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_VMM_ENABLE=0 -x FLAGCX_USE_HETERO_COMM=1 $PERF_BIN/perf_alltoall -b 128M -e 1G -f 2 -p 1 -R 1
7398
99+
- name: "Registration -R 1 (uniRunner NET)"
100+
run: |
101+
export PATH=$MPI_HOME/bin:$PATH
102+
export LD_LIBRARY_PATH=/__w/FlagCX/FlagCX/build/lib:$LD_LIBRARY_PATH
103+
set -e
104+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_VMM_ENABLE=0 -x FLAGCX_USE_HETERO_COMM=1 -x FLAGCX_P2P_DISABLE=1 $PERF_BIN/perf_sendrecv -b 128M -e 1G -f 2 -p 1 -R 1
105+
mpirun -np 8 --allow-run-as-root -x FLAGCX_MEM_ENABLE=1 -x FLAGCX_VMM_ENABLE=0 -x FLAGCX_USE_HETERO_COMM=1 -x FLAGCX_P2P_DISABLE=1 $PERF_BIN/perf_alltoall -b 128M -e 1G -f 2 -p 1 -R 1

flagcx/core/include/reg_pool.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
#include "flagcx.h"
77
#include "net.h"
88
#include "register.h"
9-
#include <map>
9+
#include <memory>
1010
#include <unistd.h>
11+
#include <unordered_map>
1112

1213
class flagcxRegPool {
1314
public:
15+
static constexpr uintptr_t GLOBAL_POOL_KEY = 0; // nullptr comm maps here
16+
1417
flagcxRegPool();
1518
~flagcxRegPool();
1619

@@ -23,18 +26,22 @@ class flagcxRegPool {
2326
struct flagcxProxyConnector *proxyConn);
2427
flagcxResult_t removeRegItemP2pHandles(void *comm, flagcxRegItem *reg);
2528
flagcxResult_t removeAllP2pHandles(void *comm);
29+
flagcxResult_t removeAllNetHandles(void *comm);
2630
flagcxResult_t registerBuffer(void *comm, void *data, size_t length);
2731
flagcxResult_t deregisterBuffer(void *comm, void *handle);
28-
std::map<uintptr_t, std::map<uintptr_t, flagcxRegItem *>> &getGlobalMap();
32+
std::unordered_map<uintptr_t, std::unordered_map<uintptr_t, flagcxRegItem *>>
33+
&getGlobalMap();
2934
flagcxRegItem *getItem(const void *comm, void *data);
3035
void dump();
3136

3237
private:
3338
void mapRegItemPages(uintptr_t commKey, flagcxRegItem *reg);
34-
std::map<uintptr_t, std::map<uintptr_t, flagcxRegItem *>>
39+
std::unordered_map<uintptr_t, std::unordered_map<uintptr_t, flagcxRegItem *>>
3540
regMap; // <commPtr, <pageBasePtr, regItemPtr>>
36-
std::map<uintptr_t, std::list<flagcxRegItem>>
37-
regPool; // <commPtr, regItemList>
41+
std::unordered_map<
42+
uintptr_t, std::unordered_map<uintptr_t, std::unique_ptr<flagcxRegItem>>>
43+
regPool; // <commPtr, <beginAddr, regItem>> (only GLOBAL_POOL_KEY owns
44+
// data)
3845
uintptr_t pageSize;
3946
};
4047

flagcx/core/include/register.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
#include "core.h"
55
#include "device.h"
6-
#include <list>
6+
#include <unordered_map>
7+
#include <vector>
78

89
#define FLAGCX_IPC_HANDLE_SIZE 64
910

@@ -28,11 +29,13 @@ struct netRegInfo {
2829
struct flagcxRegNetHandle {
2930
void *handle = NULL;
3031
struct flagcxProxyConnector *proxyConn = NULL;
32+
void *ownerComm = NULL; // comm that registered this handle
3133
};
3234

3335
struct flagcxRegP2pHandle {
3436
void *handle = NULL;
3537
struct flagcxProxyConnector *proxyConn = NULL;
38+
void *ownerComm = NULL; // comm that registered this handle
3639
};
3740

3841
struct flagcxIpcImpInfo {
@@ -60,9 +63,11 @@ struct flagcxRegItem {
6063
uintptr_t beginAddr = 0;
6164
uintptr_t endAddr = 0;
6265
int refCount = 1;
63-
std::list<std::pair<flagcxRegNetHandle, flagcxRegP2pHandle>> handles;
64-
void *homoRegHandle = nullptr; // backend CCL handle (homo path only)
65-
flagcxIpcHandleData ipcHandleData = {}; // IPC handle bytes (both paths)
66+
std::vector<std::pair<flagcxRegNetHandle, flagcxRegP2pHandle>> handles;
67+
flagcxIpcHandleData localIpcHandleData =
68+
{}; // sender's IPC handle bytes (hetero path)
69+
std::unordered_map<uintptr_t, void *>
70+
homoRegHandles; // commKey → backend CCL handle
6671
};
6772

6873
struct flagcxReg {

flagcx/core/init.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,9 @@ flagcxResult_t flagcxHeteroCommUserRank(const flagcxHeteroComm_t comm,
465465

466466
flagcxResult_t flagcxHeteroCommDestroy(flagcxHeteroComm_t comm) {
467467
FLAGCXCHECK(flagcxHeteroRmaProxyStop(comm));
468-
// Clean up P2P IPC handles while proxy is still alive and peerSocks valid
468+
// Clean up P2P/Net handles while proxy is still alive and peerSocks valid
469469
FLAGCXCHECK(globalRegPool.removeAllP2pHandles(comm));
470+
FLAGCXCHECK(globalRegPool.removeAllNetHandles(comm));
470471
// Stop: send stop + close peerSocks
471472
FLAGCXCHECK(flagcxProxyStop(comm));
472473
// Destroy: join thread, free proxy resources

flagcx/core/net.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ static flagcxResult_t netRegisterBuffer(flagcxHeteroComm *comm,
430430
peerProxyConn = &peerConn->proxyConn;
431431
for (auto it = regRecord->handles.begin(); it != regRecord->handles.end();
432432
it++) {
433-
if (it->first.proxyConn == peerProxyConn && it->first.handle) {
433+
if (it->first.proxyConn == peerProxyConn && it->first.handle &&
434+
it->first.ownerComm == comm) {
434435
found = true;
435436
outHandle[p] = it->first.handle;
436437
*outRegBufFlag = 1;

flagcx/core/p2p.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -764,10 +764,11 @@ static flagcxResult_t p2pRegisterBuffer(flagcxHeteroComm *comm,
764764
for (int p = 0; p < nPeers; p++) {
765765
int peerRank = peerRanks[p];
766766

767-
// Check cache: existing info with handleReady for this peer
767+
// Check cache: existing info with handleReady for this peer (this comm
768+
// only)
768769
flagcxIpcRegInfo *existingInfo = NULL;
769770
for (auto &handlePair : regItem->handles) {
770-
if (handlePair.second.handle) {
771+
if (handlePair.second.handle && handlePair.second.ownerComm == comm) {
771772
flagcxIpcRegInfo *info = (flagcxIpcRegInfo *)handlePair.second.handle;
772773
if (info->peerRank == peerRank) {
773774
existingInfo = info;
@@ -817,9 +818,9 @@ static flagcxResult_t p2pRegisterBuffer(flagcxHeteroComm *comm,
817818
} else if (legacyIpcCap) {
818819
// Different process: get IPC handle for our own buffer
819820
char zeros[sizeof(flagcxIpcHandleData)] = {};
820-
if (memcmp(&regItem->ipcHandleData, zeros,
821+
if (memcmp(&regItem->localIpcHandleData, zeros,
821822
sizeof(flagcxIpcHandleData)) != 0) {
822-
memcpy(&handleData, &regItem->ipcHandleData,
823+
memcpy(&handleData, &regItem->localIpcHandleData,
823824
sizeof(flagcxIpcHandleData));
824825
} else {
825826
flagcxIpcMemHandle_t ipcHandle = NULL;
@@ -832,7 +833,7 @@ static flagcxResult_t p2pRegisterBuffer(flagcxHeteroComm *comm,
832833
fail);
833834
if (handleSize <= sizeof(flagcxIpcHandleData)) {
834835
memcpy(&handleData, ipcHandle, handleSize);
835-
memcpy(&regItem->ipcHandleData, ipcHandle, handleSize);
836+
memcpy(&regItem->localIpcHandleData, ipcHandle, handleSize);
836837
}
837838
deviceAdaptor->ipcMemHandleFree(ipcHandle);
838839
}

0 commit comments

Comments
 (0)