Skip to content

Commit 3887590

Browse files
committed
fix(device-ir): pre-allocate net contexts in DevComm, expand scalar IR tests
1 parent e5e538a commit 3887590

7 files changed

Lines changed: 664 additions & 13 deletions

File tree

bindings/ir/flagcx_device_scalar_ir_impl.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
/*************************************************************************
22
* Copyright (c) 2026 BAAI. All rights reserved.
33
*
4-
* FlagCX Device Scalar IR API — Implementation (Step 2: Coop + Team).
4+
* FlagCX Device Scalar IR API — Implementation.
55
*
6-
* This file implements the scalar cooperative group and team functions.
6+
* This file implements the scalar (S-suffixed) IR functions.
77
* It is included by the bitcode compilation unit alongside the existing
88
* flagcx_device_wrapper_impl.h.
9-
*
10-
* Remaining categories (barrier, net) will be added in subsequent steps.
119
************************************************************************/
1210
#ifndef FLAGCX_DEVICE_SCALAR_IR_IMPL_H_
1311
#define FLAGCX_DEVICE_SCALAR_IR_IMPL_H_
@@ -332,11 +330,12 @@ flagcxWorldBarrierSyncS(const void *netOpaque, flagcxCoopKind_t coopKind,
332330
FLAGCX_IR_EXTERN_C FLAGCX_DEVICE_INLINE_DECORATOR const void *
333331
flagcxDevNetGetFromCommS(const void *commOpaque, int idx) {
334332
const flagcxDevComm *comm = (const flagcxDevComm *)commOpaque;
335-
// When always-inlined, the static local is promoted into the caller's
336-
// scope by LLVM. This provides stable storage for the returned pointer.
337-
static flagcxDevNet storage;
338-
::new (&storage) flagcxDevNet(*comm, idx);
339-
return &storage;
333+
// Return pointer into pre-allocated device array (built by
334+
// flagcxDevCommGetDevicePtr). Each entry is a fully-constructed
335+
// flagcxDevNet for that context index — no per-call construction.
336+
const flagcxDevNet *nets = (const flagcxDevNet *)comm->_netContexts;
337+
int safeIdx = (comm->_contextCount > 0) ? (idx % comm->_contextCount) : 0;
338+
return &nets[safeIdx];
340339
}
341340

342341
/* ================================================================

flagcx/adaptor/flagcx_device.cc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,9 @@ extern "C" flagcxResult_t flagcxDevCommDestroy(flagcxComm_t comm,
10561056
}
10571057

10581058
// Device pointer cache cleanup
1059+
if (devComm->cachedNetContextsPtr) {
1060+
flagcxCommDeferFree(comm, devComm->cachedNetContextsPtr, flagcxMemDevice);
1061+
}
10591062
if (devComm->cachedDevicePtr) {
10601063
flagcxCommDeferFree(comm, devComm->cachedDevicePtr, flagcxMemDevice);
10611064
}
@@ -1268,6 +1271,34 @@ extern "C" flagcxResult_t flagcxDevCommGetDevicePtr(flagcxDevComm_t devComm,
12681271
// Construct value struct on host stack
12691272
flagcxDevComm hostCopy(*devComm);
12701273

1274+
// Pre-allocate net contexts (one flagcxDevNet per context) in device memory
1275+
void *netDevPtr = nullptr;
1276+
if (hostCopy._contextCount > 0) {
1277+
size_t netArraySize = hostCopy._contextCount * sizeof(flagcxDevNet);
1278+
// Build array on host heap
1279+
flagcxDevNet *hostNets = (flagcxDevNet *)malloc(netArraySize);
1280+
if (hostNets) {
1281+
for (int i = 0; i < hostCopy._contextCount; i++) {
1282+
::new (&hostNets[i]) flagcxDevNet(hostCopy, i);
1283+
}
1284+
// Copy to device
1285+
flagcxResult_t netRes = deviceAdaptor->deviceMalloc(
1286+
&netDevPtr, netArraySize, flagcxMemDevice, NULL);
1287+
if (netRes == flagcxSuccess) {
1288+
netRes =
1289+
deviceAdaptor->deviceMemcpy(netDevPtr, hostNets, netArraySize,
1290+
flagcxMemcpyHostToDevice, NULL, NULL);
1291+
}
1292+
if (netRes != flagcxSuccess) {
1293+
if (netDevPtr)
1294+
deviceAdaptor->deviceFree(netDevPtr, flagcxMemDevice, NULL);
1295+
netDevPtr = nullptr;
1296+
}
1297+
free(hostNets);
1298+
}
1299+
hostCopy._netContexts = netDevPtr;
1300+
}
1301+
12711302
// Allocate device memory and copy
12721303
void *dPtr = nullptr;
12731304
flagcxResult_t res = flagcxSuccess;
@@ -1280,12 +1311,16 @@ extern "C" flagcxResult_t flagcxDevCommGetDevicePtr(flagcxDevComm_t devComm,
12801311
res, fail);
12811312

12821313
devComm->cachedDevicePtr = dPtr;
1314+
devComm->cachedNetContextsPtr = netDevPtr;
12831315
*devPtr = dPtr;
12841316
pthread_mutex_unlock(&devComm->cachedPtrMutex);
12851317
return flagcxSuccess;
12861318

12871319
fail:
12881320
pthread_mutex_unlock(&devComm->cachedPtrMutex);
1321+
if (netDevPtr) {
1322+
deviceAdaptor->deviceFree(netDevPtr, flagcxMemDevice, NULL);
1323+
}
12891324
if (dPtr) {
12901325
deviceAdaptor->deviceFree(dPtr, flagcxMemDevice, NULL);
12911326
}
@@ -1298,9 +1333,14 @@ extern "C" flagcxResult_t flagcxDevCommFreeDevicePtr(flagcxDevComm_t devComm) {
12981333

12991334
pthread_mutex_lock(&devComm->cachedPtrMutex);
13001335
void *ptr = devComm->cachedDevicePtr;
1336+
void *netPtr = devComm->cachedNetContextsPtr;
13011337
devComm->cachedDevicePtr = nullptr;
1338+
devComm->cachedNetContextsPtr = nullptr;
13021339
pthread_mutex_unlock(&devComm->cachedPtrMutex);
13031340

1341+
if (netPtr) {
1342+
FLAGCXCHECK(deviceAdaptor->deviceFree(netPtr, flagcxMemDevice, NULL));
1343+
}
13041344
if (ptr) {
13051345
FLAGCXCHECK(deviceAdaptor->deviceFree(ptr, flagcxMemDevice, NULL));
13061346
}

flagcx/adaptor/include/device_api/flagcx_device_core.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,20 @@ struct flagcxDevComm {
7171
int _contextCount;
7272
int _nInterPeers;
7373

74+
// Pre-allocated net contexts (one per _contextCount, device memory).
75+
// Set by flagcxDevCommGetDevicePtr; nullptr when contextCount == 0.
76+
// Actually flagcxDevNet[] but kept as void* for C/opaque linkage.
77+
void *_netContexts;
78+
7479
FLAGCX_HOST_DEVICE_INLINE flagcxDevComm()
7580
: _commBase(), _signalCount(0), _counterCount(0), _contextCount(0),
76-
_nInterPeers(0) {}
81+
_nInterPeers(0), _netContexts(nullptr) {}
7782

7883
#ifndef __clang_llvm_bitcode_lib__
7984
FLAGCX_HOST_DEVICE_INLINE flagcxDevComm(const flagcxDevCommInternal &di)
8085
: _signalCount(di.signalCount), _counterCount(di.counterCount),
81-
_contextCount(di.contextCount), _nInterPeers(di.nInterPeers) {
86+
_contextCount(di.contextCount), _nInterPeers(di.nInterPeers),
87+
_netContexts(nullptr) {
8288
if (di.devComm) {
8389
_commBase = *(typename DeviceAPI::Comm *)di.devComm;
8490
} else {

flagcx/adaptor/include/device_api/flagcx_device_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ struct flagcxDevCommInternal {
9999
flagcxInnerDevComm_t devComm; // Typed vendor handle (per-adaptor struct)
100100

101101
// ---- Device pointer cache (for Triton integration) ----
102-
void *cachedDevicePtr; // Lazily allocated by flagcxDevCommGetDevicePtr
102+
void *cachedDevicePtr; // Lazily allocated by flagcxDevCommGetDevicePtr
103+
void *cachedNetContextsPtr; // Device memory for pre-allocated flagcxDevNet[]
103104
pthread_mutex_t cachedPtrMutex; // Protects lazy init of cachedDevicePtr
104105
};
105106

0 commit comments

Comments
 (0)