Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 ---
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion include/comm.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
extern "C" {
#endif

#define INFINICCL_UNIQUE_ID_BYTES 128
#define INFINICCL_UNIQUE_ID_BYTES 136

typedef void *infinicclComm_t;

Expand Down
3 changes: 3 additions & 0 deletions scripts/gen_bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}

# =================================================================
Expand Down
10 changes: 10 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 ---
# =========================================================
Expand Down
5 changes: 5 additions & 0 deletions src/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ struct BackendPriority<BackendType::kMccl> {
static constexpr int value = 10;
};

template <>
struct BackendPriority<BackendType::kCncl> {
static constexpr int value = 10;
};

} // namespace infini::ccl

#endif // INFINI_CCL_BACKEND_H_
4 changes: 4 additions & 0 deletions src/backend_device_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ template <>
struct IsSupportedCombination<BackendType::kMccl, Device::Type::kMoore>
: std::true_type {};

template <>
struct IsSupportedCombination<BackendType::kCncl, Device::Type::kCambricon>
: std::true_type {};

}; // namespace infini::ccl

#endif // INFINI_CCL_BACKEND_DEVICE_MAP_H_
67 changes: 67 additions & 0 deletions src/backends/ccl/cncl/api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_API_H_
#define INFINI_CCL_BACKENDS_CCL_CNCL_API_H_

#include <cncl.h>

#include <cstddef>

#include "backends/ccl/common/api.h"
#include "logging.h"
#include "return_status_impl.h"
#include "runtime.h"

namespace infini::ccl {

template <Device::Type device>
struct CnclApi {
static constexpr BackendType kBackendType = BackendType::kCncl;
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;
using Stream = typename Runtime<device>::Stream;

static ReturnStatus Check(Result result) {
if (result != CNCL_RET_SUCCESS) {
LOG(cnclGetErrorStr(result));
return ReturnStatus::kSystemError;
}
return ReturnStatus::kSuccess;
}

static Result GetUniqueId(UniqueId* id) { return cnclGetCliqueId(id); }

static Result CommInitRank(Comm* comm, int nranks, UniqueId id, int rank) {
using Rt = Runtime<device>;

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); }

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_
15 changes: 15 additions & 0 deletions src/backends/ccl/cncl/cambricon/api.h
Original file line number Diff line number Diff line change
@@ -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<BackendType::kCncl, Device::Type::kCambricon>
: CnclApi<Device::Type::kCambricon> {};

} // namespace infini::ccl

#endif // INFINI_CCL_BACKENDS_CCL_CNCL_CAMBRICON_API_H_
17 changes: 17 additions & 0 deletions src/backends/ccl/cncl/impl/all_gather.h
Original file line number Diff line number Diff line change
@@ -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 <Device::Type device>
class AllGatherImpl<BackendType::kCncl, device>
: public CclAllGatherImpl<BackendType::kCncl, device> {};

template <>
struct BackendEnabled<AllGather, BackendType::kCncl> : std::true_type {};

} // namespace infini::ccl

#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_ALL_GATHER_H_
17 changes: 17 additions & 0 deletions src/backends/ccl/cncl/impl/all_reduce.h
Original file line number Diff line number Diff line change
@@ -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 <Device::Type device>
class AllReduceImpl<BackendType::kCncl, device>
: public CclAllReduceImpl<BackendType::kCncl, device> {};

template <>
struct BackendEnabled<AllReduce, BackendType::kCncl> : std::true_type {};

} // namespace infini::ccl

#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_ALL_REDUCE_H_
17 changes: 17 additions & 0 deletions src/backends/ccl/cncl/impl/comm_destroy.h
Original file line number Diff line number Diff line change
@@ -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 <Device::Type device>
class CommDestroyImpl<BackendType::kCncl, device>
: public CclCommDestroyImpl<BackendType::kCncl, device> {};

template <>
struct BackendEnabled<CommDestroy, BackendType::kCncl> : std::true_type {};

} // namespace infini::ccl

#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_DESTROY_H_
17 changes: 17 additions & 0 deletions src/backends/ccl/cncl/impl/comm_init_rank.h
Original file line number Diff line number Diff line change
@@ -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 <Device::Type device>
class CommInitRankImpl<BackendType::kCncl, device>
: public CclCommInitRankImpl<BackendType::kCncl, device> {};

template <>
struct BackendEnabled<CommInitRank, BackendType::kCncl> : std::true_type {};

} // namespace infini::ccl

#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_COMM_INIT_RANK_H_
17 changes: 17 additions & 0 deletions src/backends/ccl/cncl/impl/get_unique_id.h
Original file line number Diff line number Diff line change
@@ -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 <Device::Type device>
class GetUniqueIdImpl<BackendType::kCncl, device>
: public CclGetUniqueIdImpl<BackendType::kCncl, device> {};

template <>
struct BackendEnabled<GetUniqueId, BackendType::kCncl> : std::true_type {};

} // namespace infini::ccl

#endif // INFINI_CCL_BACKENDS_CCL_CNCL_IMPL_GET_UNIQUE_ID_H_
73 changes: 73 additions & 0 deletions src/backends/ccl/cncl/type_map.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#ifndef INFINI_CCL_BACKENDS_CCL_CNCL_TYPE_MAP_H_
#define INFINI_CCL_BACKENDS_CCL_CNCL_TYPE_MAP_H_

#include <cncl.h>

#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<BackendType::kCncl, Device::Type::kCambricon> {
using Api = CclApi<BackendType::kCncl, Device::Type::kCambricon>;

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<cnclReduceOp_t>(red_op);
return true;
}
};

} // namespace infini::ccl

#endif // INFINI_CCL_BACKENDS_CCL_CNCL_TYPE_MAP_H_
13 changes: 10 additions & 3 deletions src/backends/ccl/common/impl/comm_init_rank.h
Original file line number Diff line number Diff line change
@@ -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 <cstring>
#include <memory>

#include "backends/ccl/common/api.h"
Expand All @@ -19,12 +20,18 @@ class CclCommInitRankImpl {
using Api = CclApi<backend, device>;
using CommInstance = CclCommInstance<Api>;

const auto *backend_id =
reinterpret_cast<const typename Api::UniqueId *>(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;
}
Expand Down
Loading
Loading