Skip to content

Commit 5ca4553

Browse files
authored
[CRL] Shard P2P QPs across per-worker CQs and pin worker threads to NIC-local CPUs (#504)
1 parent 9b52949 commit 5ca4553

5 files changed

Lines changed: 432 additions & 208 deletions

File tree

flagcx/adaptor/device/ducuda_adaptor.cc

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -301,14 +301,12 @@ flagcxResult_t ducudaAdaptorDmaSupport(bool *dmaBufferSupport) {
301301
return flagcxSuccess;
302302
}
303303

304-
flagcxResult_t
305-
ducudaAdaptorMemGetHandleForAddressRange(void *handleOut, void *buffer,
306-
size_t size, unsigned long long flags) {
307-
//unsupportted on dcu
304+
flagcxResult_t ducudaAdaptorMemGetHandleForAddressRange(
305+
void *handleOut, void *buffer, size_t size, unsigned long long flags) {
306+
// unsupportted on dcu
308307
return flagcxNotSupported;
309308
}
310309

311-
312310
flagcxResult_t ducudaAdaptorGetDeviceProperties(struct flagcxDevProps *props,
313311
int dev) {
314312
if (props == NULL) {
@@ -348,7 +346,7 @@ flagcxResult_t ducudaAdaptorGetDeviceByPciBusId(int *dev,
348346
}
349347

350348
flagcxResult_t ducudaAdaptorStreamWaitValue64(flagcxStream_t stream, void *addr,
351-
uint64_t value, int flags) {
349+
uint64_t value, int flags) {
352350
(void)flags;
353351
if (stream == NULL || addr == NULL)
354352
return flagcxInvalidArgument;
@@ -357,8 +355,9 @@ flagcxResult_t ducudaAdaptorStreamWaitValue64(flagcxStream_t stream, void *addr,
357355
CU_STREAM_WAIT_VALUE_GEQ);
358356
return (err == CUDA_SUCCESS) ? flagcxSuccess : flagcxUnhandledDeviceError;
359357
}
360-
flagcxResult_t ducudaAdaptorStreamWriteValue64(flagcxStream_t stream, void *addr,
361-
uint64_t value, int flags) {
358+
flagcxResult_t ducudaAdaptorStreamWriteValue64(flagcxStream_t stream,
359+
void *addr, uint64_t value,
360+
int flags) {
362361
(void)flags;
363362
if (stream == NULL || addr == NULL)
364363
return flagcxInvalidArgument;
@@ -368,7 +367,7 @@ flagcxResult_t ducudaAdaptorStreamWriteValue64(flagcxStream_t stream, void *addr
368367
return (err == CUDA_SUCCESS) ? flagcxSuccess : flagcxUnhandledDeviceError;
369368
}
370369
flagcxResult_t ducudaAdaptorEventElapsedTime(float *ms, flagcxEvent_t start,
371-
flagcxEvent_t end) {
370+
flagcxEvent_t end) {
372371
if (ms == NULL || start == NULL || end == NULL) {
373372
return flagcxInvalidArgument;
374373
}
@@ -394,8 +393,10 @@ flagcxResult_t ducudaAdaptorHostUnregister(void *ptr) {
394393

395394
// Symmetric memory VMM stubs (not supported)
396395
flagcxResult_t ducudaAdaptorSymPhysAlloc(void *ptr, size_t size,
397-
void **physHandle, void *shareableHandle,
398-
size_t *handleSize, size_t *allocSize) {
396+
void **physHandle,
397+
void *shareableHandle,
398+
size_t *handleSize,
399+
size_t *allocSize) {
399400
if (ptr == NULL || physHandle == NULL || shareableHandle == NULL ||
400401
handleSize == NULL || allocSize == NULL)
401402
return flagcxInvalidArgument;
@@ -425,7 +426,7 @@ flagcxResult_t ducudaAdaptorSymPhysAlloc(void *ptr, size_t size,
425426
*physHandle = cuHandle;
426427
return flagcxSuccess;
427428
}
428-
flagcxResult_t ducudaAdaptorSymPhysFree(void *physHandle) {
429+
flagcxResult_t ducudaAdaptorSymPhysFree(void *physHandle) {
429430
if (physHandle == NULL)
430431
return flagcxSuccess;
431432
CUmemGenericAllocationHandle *cuHandle =
@@ -435,8 +436,8 @@ flagcxResult_t ducudaAdaptorSymPhysFree(void *physHandle) {
435436
return flagcxSuccess;
436437
}
437438
flagcxResult_t ducudaAdaptorSymFlatMap(void *peerHandles[], int nPeers,
438-
int selfIndex, void *selfPhysHandle,
439-
size_t allocSize, void **flatBase) {
439+
int selfIndex, void *selfPhysHandle,
440+
size_t allocSize, void **flatBase) {
440441
if (peerHandles == NULL || selfPhysHandle == NULL || flatBase == NULL ||
441442
nPeers <= 0 || allocSize == 0)
442443
return flagcxInvalidArgument;
@@ -481,7 +482,7 @@ flagcxResult_t ducudaAdaptorSymFlatMap(void *peerHandles[], int nPeers,
481482
return flagcxSuccess;
482483
}
483484
flagcxResult_t ducudaAdaptorSymFlatUnmap(void *flatBase, size_t allocSize,
484-
int nPeers) {
485+
int nPeers) {
485486
if (flatBase == NULL)
486487
return flagcxSuccess;
487488
CUdeviceptr base = (CUdeviceptr)flatBase;
@@ -494,16 +495,16 @@ flagcxResult_t ducudaAdaptorSymMulticastSupported(int *supported) {
494495
// not supported on dcu
495496
if (supported == NULL)
496497
return flagcxInvalidArgument;
497-
498+
498499
if (supported)
499500
*supported = 0;
500501
return flagcxSuccess;
501502
}
502503
flagcxResult_t ducudaAdaptorSymMulticastCreate(size_t allocSize,
503-
int nLocalDevices,
504-
const int *localDeviceOrdinals,
505-
void **mcHandle,
506-
int *shareableFd) {
504+
int nLocalDevices,
505+
const int *localDeviceOrdinals,
506+
void **mcHandle,
507+
int *shareableFd) {
507508
// not supported on dcu
508509
if (mcHandle)
509510
*mcHandle = NULL;
@@ -514,9 +515,9 @@ flagcxResult_t ducudaAdaptorSymMulticastCreate(size_t allocSize,
514515
return flagcxNotSupported;
515516
}
516517
flagcxResult_t ducudaAdaptorSymMulticastBind(void *mcHandle, int importFd,
517-
void *physHandle, size_t allocSize,
518-
int localRank, int nLocalDevices,
519-
void **mcBase, size_t *mcMapSize) {
518+
void *physHandle, size_t allocSize,
519+
int localRank, int nLocalDevices,
520+
void **mcBase, size_t *mcMapSize) {
520521
// not supported on dcu
521522
if (mcBase)
522523
*mcBase = NULL;
@@ -526,7 +527,8 @@ flagcxResult_t ducudaAdaptorSymMulticastBind(void *mcHandle, int importFd,
526527

527528
return flagcxNotSupported;
528529
}
529-
flagcxResult_t ducudaAdaptorSymMulticastTeardown(void *mcBase, size_t mcMapSize) {
530+
flagcxResult_t ducudaAdaptorSymMulticastTeardown(void *mcBase,
531+
size_t mcMapSize) {
530532
// not supported on dcu
531533
return flagcxSuccess;
532534
}
@@ -590,9 +592,13 @@ struct flagcxDeviceAdaptor ducudaAdaptor {
590592
// *dev, const char *pciBusId);
591593
ducudaAdaptorLaunchHostFunc,
592594
// DMA buffer
593-
ducudaAdaptorDmaSupport, // flagcxResult_t (*dmaSupport)(bool *dmaBufferSupport);
594-
ducudaAdaptorMemGetHandleForAddressRange, // flagcxResult_t (*memGetHandleForAddressRange)(void *handleOut,
595-
// void *buffer, size_t size, unsigned long long flags);
595+
ducudaAdaptorDmaSupport, // flagcxResult_t (*dmaSupport)(bool
596+
// *dmaBufferSupport);
597+
ducudaAdaptorMemGetHandleForAddressRange, // flagcxResult_t
598+
// (*memGetHandleForAddressRange)(void
599+
// *handleOut, void *buffer,
600+
// size_t size, unsigned long
601+
// long flags);
596602
ducudaAdaptorHostRegister, // flagcxResult_t (*hostRegister)(void *,
597603
// size_t);
598604
ducudaAdaptorHostUnregister, // flagcxResult_t (*hostUnregister)(void *);

flagcx/adaptor/net/ibrc_p2p_adaptor.cc

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <pthread.h>
2323
#include <stdint.h>
2424
#include <string.h>
25-
#include <string>
2625
#include <thread>
2726
#include <unistd.h>
2827
#include <vector>
@@ -629,7 +628,6 @@ flagcxP2pBuildSingleSliceReq(struct flagcxP2pSendComm *comm, uint64_t localVa,
629628
req->slice.lkey = lkey;
630629
req->slice.rkey = rkey;
631630
req->slice.opcode = opcode;
632-
req->slice.peerNicPath = std::string();
633631
req->slice.task = &req->task;
634632
req->slice.qpDepth = NULL;
635633
req->task.sliceList.push_back(&req->slice);
@@ -710,7 +708,6 @@ flagcxP2pIgetBatch(void *sendComm, int count, const uint64_t *srcOffs,
710708
dst->lkey,
711709
src->rkey,
712710
FLAGCX_SLICE_OP_READ,
713-
std::string(),
714711
&req->task,
715712
NULL};
716713
req->task.sliceList.push_back(s);
@@ -745,8 +742,11 @@ static inline enum ibv_wr_opcode flagcxSliceOpcodeToVerbs(uint8_t op) {
745742
}
746743

747744
extern "C" flagcxResult_t flagcxP2pSliceBatch(void *sendComm, struct ibv_qp *qp,
748-
int count, FlagcxSlice **slices) {
745+
int count, FlagcxSlice **slices,
746+
int *failedCount) {
749747
struct flagcxP2pSendComm *comm = (struct flagcxP2pSendComm *)sendComm;
748+
if (failedCount != NULL)
749+
*failedCount = 0;
750750
const char *opLabel = (slices != NULL && count > 0 && slices[0] != NULL &&
751751
slices[0]->opcode == FLAGCX_SLICE_OP_READ)
752752
? "READ"
@@ -757,23 +757,50 @@ extern "C" flagcxResult_t flagcxP2pSliceBatch(void *sendComm, struct ibv_qp *qp,
757757
WARN("NET/IB_P2P : invalid sliceBatch arguments (op=%s, count=%d, qp=%p, "
758758
"max=%d)",
759759
opLabel, count, (void *)qp, maxWrPerPost);
760+
int failed = 0;
761+
if (slices != NULL && count > 0) {
762+
for (int i = 0; i < count; i++) {
763+
if (slices[i] != NULL) {
764+
if (slices[i]->qpDepth != NULL)
765+
__sync_fetch_and_sub(slices[i]->qpDepth, 1);
766+
slices[i]->markFailed();
767+
failed++;
768+
}
769+
}
770+
}
771+
if (failedCount != NULL)
772+
*failedCount = failed;
760773
return flagcxInternalError;
761774
}
762775

763-
// count can be up to flagcxP2pGlobalConfig().maxWrPerPost (default 256,
764-
// bounded at 1024). Heap-allocate to keep the stack small.
765-
std::vector<struct ibv_send_wr> wrs(count);
766-
std::vector<struct ibv_sge> sges(count);
776+
static thread_local std::vector<struct ibv_send_wr> wrScratch;
777+
static thread_local std::vector<struct ibv_sge> sgeScratch;
778+
if ((int)wrScratch.size() < maxWrPerPost) {
779+
wrScratch.resize(maxWrPerPost);
780+
sgeScratch.resize(maxWrPerPost);
781+
}
782+
struct ibv_send_wr *wrs = wrScratch.data();
783+
struct ibv_sge *sges = sgeScratch.data();
784+
memset(wrs, 0, sizeof(*wrs) * count);
767785

768786
for (int i = 0; i < count; i++) {
769787
FlagcxSlice *s = slices[i];
770788
if (s == NULL) {
771789
WARN("NET/IB_P2P : sliceBatch slice[%d] is NULL", i);
772-
for (int k = 0; k < i; k++)
790+
for (int k = 0; k < i; k++) {
791+
if (slices[k]->qpDepth != NULL)
792+
__sync_fetch_and_sub(slices[k]->qpDepth, 1);
773793
slices[k]->markFailed();
774-
for (int k = i; k < count; k++)
775-
if (slices[k])
794+
}
795+
for (int k = i; k < count; k++) {
796+
if (slices[k]) {
797+
if (slices[k]->qpDepth != NULL)
798+
__sync_fetch_and_sub(slices[k]->qpDepth, 1);
776799
slices[k]->markFailed();
800+
}
801+
}
802+
if (failedCount != NULL)
803+
*failedCount = count;
777804
return flagcxInternalError;
778805
}
779806

@@ -792,11 +819,11 @@ extern "C" flagcxResult_t flagcxP2pSliceBatch(void *sendComm, struct ibv_qp *qp,
792819
}
793820

794821
struct ibv_send_wr *bad_wr = NULL;
795-
flagcxResult_t res = flagcxWrapIbvPostSend(qp, &wrs[0], &bad_wr);
822+
flagcxResult_t res = flagcxWrapIbvPostSend(qp, wrs, &bad_wr);
796823
if (res != flagcxSuccess) {
797824
int failedFrom = 0;
798825
if (bad_wr != NULL) {
799-
ptrdiff_t off = bad_wr - &wrs[0];
826+
ptrdiff_t off = bad_wr - wrs;
800827
if (off >= 0 && off < count)
801828
failedFrom = (int)off;
802829
}
@@ -807,6 +834,8 @@ extern "C" flagcxResult_t flagcxP2pSliceBatch(void *sendComm, struct ibv_qp *qp,
807834
__sync_fetch_and_sub(slices[k]->qpDepth, 1);
808835
slices[k]->markFailed();
809836
}
837+
if (failedCount != NULL)
838+
*failedCount = count - failedFrom;
810839
WARN("NET/IB_P2P : sliceBatch ibv_post_send failed (op=%s, count=%d, "
811840
"failedFrom=%d)",
812841
opLabel, count, failedFrom);

0 commit comments

Comments
 (0)