77#include " group.h"
88#include " adaptor.h"
99#include " assert.h"
10- #include " collectives.h"
1110#include " debug.h"
11+ #include " flagcx_hetero.h"
1212#include " launch_kernel.h"
1313#include " net.h"
1414#include " p2p.h"
@@ -75,6 +75,26 @@ void *flagcxAsyncJobMain(void *arg) {
7575 return arg;
7676}
7777
78+ flagcxResult_t createAndLookupSemaphore (
79+ std::map<int , std::shared_ptr<flagcxSemaphore>> &semaphoreMap,
80+ std::shared_ptr<flagcxSemaphore> &semaphore, int &subGroupCount,
81+ int roundIdx) {
82+ if (semaphoreMap.find (roundIdx) != semaphoreMap.end ()) {
83+ semaphore = semaphoreMap[roundIdx];
84+ } else {
85+ if (deviceAsyncKernel) {
86+ semaphore = std::make_shared<flagcxDeviceSemaphore>();
87+ } else {
88+ semaphore = std::make_shared<flagcxHostSemaphore>();
89+ }
90+ if (semaphoreMap.empty ()) {
91+ subGroupCount++;
92+ }
93+ semaphoreMap[roundIdx] = semaphore;
94+ }
95+ return flagcxSuccess;
96+ }
97+
7898static flagcxResult_t groupLaunch (struct flagcxAsyncJob *job_) {
7999 flagcxResult_t ret = flagcxSuccess;
80100 // bool errorJobAbortFlag = false;
@@ -88,14 +108,11 @@ static flagcxResult_t groupLaunch(struct flagcxAsyncJob *job_) {
88108 *asyncJobsMain = gjob->asyncJobsPtr ;
89109 // volatile bool *groupAbortFlag = gjob->abortFlagPtr;
90110
91- // Each groupLaunch we create a semaphore to track the p2p ops
92- // and a stream to launch host or device func
93- std::shared_ptr<flagcxSemaphore> semaphore;
94- if (deviceAsyncKernel) {
95- semaphore = std::make_shared<flagcxDeviceSemaphore>();
96- } else {
97- semaphore = std::make_shared<flagcxHostSemaphore>();
98- }
111+ // Each groupLaunch we create a set of sub-groups of semaphores to track the
112+ // p2p ops and a stream to launch host or device func
113+ int subGroupCount = 0 ;
114+ std::map<int , std::shared_ptr<flagcxSemaphore>>
115+ semaphoreMapList[FLAGCX_MAX_SUBGROUPS ];
99116 flagcxStream_t launchStream = nullptr ;
100117 flagcxEvent_t launchEvent = nullptr ;
101118
@@ -143,6 +160,7 @@ static flagcxResult_t groupLaunch(struct flagcxAsyncJob *job_) {
143160 do {
144161 flagcxTasks *tasks = &comm->tasks ;
145162 int nRanks = comm->nRanks ;
163+ int localRanks = comm->localRanks ;
146164
147165 // Round 0: handle self send/recv (local copy)
148166 {
@@ -162,6 +180,10 @@ static flagcxResult_t groupLaunch(struct flagcxAsyncJob *job_) {
162180 if (sendTasks[i]->bytes == recvTasks[j]->bytes &&
163181 sendTasks[i]->dtype == recvTasks[j]->dtype ) {
164182 if (sendTasks[i]->buff != recvTasks[j]->buff ) {
183+ std::shared_ptr<flagcxSemaphore> semaphore;
184+ createAndLookupSemaphore (
185+ semaphoreMapList[sendTasks[i]->groupIdx ], semaphore,
186+ subGroupCount, 0 );
165187 flagcxProxyOp *op;
166188 FLAGCXCHECK (flagcxCalloc (&op, 1 ));
167189 op->pattern = flagcxPatternSend;
@@ -209,6 +231,7 @@ static flagcxResult_t groupLaunch(struct flagcxAsyncJob *job_) {
209231 // Round 1..nRanks-1: use p2pSchedule to pair recv/send with different
210232 // peers
211233 for (int round = 1 ; round < nRanks; round++) {
234+ int roundIdx = round % localRanks;
212235 int recvPeer = comm->p2pSchedule [round].recvRank ;
213236 int sendPeer = comm->p2pSchedule [round].sendRank ;
214237
@@ -220,6 +243,9 @@ static flagcxResult_t groupLaunch(struct flagcxAsyncJob *job_) {
220243 flagcxTaskP2p *p2p =
221244 flagcxIntruQueueDequeue (&tasks->peers [recvPeer].recvQueue );
222245 int peer = recvPeer;
246+ std::shared_ptr<flagcxSemaphore> semaphore;
247+ createAndLookupSemaphore (semaphoreMapList[p2p->groupIdx ], semaphore,
248+ subGroupCount, roundIdx);
223249 flagcxProxyOp *op;
224250 FLAGCXCHECK (flagcxCalloc (&op, 1 ));
225251 op->pattern = flagcxPatternRecv;
@@ -299,6 +325,9 @@ static flagcxResult_t groupLaunch(struct flagcxAsyncJob *job_) {
299325 flagcxTaskP2p *p2p =
300326 flagcxIntruQueueDequeue (&tasks->peers [sendPeer].sendQueue );
301327 int peer = sendPeer;
328+ std::shared_ptr<flagcxSemaphore> semaphore;
329+ createAndLookupSemaphore (semaphoreMapList[p2p->groupIdx ], semaphore,
330+ subGroupCount, roundIdx);
302331 flagcxProxyOp *op;
303332 FLAGCXCHECK (flagcxCalloc (&op, 1 ));
304333 op->pattern = flagcxPatternSend;
@@ -376,15 +405,24 @@ static flagcxResult_t groupLaunch(struct flagcxAsyncJob *job_) {
376405 }
377406
378407 if (launchStream != nullptr && launchEvent != nullptr ) {
408+ for (int i = 0 ; i < subGroupCount; i++) {
409+ auto &semaphoreMap = semaphoreMapList[i];
410+ for (auto it = semaphoreMap.begin (); it != semaphoreMap.end (); ++it) {
411+ auto &semaphore = it->second ;
412+ if (deviceAsyncKernel) {
413+ FLAGCXCHECK (
414+ deviceAdaptor->launchDeviceFunc (launchStream, deviceAsyncKernel,
415+ (void *)semaphore->getSignals ()));
416+ } else {
417+ FLAGCXCHECK (deviceAdaptor->launchHostFunc (
418+ launchStream, cpuAsyncKernel, (void *)semaphore.get ()));
419+ }
420+ }
421+ }
379422 if (deviceAsyncKernel) {
380- FLAGCXCHECK (deviceAdaptor->launchDeviceFunc (
381- launchStream, deviceAsyncKernel, (void *)semaphore->getSignals ()));
382- } else {
383- FLAGCXCHECK (deviceAdaptor->launchHostFunc (launchStream, cpuAsyncKernel,
384- (void *)semaphore.get ()));
423+ // device semaphore need this event to signal completion
424+ FLAGCXCHECK (deviceAdaptor->eventRecord (launchEvent, launchStream));
385425 }
386- // device semaphore need this event to signal completion
387- FLAGCXCHECK (deviceAdaptor->eventRecord (launchEvent, launchStream));
388426 }
389427
390428 while (!flagcxIntruQueueEmpty (asyncJobsMain)) {
0 commit comments