2727#include < string>
2828#include < vector>
2929
30+ #include " cudecomp_config.h"
31+ #if !CUDECOMP_BUILD_CPU_ONLY
3032#include < cuda/std/complex>
3133#include < cuda_runtime.h>
34+ #endif
3235#include < mpi.h>
36+ #if !CUDECOMP_BUILD_CPU_ONLY
3337#include < nccl.h>
38+ #endif
3439#ifdef ENABLE_NVSHMEM
3540#include < nvshmem.h>
3641#include < nvshmemx.h>
3944#include " internal/checks.h"
4045#include " internal/cudecomp_kernels.h"
4146#include " internal/nvtx.h"
47+ #include " internal/utils.h"
4248
4349namespace cudecomp {
4450
@@ -48,8 +54,8 @@ inline constexpr uint64_t nvshmem_signal_set_value = 1; // Graph-stable source f
4854
4955static inline MPI_Datatype getMpiDataType (float ) { return MPI_FLOAT ; }
5056static inline MPI_Datatype getMpiDataType (double ) { return MPI_DOUBLE ; }
51- static inline MPI_Datatype getMpiDataType (cuda::std ::complex <float >) { return MPI_C_FLOAT_COMPLEX ; }
52- static inline MPI_Datatype getMpiDataType (cuda::std ::complex <double >) { return MPI_C_DOUBLE_COMPLEX ; }
57+ static inline MPI_Datatype getMpiDataType (cudecomp ::complex <float >) { return MPI_C_FLOAT_COMPLEX ; }
58+ static inline MPI_Datatype getMpiDataType (cudecomp ::complex <double >) { return MPI_C_DOUBLE_COMPLEX ; }
5359template <typename T> static inline MPI_Datatype getMpiDataType () { return getMpiDataType (T (0 )); }
5460
5561static inline bool canUseMpiAlltoall (const std::vector<comm_count_t >& send_counts,
@@ -271,9 +277,11 @@ static void cudecompAlltoall(const cudecompHandle_t& handle, const cudecompGridD
271277 cudaStream_t stream, cudecompTransposePerformanceSample* current_sample = nullptr ) {
272278 nvtx::rangePush (" cudecompAlltoall" );
273279
280+ #if !CUDECOMP_BUILD_CPU_ONLY
274281 if (handle->performance_report_enable ) {
275282 CHECK_CUDA (cudaEventRecord (current_sample->alltoall_start_events [current_sample->alltoall_timing_count ], stream));
276283 }
284+ #endif
277285
278286#ifdef ENABLE_NVSHMEM
279287 if (transposeBackendRequiresMpi (grid_desc->config .transpose_comm_backend )) {
@@ -298,6 +306,7 @@ static void cudecompAlltoall(const cudecompHandle_t& handle, const cudecompGridD
298306 THROW_NOT_SUPPORTED (" build does not support NVSHMEM communication backends." );
299307#endif
300308 }
309+ #if !CUDECOMP_BUILD_CPU_ONLY
301310 case CUDECOMP_TRANSPOSE_COMM_NCCL : {
302311 auto & comm_info = (comm_axis == CUDECOMP_COMM_ROW ) ? grid_desc->row_comm_info : grid_desc->col_comm_info ;
303312 // For fully intra-group alltoall, use distinct NCCL local comm instead of global comm as it is faster.
@@ -326,17 +335,17 @@ static void cudecompAlltoall(const cudecompHandle_t& handle, const cudecompGridD
326335 CHECK_NCCL (ncclGroupEnd ());
327336 break ;
328337 }
338+ #endif
329339 case CUDECOMP_TRANSPOSE_COMM_MPI_P2P : {
330340 std::vector<MPI_Request> reqs (2 * send_counts.size (), MPI_REQUEST_NULL );
331- CHECK_CUDA ( cudaStreamSynchronize ( stream) );
341+ streamSynchronize ( stream);
332342
333343 auto comm =
334344 (comm_axis == CUDECOMP_COMM_ROW ) ? grid_desc->row_comm_info .mpi_comm : grid_desc->col_comm_info .mpi_comm ;
335345 int self_rank = (comm_axis == CUDECOMP_COMM_ROW ) ? grid_desc->row_comm_info .rank : grid_desc->col_comm_info .rank ;
336346
337- // Self-copy with cudaMemcpy
338- CHECK_CUDA (cudaMemcpyAsync (recv_buff + recv_offsets[self_rank], send_buff + send_offsets[self_rank],
339- send_counts[self_rank] * sizeof (T), cudaMemcpyDeviceToDevice, stream));
347+ copyBuffer (recv_buff + recv_offsets[self_rank], send_buff + send_offsets[self_rank],
348+ send_counts[self_rank] * sizeof (T), stream);
340349
341350 for (int i = 1 ; i < recv_counts.size (); ++i) {
342351 int src_rank, dst_rank;
@@ -365,7 +374,7 @@ static void cudecompAlltoall(const cudecompHandle_t& handle, const cudecompGridD
365374 break ;
366375 }
367376 case CUDECOMP_TRANSPOSE_COMM_MPI_A2A : {
368- CHECK_CUDA ( cudaStreamSynchronize ( stream) );
377+ streamSynchronize ( stream);
369378 auto comm =
370379 (comm_axis == CUDECOMP_COMM_ROW ) ? grid_desc->row_comm_info .mpi_comm : grid_desc->col_comm_info .mpi_comm ;
371380 int self_rank = (comm_axis == CUDECOMP_COMM_ROW ) ? grid_desc->row_comm_info .rank : grid_desc->col_comm_info .rank ;
@@ -379,9 +388,8 @@ static void cudecompAlltoall(const cudecompHandle_t& handle, const cudecompGridD
379388 int32_t rc = static_cast <int32_t >(recv_counts[0 ]);
380389 CHECK_MPI (MPI_Alltoall (send_buff, sc, getMpiDataType<T>(), recv_buff, rc, getMpiDataType<T>(), comm));
381390 } else {
382- // Self-copy with cudaMemcpy
383- CHECK_CUDA (cudaMemcpyAsync (recv_buff + recv_offsets[self_rank], send_buff + send_offsets[self_rank],
384- send_counts[self_rank] * sizeof (T), cudaMemcpyDeviceToDevice, stream));
391+ copyBuffer (recv_buff + recv_offsets[self_rank], send_buff + send_offsets[self_rank],
392+ send_counts[self_rank] * sizeof (T), stream);
385393
386394 // Convert count/offset args to int32
387395 std::vector<int32_t > send_counts_i32 (send_counts.size ());
@@ -420,10 +428,12 @@ static void cudecompAlltoall(const cudecompHandle_t& handle, const cudecompGridD
420428 }
421429 }
422430
431+ #if !CUDECOMP_BUILD_CPU_ONLY
423432 if (handle->performance_report_enable ) {
424433 CHECK_CUDA (cudaEventRecord (current_sample->alltoall_end_events [current_sample->alltoall_timing_count ], stream));
425434 current_sample->alltoall_timing_count ++;
426435 }
436+ #endif
427437
428438 nvtx::rangePop ();
429439}
@@ -450,13 +460,15 @@ cudecompAlltoallPipelined(const cudecompHandle_t& handle, const cudecompGridDesc
450460 }
451461 nvtx::rangePush (os.str ());
452462
463+ #if !CUDECOMP_BUILD_CPU_ONLY
453464 int self_rank = (comm_axis == CUDECOMP_COMM_ROW ) ? grid_desc->row_comm_info .rank : grid_desc->col_comm_info .rank ;
454465 if (handle->performance_report_enable && src_ranks[0 ] != self_rank) {
455466 // Note: skipping self-copy for timing as it should be overlapped
456467 CHECK_CUDA (cudaStreamWaitEvent (handle->streams [0 ], grid_desc->events [dst_ranks[0 ]], 0 ));
457468 CHECK_CUDA (cudaEventRecord (current_sample->alltoall_start_events [current_sample->alltoall_timing_count ],
458469 handle->streams [0 ]));
459470 }
471+ #endif
460472
461473#ifdef ENABLE_NVSHMEM
462474 if (transposeBackendRequiresMpi (grid_desc->config .transpose_comm_backend )) {
@@ -537,6 +549,7 @@ cudecompAlltoallPipelined(const cudecompHandle_t& handle, const cudecompGridDesc
537549 THROW_NOT_SUPPORTED (" build does not support NVSHMEM communication backends." );
538550#endif
539551 }
552+ #if !CUDECOMP_BUILD_CPU_ONLY
540553 case CUDECOMP_TRANSPOSE_COMM_NCCL_PL : {
541554 const auto & comm_info = (comm_axis == CUDECOMP_COMM_ROW ) ? grid_desc->row_comm_info : grid_desc->col_comm_info ;
542555 // For fully intra-group alltoall, use distinct NCCL local comm instead of global comm as it is faster.
@@ -589,6 +602,7 @@ cudecompAlltoallPipelined(const cudecompHandle_t& handle, const cudecompGridDesc
589602 }
590603 break ;
591604 }
605+ #endif
592606 case CUDECOMP_TRANSPOSE_COMM_MPI_P2P_PL : {
593607 auto comm =
594608 (comm_axis == CUDECOMP_COMM_ROW ) ? grid_desc->row_comm_info .mpi_comm : grid_desc->col_comm_info .mpi_comm ;
@@ -599,11 +613,12 @@ cudecompAlltoallPipelined(const cudecompHandle_t& handle, const cudecompGridDesc
599613 int src_rank = src_ranks[i];
600614 int dst_rank = dst_ranks[i];
601615 if (src_rank == self_rank) {
602- // Self-copy with cudaMemcpy
603- CHECK_CUDA (cudaMemcpyAsync (recv_buff + recv_offsets[self_rank], send_buff + send_offsets[self_rank],
604- send_counts[self_rank] * sizeof (T), cudaMemcpyDeviceToDevice, stream));
616+ copyBuffer (recv_buff + recv_offsets[self_rank], send_buff + send_offsets[self_rank],
617+ send_counts[self_rank] * sizeof (T), stream);
605618 } else {
619+ #if !CUDECOMP_BUILD_CPU_ONLY
606620 CHECK_CUDA (cudaEventSynchronize (grid_desc->events [dst_rank]));
621+ #endif
607622
608623 if (send_counts[dst_rank] != 0 ) {
609624 checkMpiInt32Limit (send_counts[dst_rank], grid_desc->config .transpose_comm_backend );
@@ -629,11 +644,13 @@ cudecompAlltoallPipelined(const cudecompHandle_t& handle, const cudecompGridDesc
629644 }
630645 }
631646
647+ #if !CUDECOMP_BUILD_CPU_ONLY
632648 if (handle->performance_report_enable && src_ranks[0 ] != self_rank) {
633649 CHECK_CUDA (cudaEventRecord (current_sample->alltoall_end_events [current_sample->alltoall_timing_count ],
634650 handle->streams [0 ]));
635651 current_sample->alltoall_timing_count ++;
636652 }
653+ #endif
637654 nvtx::rangePop ();
638655}
639656
@@ -647,9 +664,11 @@ static void cudecompSendRecvPair(const cudecompHandle_t& handle, const cudecompG
647664 cudecompHaloPerformanceSample* current_sample = nullptr ) {
648665 nvtx::rangePush (" cudecompSendRecvPair" );
649666
667+ #if !CUDECOMP_BUILD_CPU_ONLY
650668 if (handle->performance_report_enable && current_sample) {
651669 CHECK_CUDA (cudaEventRecord (current_sample->sendrecv_start_event , stream));
652670 }
671+ #endif
653672
654673#ifdef ENABLE_NVSHMEM
655674 if (haloBackendRequiresMpi (grid_desc->config .halo_comm_backend )) {
@@ -690,6 +709,7 @@ static void cudecompSendRecvPair(const cudecompHandle_t& handle, const cudecompG
690709 THROW_NOT_SUPPORTED (" build does not support NVSHMEM communication backends." );
691710#endif
692711 }
712+ #if !CUDECOMP_BUILD_CPU_ONLY
693713 case CUDECOMP_HALO_COMM_NCCL : {
694714 auto comm = *grid_desc->nccl_comm ;
695715 CHECK_NCCL (ncclGroupStart ());
@@ -712,15 +732,14 @@ static void cudecompSendRecvPair(const cudecompHandle_t& handle, const cudecompG
712732 CHECK_NCCL (ncclGroupEnd ());
713733 break ;
714734 }
735+ #endif
715736 case CUDECOMP_HALO_COMM_MPI : {
716737 auto comm = handle->mpi_comm ;
717738 std::vector<MPI_Request> reqs (2 * send_counts.size (), MPI_REQUEST_NULL );
718- CHECK_CUDA ( cudaStreamSynchronize ( stream) );
739+ streamSynchronize ( stream);
719740 for (int i = 0 ; i < send_counts.size (); ++i) {
720741 if (peer_ranks[i] == handle->rank ) {
721- // Self-copy with cudaMemcpy
722- CHECK_CUDA (cudaMemcpyAsync (recv_buff + recv_offsets[i], send_buff + send_offsets[i], send_counts[i] * sizeof (T),
723- cudaMemcpyDeviceToDevice, stream));
742+ copyBuffer (recv_buff + recv_offsets[i], send_buff + send_offsets[i], send_counts[i] * sizeof (T), stream);
724743 } else {
725744 if (recv_counts[(i + 1 ) % 2 ] != 0 && peer_ranks[(i + 1 ) % 2 ] != -1 ) {
726745 checkMpiInt32Limit (recv_counts[(i + 1 ) % 2 ], grid_desc->config .halo_comm_backend );
@@ -742,12 +761,10 @@ static void cudecompSendRecvPair(const cudecompHandle_t& handle, const cudecompG
742761 }
743762 case CUDECOMP_HALO_COMM_MPI_BLOCKING : {
744763 auto comm = handle->mpi_comm ;
745- CHECK_CUDA ( cudaStreamSynchronize ( stream) );
764+ streamSynchronize ( stream);
746765 for (int i = 0 ; i < send_counts.size (); ++i) {
747766 if (peer_ranks[i] == handle->rank ) {
748- // Self-copy with cudaMemcpy
749- CHECK_CUDA (cudaMemcpyAsync (recv_buff + recv_offsets[i], send_buff + send_offsets[i], send_counts[i] * sizeof (T),
750- cudaMemcpyDeviceToDevice, stream));
767+ copyBuffer (recv_buff + recv_offsets[i], send_buff + send_offsets[i], send_counts[i] * sizeof (T), stream);
751768 } else {
752769 MPI_Request r = MPI_REQUEST_NULL ;
753770 if (recv_counts[(i + 1 ) % 2 ] != 0 && peer_ranks[(i + 1 ) % 2 ] != -1 ) {
@@ -772,9 +789,11 @@ static void cudecompSendRecvPair(const cudecompHandle_t& handle, const cudecompG
772789 }
773790 }
774791
792+ #if !CUDECOMP_BUILD_CPU_ONLY
775793 if (handle->performance_report_enable && current_sample) {
776794 CHECK_CUDA (cudaEventRecord (current_sample->sendrecv_end_event , stream));
777795 }
796+ #endif
778797
779798 nvtx::rangePop ();
780799}
0 commit comments