@@ -174,6 +174,7 @@ static void *bootstrapRoot(void *rargs) {
174174 flagcxResult_t res = flagcxSuccess;
175175
176176 /* Receive addresses from all ranks */
177+ int checkedIn = 0 ;
177178 do {
178179 struct flagcxSocket sock;
179180 FLAGCXCHECKGOTO (flagcxSocketInit (&sock), res, fail);
@@ -184,12 +185,20 @@ static void *bootstrapRoot(void *rargs) {
184185 if (nranks == 0 ) {
185186 nranks = info.nranks ;
186187 FLAGCXCHECKGOTO (flagcxCalloc (&rankInfo, nranks), res, fail);
188+ } else if (info.nranks != nranks) {
189+ WARN (" Bootstrap Root: rank %d nranks mismatch: expected %d, got %d" ,
190+ info.rank , nranks, info.nranks );
191+ res = flagcxInvalidArgument;
192+ goto fail;
187193 }
188194 if (info.rank < 0 || info.rank >= nranks) {
195+ res = flagcxInvalidArgument;
189196 goto fail;
190197 }
198+ if (rankInfo[info.rank ].nranks == 0 )
199+ checkedIn++;
191200 rankInfo[info.rank ] = info;
192- } while (rankInfo[nranks - 1 ]. nranks == 0 );
201+ } while (checkedIn < nranks);
193202
194203 /* Send everyone info about their "next" rank in the ring */
195204 for (int i = 0 ; i < nranks; ++i) {
@@ -234,6 +243,9 @@ flagcxResult_t bootstrapCollCreateRoot(struct flagcxBootstrapHandle *handle,
234243 args->magic = handle->magic ;
235244 if (pthread_create (&thread, NULL , bootstrapRoot, (void *)args) != 0 ) {
236245 WARN (" bootstrapCollCreateRoot: pthread_create failed" );
246+ free (args);
247+ flagcxSocketClose (listenSock);
248+ free (listenSock);
237249 return flagcxSystemError;
238250 }
239251 flagcxSetThreadName (thread, " FlagCX BootRoot" );
@@ -889,11 +901,18 @@ bootstrapRingAllReduce(struct flagcxSocket *prevSocket,
889901 sendbuff, recvbuff, offset.data (),
890902 length.data (), datatype, op));
891903
892- // AllGather the results
904+ // AllGather the results with variable chunk sizes
893905 // Copy my chunk into correct position
894- memcpy (recvbuff + offset[rank], recvbuff, length[rank]);
895- FLAGCXCHECK (bootstrapRingAllGather (prevSocket, nextSocket, rank, nranks,
896- recvbuff, ChunkBytes));
906+ memmove (recvbuff + offset[rank], recvbuff, length[rank]);
907+
908+ // Ring AllGather with per-slice variable sizes
909+ for (int i = 0 ; i < nranks - 1 ; i++) {
910+ size_t sslice = (rank - i + nranks) % nranks;
911+ size_t rslice = (rank - i - 1 + nranks) % nranks;
912+ FLAGCXCHECK (bootstrapNetSendRecv (
913+ nextSocket, recvbuff + offset[sslice], (int )length[sslice], prevSocket,
914+ recvbuff + offset[rslice], (int )length[rslice]));
915+ }
897916 return flagcxSuccess;
898917}
899918
@@ -930,6 +949,9 @@ bootstrapRingReduce(struct bootstrapState *commState,
930949 sendbuff, recvbuff, offset.data (),
931950 length.data (), datatype, op));
932951
952+ // Move my reduced chunk to its final position before gather to root
953+ memmove (recvbuff + offset[rank], recvbuff, length[rank]);
954+
933955 // gather to root
934956 const int bootstrapTag = BOOTSTRAP_TAG_REDUCE ;
935957 if (rank == root) {
0 commit comments