From a2b0101ec43a227fab598632a0467d69943ddb02 Mon Sep 17 00:00:00 2001 From: Li Baoming <1508269885@qq.com> Date: Wed, 2 Sep 2026 11:12:54 +0800 Subject: [PATCH 1/2] feat(cambricon): add CNCL backend for local multi-device collectives --- CMakeLists.txt | 27 +++++++- scripts/gen_bridge.py | 3 + src/CMakeLists.txt | 10 +++ src/backend.h | 5 ++ src/backend_device_map.h | 4 ++ src/backends/ccl/cncl/api.h | 58 +++++++++++++++++ src/backends/ccl/cncl/cambricon/api.h | 15 +++++ src/backends/ccl/cncl/impl/all_gather.h | 17 +++++ src/backends/ccl/cncl/impl/all_reduce.h | 17 +++++ src/backends/ccl/cncl/impl/comm_destroy.h | 17 +++++ src/backends/ccl/cncl/impl/comm_init_all.h | 75 ++++++++++++++++++++++ src/backends/ccl/cncl/type_map.h | 73 +++++++++++++++++++++ src/backends/mpi/ompi/impl/comm_init_all.h | 17 +++-- src/base/comm_init_all.h | 21 ++---- 14 files changed, 339 insertions(+), 20 deletions(-) create mode 100644 src/backends/ccl/cncl/api.h create mode 100644 src/backends/ccl/cncl/cambricon/api.h create mode 100644 src/backends/ccl/cncl/impl/all_gather.h create mode 100644 src/backends/ccl/cncl/impl/all_reduce.h create mode 100644 src/backends/ccl/cncl/impl/comm_destroy.h create mode 100644 src/backends/ccl/cncl/impl/comm_init_all.h create mode 100644 src/backends/ccl/cncl/type_map.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b006ce..48181fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ option(WITH_OMPI "Enable OpenMPI backend" OFF) option(WITH_MPICH "Enable MPICH backend" OFF) option(WITH_NCCL "Enable NCCL backend" OFF) option(WITH_MCCL "Enable MCCL backend" OFF) +option(WITH_CNCL "Enable CNCL backend" OFF) # ========================================================= # --- MISC. BUILD OPTIONS --- @@ -327,10 +328,23 @@ if(AUTO_DETECT_BACKENDS) else() message(STATUS "No suitable device environment, skipping MCCL detection.") endif() + + # Detect CNCL Dependencies + if(WITH_CAMBRICON) + find_path(AUTO_CNCL_INC NAMES cncl.h HINTS "$ENV{NEUWARE_HOME}" /usr/local/neuware PATH_SUFFIXES include QUIET) + find_library(AUTO_CNCL_LIB NAMES cncl HINTS "$ENV{NEUWARE_HOME}" /usr/local/neuware PATH_SUFFIXES lib lib64 QUIET) + + if(AUTO_CNCL_INC AND AUTO_CNCL_LIB) + set(WITH_CNCL ON) + message(STATUS "Auto-detected CNCL backend.") + else() + message(STATUS "CNCL library/headers not found in Cambricon paths.") + endif() + endif() endif() # Fallback: If no backends are enabled or auto-detected, fall back to OpenMPI as the default bootstrap profile. -if(NOT WITH_OMPI AND NOT WITH_MPICH AND NOT WITH_NCCL AND NOT WITH_MCCL) +if(NOT WITH_OMPI AND NOT WITH_MPICH AND NOT WITH_NCCL AND NOT WITH_MCCL AND NOT WITH_CNCL) set(WITH_OMPI ON) message(STATUS "No backend specified or detected. Defaulting to `WITH_OMPI=ON`") endif() @@ -535,6 +549,17 @@ if(WITH_MCCL) include_directories(${MCCL_INC}) endif() +if(WITH_CNCL) + if(NOT WITH_CAMBRICON) + message(FATAL_ERROR "CNCL backend requires Cambricon device support. Please enable `WITH_CAMBRICON`.") + endif() + + find_library(CNCL_LIB NAMES cncl HINTS "${NEUWARE_HOME}" "$ENV{NEUWARE_HOME}" /usr/local/neuware PATH_SUFFIXES lib lib64 REQUIRED) + find_path(CNCL_INC NAMES cncl.h HINTS "${NEUWARE_HOME}" "$ENV{NEUWARE_HOME}" /usr/local/neuware PATH_SUFFIXES include REQUIRED) + + include_directories(${CNCL_INC}) +endif() + # Python is required for code generation. find_package(Python3 REQUIRED) diff --git a/scripts/gen_bridge.py b/scripts/gen_bridge.py index 211080b..59d4dd2 100644 --- a/scripts/gen_bridge.py +++ b/scripts/gen_bridge.py @@ -32,16 +32,19 @@ "mpich": ["backends/mpi/ompi/impl"], "nccl": ["backends/ccl/nccl/impl"], "mccl": ["backends/ccl/mccl/impl"], + "cncl": ["backends/ccl/cncl/impl"], } BACKEND_COMMON_HEADERS = { "nccl": ["backends/ccl/nccl/type_map.h"], "mccl": ["backends/ccl/mccl/type_map.h"], + "cncl": ["backends/ccl/cncl/type_map.h"], } CCL_PROVIDER_BACKENDS = { "nccl": "backends/ccl/nccl", "mccl": "backends/ccl/mccl", + "cncl": "backends/ccl/cncl", } # ================================================================= diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 84ffbcf..c191b68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -283,6 +283,16 @@ if(WITH_MCCL) target_link_libraries(infiniccl PRIVATE ${MCCL_LIB}) endif() +# CNCL +if(WITH_CNCL) + list(APPEND BACKEND_LIST "cncl") + file(GLOB_RECURSE CNCL_SRCS "backends/ccl/cncl/*.cc" "backends/ccl/cncl/*.cpp") + + target_sources(infiniccl PRIVATE ${CNCL_SRCS}) + target_include_directories(infiniccl PRIVATE ${CNCL_INC}) + target_link_libraries(infiniccl PRIVATE ${CNCL_LIB}) +endif() + # ========================================================= # --- File Generation --- # ========================================================= diff --git a/src/backend.h b/src/backend.h index 0b02662..7ebad6d 100644 --- a/src/backend.h +++ b/src/backend.h @@ -63,6 +63,11 @@ struct BackendPriority { static constexpr int value = 10; }; +template <> +struct BackendPriority { + static constexpr int value = 10; +}; + } // namespace infini::ccl #endif // INFINI_CCL_BACKEND_H_ diff --git a/src/backend_device_map.h b/src/backend_device_map.h index 7cf46b0..8c65d82 100644 --- a/src/backend_device_map.h +++ b/src/backend_device_map.h @@ -33,6 +33,10 @@ template <> struct IsSupportedCombination : std::true_type {}; +template <> +struct IsSupportedCombination + : std::true_type {}; + }; // namespace infini::ccl #endif // INFINI_CCL_BACKEND_DEVICE_MAP_H_ diff --git a/src/backends/ccl/cncl/api.h b/src/backends/ccl/cncl/api.h new file mode 100644 index 0000000..709da32 --- /dev/null +++ b/src/backends/ccl/cncl/api.h @@ -0,0 +1,58 @@ +#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_API_H_ +#define INFINI_CCL_BACKENDS_CCL_CNCL_API_H_ + +#include + +#include + +#include "backends/ccl/common/api.h" +#include "logging.h" +#include "return_status_impl.h" +#include "runtime.h" + +namespace infini::ccl { + +template +struct CnclApi { + static constexpr BackendType kBackendType = BackendType::kCncl; + static constexpr Device::Type kDeviceType = device; + + using Comm = cnclComm_t; + using Result = cnclResult_t; + using DataType = cnclDataType_t; + using RedOp = cnclReduceOp_t; + using Stream = typename Runtime::Stream; + + static ReturnStatus Check(Result result) { + if (result != CNCL_RET_SUCCESS) { + LOG(cnclGetErrorStr(result)); + return ReturnStatus::kSystemError; + } + return ReturnStatus::kSuccess; + } + + static Result CommInitAll(Comm* comms, int n_dev, const int* dev_list, + const int* rank_list) { + return cnclInitComms(comms, n_dev, dev_list, rank_list, n_dev, nullptr); + } + + static Result CommDestroy(Comm comm) { return cnclFreeComm(comm); } + + static Result AllReduce(const void* send_buff, void* recv_buff, size_t count, + DataType data_type, RedOp op, Comm comm, + Stream stream) { + return cnclAllReduce(send_buff, recv_buff, count, data_type, op, comm, + stream); + } + + static Result AllGather(const void* send_buff, void* recv_buff, + size_t send_count, DataType data_type, Comm comm, + Stream stream) { + return cnclAllGather(send_buff, recv_buff, send_count, data_type, comm, + stream); + } +}; + +} // namespace infini::ccl + +#endif // INFINI_CCL_BACKENDS_CCL_CNCL_API_H_ diff --git a/src/backends/ccl/cncl/cambricon/api.h b/src/backends/ccl/cncl/cambricon/api.h new file mode 100644 index 0000000..865fc0e --- /dev/null +++ b/src/backends/ccl/cncl/cambricon/api.h @@ -0,0 +1,15 @@ +#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_CAMBRICON_API_H_ +#define INFINI_CCL_BACKENDS_CCL_CNCL_CAMBRICON_API_H_ + +#include "backends/ccl/cncl/api.h" +#include "devices/cambricon/runtime_.h" + +namespace infini::ccl { + +template <> +struct CclApi + : CnclApi {}; + +} // namespace infini::ccl + +#endif // INFINI_CCL_BACKENDS_CCL_CNCL_CAMBRICON_API_H_ diff --git a/src/backends/ccl/cncl/impl/all_gather.h b/src/backends/ccl/cncl/impl/all_gather.h new file mode 100644 index 0000000..6ab1dad --- /dev/null +++ b/src/backends/ccl/cncl/impl/all_gather.h @@ -0,0 +1,17 @@ +#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_ALL_GATHER_H_ +#define INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_ALL_GATHER_H_ + +#include "backends/ccl/common/impl/all_gather.h" + +namespace infini::ccl { + +template +class AllGatherImpl + : public CclAllGatherImpl {}; + +template <> +struct BackendEnabled : std::true_type {}; + +} // namespace infini::ccl + +#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_ALL_GATHER_H_ diff --git a/src/backends/ccl/cncl/impl/all_reduce.h b/src/backends/ccl/cncl/impl/all_reduce.h new file mode 100644 index 0000000..490f609 --- /dev/null +++ b/src/backends/ccl/cncl/impl/all_reduce.h @@ -0,0 +1,17 @@ +#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_ALL_REDUCE_H_ +#define INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_ALL_REDUCE_H_ + +#include "backends/ccl/common/impl/all_reduce.h" + +namespace infini::ccl { + +template +class AllReduceImpl + : public CclAllReduceImpl {}; + +template <> +struct BackendEnabled : std::true_type {}; + +} // namespace infini::ccl + +#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_ALL_REDUCE_H_ diff --git a/src/backends/ccl/cncl/impl/comm_destroy.h b/src/backends/ccl/cncl/impl/comm_destroy.h new file mode 100644 index 0000000..efc8899 --- /dev/null +++ b/src/backends/ccl/cncl/impl/comm_destroy.h @@ -0,0 +1,17 @@ +#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_DESTROY_H_ +#define INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_DESTROY_H_ + +#include "backends/ccl/common/impl/comm_destroy.h" + +namespace infini::ccl { + +template +class CommDestroyImpl + : public CclCommDestroyImpl {}; + +template <> +struct BackendEnabled : std::true_type {}; + +} // namespace infini::ccl + +#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_DESTROY_H_ diff --git a/src/backends/ccl/cncl/impl/comm_init_all.h b/src/backends/ccl/cncl/impl/comm_init_all.h new file mode 100644 index 0000000..06fdfa2 --- /dev/null +++ b/src/backends/ccl/cncl/impl/comm_init_all.h @@ -0,0 +1,75 @@ +#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_ALL_H_ +#define INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_ALL_H_ + +#include +#include +#include + +#include "backends/ccl/common/comm_instance.h" +#include "base/comm_init_all.h" +#include "communicator.h" +#include "runtime.h" + +namespace infini::ccl { + +template +class CommInitAllImpl { + public: + static ReturnStatus Apply(void** comm_handles, int n_dev, + const int* dev_list) { + using Api = CclApi; + using CommInstance = CclCommInstance; + using Rt = Runtime; + + if (!comm_handles || !dev_list || n_dev <= 0) { + return ReturnStatus::kInvalidArgument; + } + + auto** comms = reinterpret_cast(comm_handles); + for (int i = 0; i < n_dev; ++i) { + if (comms[i]) { + return ReturnStatus::kInvalidArgument; + } + } + + std::vector> wrappers; + std::vector> instances; + std::vector backend_comms(n_dev); + std::vector rank_list(n_dev); + wrappers.reserve(n_dev); + instances.reserve(n_dev); + std::iota(rank_list.begin(), rank_list.end(), 0); + + for (int i = 0; i < n_dev; ++i) { + auto status = Rt::Check(Rt::SetDevice(dev_list[i])); + if (status != ReturnStatus::kSuccess) { + return status; + } + wrappers.emplace_back( + std::make_unique(device, dev_list[i])); + instances.emplace_back(std::make_unique()); + } + + auto status = Api::Check(Api::CommInitAll(backend_comms.data(), n_dev, + dev_list, rank_list.data())); + if (status != ReturnStatus::kSuccess) { + return status; + } + + for (int i = 0; i < n_dev; ++i) { + instances[i]->handle = backend_comms[i]; + wrappers[i]->set_world_info(i, n_dev); + wrappers[i]->set_intra_comm(std::move(instances[i])); + comms[i] = wrappers[i].release(); + } + + return ReturnStatus::kSuccess; + } +}; + +template <> +struct BackendEnabled : std::true_type {}; + +} // namespace infini::ccl + +#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_ALL_H_ diff --git a/src/backends/ccl/cncl/type_map.h b/src/backends/ccl/cncl/type_map.h new file mode 100644 index 0000000..04f6eee --- /dev/null +++ b/src/backends/ccl/cncl/type_map.h @@ -0,0 +1,73 @@ +#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_TYPE_MAP_H_ +#define INFINI_CCL_BACKENDS_CCL_CNCL_TYPE_MAP_H_ + +#include + +#include "backends/ccl/common/api.h" +#include "comm_impl.h" +#include "data_type_impl.h" + +namespace infini::ccl { + +inline bool DataTypeToCnclType(DataType dtype, cnclDataType_t* cncl_dtype) { + switch (dtype) { + case DataType::kInt8: + *cncl_dtype = cnclInt8; + return true; + case DataType::kInt16: + *cncl_dtype = cnclInt16; + return true; + case DataType::kInt32: + *cncl_dtype = cnclInt32; + return true; + case DataType::kInt64: + *cncl_dtype = cnclInt64; + return true; + case DataType::kUInt8: + *cncl_dtype = cnclUint8; + return true; + case DataType::kUInt16: + *cncl_dtype = cnclUint16; + return true; + case DataType::kUInt32: + *cncl_dtype = cnclUint32; + return true; + case DataType::kUInt64: + *cncl_dtype = cnclUint64; + return true; + case DataType::kFloat16: + *cncl_dtype = cnclFloat16; + return true; + case DataType::kBFloat16: + *cncl_dtype = cnclBfloat16; + return true; + case DataType::kFloat32: + *cncl_dtype = cnclFloat32; + return true; + default: + return false; + } +} + +template <> +struct CclTypeMap { + using Api = CclApi; + + static bool ToBackendDataType(DataType dtype, + typename Api::DataType* backend_dtype) { + return DataTypeToCnclType(dtype, backend_dtype); + } + + static bool ToBackendRedOp(ReductionOpType red_op, + typename Api::RedOp* backend_op) { + if (red_op == ReductionOpType::kAvg) { + return false; + } + *backend_op = static_cast(red_op); + return true; + } +}; + +} // namespace infini::ccl + +#endif // INFINI_CCL_BACKENDS_CCL_CNCL_TYPE_MAP_H_ diff --git a/src/backends/mpi/ompi/impl/comm_init_all.h b/src/backends/mpi/ompi/impl/comm_init_all.h index e834622..7cf320b 100644 --- a/src/backends/mpi/ompi/impl/comm_init_all.h +++ b/src/backends/mpi/ompi/impl/comm_init_all.h @@ -12,19 +12,28 @@ namespace infini::ccl { template class CommInitAllImpl { public: - static ReturnStatus Apply(Communicator *comm, int n_dev, - const int *dev_list) { + static ReturnStatus Apply(void** comm_handles, int n_dev, + const int* dev_list) { constexpr Device::Type kDev = ListGetBest(ActiveDevices{}); using Rt = Runtime; - if (!comm) { + if (!comm_handles) { // TODO(lzm): change to use `glog`. LOG("Failed to initialize OpenMPI communicator: invalid " "communicator pointer."); return ReturnStatus::kInternalError; } + Communicator*& comm = *reinterpret_cast(comm_handles); + if (comm && comm->inter_comm()) { + LOG("Invalid communicator handle for `CommInitAll`."); + return ReturnStatus::kInvalidArgument; + } + if (!comm) { + comm = new Communicator(kDev, 0); + } + int rank, size; auto inst = std::make_unique(); INFINI_CHECK_MPI(MPI_Comm_dup(MPI_COMM_WORLD, &inst->handle)); @@ -35,7 +44,7 @@ class CommInitAllImpl { comm->set_inter_comm(std::move(inst)); int local_rank = 0; - char *local_rank_str = getenv("OMPI_COMM_WORLD_LOCAL_RANK"); + char* local_rank_str = getenv("OMPI_COMM_WORLD_LOCAL_RANK"); if (local_rank_str) { local_rank = atoi(local_rank_str); } diff --git a/src/base/comm_init_all.h b/src/base/comm_init_all.h index e737306..2371e50 100644 --- a/src/base/comm_init_all.h +++ b/src/base/comm_init_all.h @@ -13,25 +13,16 @@ struct CommInitAllImpl; class CommInitAll : public Operation { public: - template - static ReturnStatus Execute(void **comm_handle, Args &&...args) { - Communicator *&comm = *reinterpret_cast(comm_handle); - if (comm && comm->inter_comm()) { - // TODO(lzm): change to use `glog`. + template + static ReturnStatus Execute(void** comm_handles, int n_dev, + const int* dev_list) { + if (!comm_handles || n_dev <= 0) { LOG("Invalid communicator handle for `CommInitAll`."); return ReturnStatus::kInvalidArgument; } - constexpr Device::Type kDev = - ListGetBest(ActiveDevices{}); - - if (!comm) { - comm = new Communicator(kDev, 0); - } - - return CommInitAllImpl::Apply( - comm, std::forward(args)...); + return CommInitAllImpl::Apply(comm_handles, + n_dev, dev_list); } }; From 75c7aa4690e08ec8f6874e287f7b29c75c7f11f9 Mon Sep 17 00:00:00 2001 From: Zimin Li Date: Thu, 17 Sep 2026 18:29:20 +0800 Subject: [PATCH 2/2] feat: support the missing CCL implementations for CNCl and orgnaize relevant code - support `GetUniqueId` and `CommInitRank` for CNCL - remove the currently unsupported and irrelevant CCL backend of `CommInitAll` - set `INFINICCL_UNIQUE_ID_BYTES` to 136 to accommodate `cnclCliqueId` - organize code for `CommInitAll` and `CommInitRank` --- include/comm.h | 2 +- src/backends/ccl/cncl/api.h | 15 +++- src/backends/ccl/cncl/impl/comm_init_all.h | 75 ------------------- src/backends/ccl/cncl/impl/comm_init_rank.h | 17 +++++ src/backends/ccl/cncl/impl/get_unique_id.h | 17 +++++ src/backends/ccl/common/impl/comm_init_rank.h | 13 +++- src/backends/mpi/ompi/impl/comm_init_all.h | 18 +---- src/base/comm_init_all.h | 13 +++- src/base/comm_init_rank.h | 10 +-- 9 files changed, 77 insertions(+), 103 deletions(-) delete mode 100644 src/backends/ccl/cncl/impl/comm_init_all.h create mode 100644 src/backends/ccl/cncl/impl/comm_init_rank.h create mode 100644 src/backends/ccl/cncl/impl/get_unique_id.h diff --git a/include/comm.h b/include/comm.h index ec16c92..e36f2ac 100644 --- a/include/comm.h +++ b/include/comm.h @@ -10,7 +10,7 @@ extern "C" { #endif -#define INFINICCL_UNIQUE_ID_BYTES 128 +#define INFINICCL_UNIQUE_ID_BYTES 136 typedef void *infinicclComm_t; diff --git a/src/backends/ccl/cncl/api.h b/src/backends/ccl/cncl/api.h index 709da32..b2b8ca2 100644 --- a/src/backends/ccl/cncl/api.h +++ b/src/backends/ccl/cncl/api.h @@ -18,6 +18,7 @@ struct CnclApi { static constexpr Device::Type kDeviceType = device; using Comm = cnclComm_t; + using UniqueId = cnclCliqueId; using Result = cnclResult_t; using DataType = cnclDataType_t; using RedOp = cnclReduceOp_t; @@ -31,9 +32,17 @@ struct CnclApi { return ReturnStatus::kSuccess; } - static Result CommInitAll(Comm* comms, int n_dev, const int* dev_list, - const int* rank_list) { - return cnclInitComms(comms, n_dev, dev_list, rank_list, n_dev, nullptr); + static Result GetUniqueId(UniqueId* id) { return cnclGetCliqueId(id); } + + static Result CommInitRank(Comm* comm, int nranks, UniqueId id, int rank) { + using Rt = Runtime; + + int device_id = 0; + if (Rt::GetDevice(&device_id) != cnrtSuccess) { + return CNCL_RET_ERR_MLU_RUNTIME; + } + + return cnclInitComms(comm, 1, &device_id, &rank, nranks, &id); } static Result CommDestroy(Comm comm) { return cnclFreeComm(comm); } diff --git a/src/backends/ccl/cncl/impl/comm_init_all.h b/src/backends/ccl/cncl/impl/comm_init_all.h deleted file mode 100644 index 06fdfa2..0000000 --- a/src/backends/ccl/cncl/impl/comm_init_all.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_ALL_H_ -#define INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_ALL_H_ - -#include -#include -#include - -#include "backends/ccl/common/comm_instance.h" -#include "base/comm_init_all.h" -#include "communicator.h" -#include "runtime.h" - -namespace infini::ccl { - -template -class CommInitAllImpl { - public: - static ReturnStatus Apply(void** comm_handles, int n_dev, - const int* dev_list) { - using Api = CclApi; - using CommInstance = CclCommInstance; - using Rt = Runtime; - - if (!comm_handles || !dev_list || n_dev <= 0) { - return ReturnStatus::kInvalidArgument; - } - - auto** comms = reinterpret_cast(comm_handles); - for (int i = 0; i < n_dev; ++i) { - if (comms[i]) { - return ReturnStatus::kInvalidArgument; - } - } - - std::vector> wrappers; - std::vector> instances; - std::vector backend_comms(n_dev); - std::vector rank_list(n_dev); - wrappers.reserve(n_dev); - instances.reserve(n_dev); - std::iota(rank_list.begin(), rank_list.end(), 0); - - for (int i = 0; i < n_dev; ++i) { - auto status = Rt::Check(Rt::SetDevice(dev_list[i])); - if (status != ReturnStatus::kSuccess) { - return status; - } - wrappers.emplace_back( - std::make_unique(device, dev_list[i])); - instances.emplace_back(std::make_unique()); - } - - auto status = Api::Check(Api::CommInitAll(backend_comms.data(), n_dev, - dev_list, rank_list.data())); - if (status != ReturnStatus::kSuccess) { - return status; - } - - for (int i = 0; i < n_dev; ++i) { - instances[i]->handle = backend_comms[i]; - wrappers[i]->set_world_info(i, n_dev); - wrappers[i]->set_intra_comm(std::move(instances[i])); - comms[i] = wrappers[i].release(); - } - - return ReturnStatus::kSuccess; - } -}; - -template <> -struct BackendEnabled : std::true_type {}; - -} // namespace infini::ccl - -#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_ALL_H_ diff --git a/src/backends/ccl/cncl/impl/comm_init_rank.h b/src/backends/ccl/cncl/impl/comm_init_rank.h new file mode 100644 index 0000000..8ca3f59 --- /dev/null +++ b/src/backends/ccl/cncl/impl/comm_init_rank.h @@ -0,0 +1,17 @@ +#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_RANK_H_ +#define INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_RANK_H_ + +#include "backends/ccl/common/impl/comm_init_rank.h" + +namespace infini::ccl { + +template +class CommInitRankImpl + : public CclCommInitRankImpl {}; + +template <> +struct BackendEnabled : std::true_type {}; + +} // namespace infini::ccl + +#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_RANK_H_ diff --git a/src/backends/ccl/cncl/impl/get_unique_id.h b/src/backends/ccl/cncl/impl/get_unique_id.h new file mode 100644 index 0000000..fac71f2 --- /dev/null +++ b/src/backends/ccl/cncl/impl/get_unique_id.h @@ -0,0 +1,17 @@ +#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_GET_UNIQUE_ID_H_ +#define INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_GET_UNIQUE_ID_H_ + +#include "backends/ccl/common/impl/get_unique_id.h" + +namespace infini::ccl { + +template +class GetUniqueIdImpl + : public CclGetUniqueIdImpl {}; + +template <> +struct BackendEnabled : std::true_type {}; + +} // namespace infini::ccl + +#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_GET_UNIQUE_ID_H_ diff --git a/src/backends/ccl/common/impl/comm_init_rank.h b/src/backends/ccl/common/impl/comm_init_rank.h index 2b7adee..aced7b5 100644 --- a/src/backends/ccl/common/impl/comm_init_rank.h +++ b/src/backends/ccl/common/impl/comm_init_rank.h @@ -1,6 +1,7 @@ #ifndef INFINI_CCL_BACKENDS_CCL_COMMON_IMPL_COMM_INIT_RANK_H_ #define INFINI_CCL_BACKENDS_CCL_COMMON_IMPL_COMM_INIT_RANK_H_ +#include #include #include "backends/ccl/common/api.h" @@ -19,12 +20,18 @@ class CclCommInitRankImpl { using Api = CclApi; using CommInstance = CclCommInstance; - const auto *backend_id = - reinterpret_cast(id.internal); + if (comm && comm->intra_comm()) { + // TODO(lzm): change to use `glog`. + LOG("Invalid communicator handle for `CommInitRank`."); + return ReturnStatus::kInvalidArgument; + } + + typename Api::UniqueId backend_id{}; + std::memcpy(&backend_id, id.internal, sizeof(backend_id)); typename Api::Comm ccl_handle{}; auto status = - Api::Check(Api::CommInitRank(&ccl_handle, nranks, *backend_id, rank)); + Api::Check(Api::CommInitRank(&ccl_handle, nranks, backend_id, rank)); if (status != ReturnStatus::kSuccess) { return status; } diff --git a/src/backends/mpi/ompi/impl/comm_init_all.h b/src/backends/mpi/ompi/impl/comm_init_all.h index 7cf320b..3217655 100644 --- a/src/backends/mpi/ompi/impl/comm_init_all.h +++ b/src/backends/mpi/ompi/impl/comm_init_all.h @@ -12,27 +12,17 @@ namespace infini::ccl { template class CommInitAllImpl { public: - static ReturnStatus Apply(void** comm_handles, int n_dev, - const int* dev_list) { + static ReturnStatus Apply(Communicator *comm, int n_dev, + const int *dev_list) { constexpr Device::Type kDev = ListGetBest(ActiveDevices{}); using Rt = Runtime; - if (!comm_handles) { - // TODO(lzm): change to use `glog`. - LOG("Failed to initialize OpenMPI communicator: invalid " - "communicator pointer."); - return ReturnStatus::kInternalError; - } - - Communicator*& comm = *reinterpret_cast(comm_handles); if (comm && comm->inter_comm()) { + // TODO(lzm): change to use `glog`. LOG("Invalid communicator handle for `CommInitAll`."); return ReturnStatus::kInvalidArgument; } - if (!comm) { - comm = new Communicator(kDev, 0); - } int rank, size; auto inst = std::make_unique(); @@ -44,7 +34,7 @@ class CommInitAllImpl { comm->set_inter_comm(std::move(inst)); int local_rank = 0; - char* local_rank_str = getenv("OMPI_COMM_WORLD_LOCAL_RANK"); + char *local_rank_str = getenv("OMPI_COMM_WORLD_LOCAL_RANK"); if (local_rank_str) { local_rank = atoi(local_rank_str); } diff --git a/src/base/comm_init_all.h b/src/base/comm_init_all.h index 2371e50..c37d781 100644 --- a/src/base/comm_init_all.h +++ b/src/base/comm_init_all.h @@ -21,8 +21,17 @@ class CommInitAll : public Operation { return ReturnStatus::kInvalidArgument; } - return CommInitAllImpl::Apply(comm_handles, - n_dev, dev_list); + constexpr Device::Type kDev = + ListGetBest(ActiveDevices{}); + + Communicator *&comm = *reinterpret_cast(comm_handle); + + if (!comm) { + comm = new Communicator(kDev, 0); + } + + return CommInitAllImpl::Apply( + comm, std::forward(args)...); } }; diff --git a/src/base/comm_init_rank.h b/src/base/comm_init_rank.h index 46f93f2..e4391d4 100644 --- a/src/base/comm_init_rank.h +++ b/src/base/comm_init_rank.h @@ -14,11 +14,9 @@ class CommInitRank : public Operation { public: template - static ReturnStatus Execute(void **comm_handle, Args &&...args) { - Communicator *&comm = *reinterpret_cast(comm_handle); - if (comm && comm->intra_comm()) { - // TODO(lzm): change to use `glog`. - LOG("Invalid communicator handle for `CommInitRank`."); + static ReturnStatus Execute(void **comm_handle, Args &&...args) { + if (!comm_handle) { + LOG("Invalid communicator handle for `CommInitAll`."); return ReturnStatus::kInvalidArgument; } @@ -29,6 +27,8 @@ class CommInitRank : public Operation { int current_dev = 0; CHECK_STATUS(Rt, Rt::GetDevice(¤t_dev)); + Communicator *&comm = *reinterpret_cast(comm_handle); + if (!comm) { comm = new Communicator(kDev, current_dev); } else {