Skip to content

Commit 7127fd2

Browse files
authored
feat: support MCCL on MetaX (#50)
* feat: support MCCL on MetaX * docs: update `README.md` to document MetaX MCCL support * docs: update the GitHub PR template to include MCCL as a valid backend * fix: add the type mapping for `DataType::kBFloat16` for MCCL
1 parent 1e4f82f commit 7127fd2

16 files changed

Lines changed: 324 additions & 3 deletions

‎.github/pull_request_template.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ Please check all the platforms and/or backends this PR affects (i.e., code is to
6464
- [ ] OpenMPI
6565
- [ ] MPICH
6666
- [ ] NCCL
67+
- [ ] MCCL
6768

6869
## Performance Impact
6970

@@ -112,6 +113,7 @@ See `CONTRIBUTING.md` § Pull Requests for the official testing requirements and
112113
- [ ] OpenMPI
113114
- [ ] MPICH
114115
- [ ] NCCL
116+
- [ ] MCCL
115117

116118
---
117119

‎CMakeLists.txt‎

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ set(WITH_CPU ON CACHE INTERNAL "CPU backend is always enabled")
2121
option(WITH_OMPI "Enable OpenMPI backend" OFF)
2222
option(WITH_MPICH "Enable MPICH backend" OFF)
2323
option(WITH_NCCL "Enable NCCL backend" OFF)
24+
option(WITH_MCCL "Enable MCCL backend" OFF)
2425

2526
# =========================================================
2627
# --- MISC. BUILD OPTIONS ---
@@ -228,10 +229,31 @@ if(AUTO_DETECT_BACKENDS)
228229
else()
229230
message(STATUS "No suitable device environment, skipping NCCL detection.")
230231
endif()
232+
233+
# Detect MCCL Dependencies
234+
if(WITH_METAX)
235+
set(_MCCL_HINTS)
236+
if(DEFINED ENV{MACA_PATH})
237+
list(APPEND _MCCL_HINTS "$ENV{MACA_PATH}")
238+
endif()
239+
list(APPEND _MCCL_HINTS /opt/maca)
240+
241+
find_path(AUTO_MCCL_INC NAMES mccl.h HINTS ${_MCCL_HINTS} PATH_SUFFIXES include QUIET)
242+
find_library(AUTO_MCCL_LIB NAMES mccl HINTS ${_MCCL_HINTS} PATH_SUFFIXES lib lib64 QUIET)
243+
244+
if(AUTO_MCCL_INC AND AUTO_MCCL_LIB)
245+
set(WITH_MCCL ON)
246+
message(STATUS "Auto-detected MCCL backend.")
247+
else()
248+
message(STATUS "MCCL library/headers not found in MetaX paths.")
249+
endif()
250+
else()
251+
message(STATUS "No suitable device environment, skipping MCCL detection.")
252+
endif()
231253
endif()
232254

233255
# Fallback: If no backends are enabled or auto-detected, fall back to OpenMPI as the default bootstrap profile.
234-
if(NOT WITH_OMPI AND NOT WITH_MPICH AND NOT WITH_NCCL)
256+
if(NOT WITH_OMPI AND NOT WITH_MPICH AND NOT WITH_NCCL AND NOT WITH_MCCL)
235257
set(WITH_OMPI ON)
236258
message(STATUS "No backend specified or detected. Defaulting to `WITH_OMPI=ON`")
237259
endif()
@@ -349,6 +371,26 @@ if(WITH_NCCL)
349371
include_directories(${NCCL_INC})
350372
endif()
351373

374+
if(WITH_MCCL)
375+
if (NOT WITH_METAX)
376+
message(FATAL_ERROR "MCCL backend requires MetaX GPU support. Please enable `WITH_METAX`.")
377+
endif()
378+
379+
set(_MCCL_HINTS)
380+
if(MACA_PATH)
381+
list(APPEND _MCCL_HINTS "${MACA_PATH}")
382+
endif()
383+
if(DEFINED ENV{MACA_PATH})
384+
list(APPEND _MCCL_HINTS "$ENV{MACA_PATH}")
385+
endif()
386+
list(APPEND _MCCL_HINTS /opt/maca)
387+
388+
find_library(MCCL_LIB NAMES mccl HINTS ${_MCCL_HINTS} PATH_SUFFIXES lib lib64 REQUIRED)
389+
find_path(MCCL_INC NAMES mccl.h HINTS ${_MCCL_HINTS} PATH_SUFFIXES include REQUIRED)
390+
391+
include_directories(${MCCL_INC})
392+
endif()
393+
352394
# Python is required for code generation.
353395
find_package(Python3 REQUIRED)
354396

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ cmake .. -DWITH_NVIDIA=ON -DWITH_OMPI=ON
142142
| `WITH_OMPI` | Enable OpenMPI backend | `ON` if no backend specified, otherwise `OFF` |
143143
| `WITH_MPICH` | Enable MPICH backend | `OFF` |
144144
| `WITH_NCCL` | Enable NCCL backend | `OFF` |
145+
| `WITH_MCCL` | Enable MCCL backend | `OFF` |
145146
| **Miscellaneous** |||
146147
| `AUTO_DETECT_DEVICES` | Automatically detect available devices and enable corresponding support | `ON` |
147148
| `AUTO_DETECT_BACKENDS` | Automatically detect available communication backends and enable corresponding support | `OFF` |
@@ -353,6 +354,7 @@ export LD_LIBRARY_PATH=${INFINI_INSTALL}/lib:$LD_LIBRARY_PATH
353354
| **OpenMPI** | Full | `WITH_OMPI=ON` | The default backend. Requires the OpenMPI development package.|
354355
| **MPICH** | Full | `WITH_MPICH=ON` | Requires the MPICH development package.|
355356
| **NCCL** | Partial | `WITH_NCCL=ON` | Requires NVIDIA or Iluvatar NCCL. Currently available when `WITH_NVIDIA=ON` or `WITH_ILUVATAR=ON`.|
357+
| **MCCL** | Partial | `WITH_MCCL=ON` | Requires MetaX's MCCL. Currently only available when `WITH_METAX=ON`.|
356358

357359
</details>
358360

‎examples/CMakeLists.txt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ foreach(source_file ${EXAMPLE_SOURCES})
5757
target_link_libraries(${target_name} PRIVATE "${NCCL_LIB}")
5858
endif()
5959

60+
if(WITH_MCCL)
61+
target_link_libraries(${target_name} PRIVATE "${MCCL_LIB}")
62+
endif()
63+
6064
# Explicitly allow examples to "peek" into the internal `src` and binary dirs.
6165
# This is necessary because these were marked `PRIVATE` in the library's CMake.
6266
target_include_directories(${target_name} PRIVATE

‎scripts/gen_bridge.py‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,17 @@
3131
"ompi": ["backends/mpi/ompi/impl"],
3232
"mpich": ["backends/mpi/ompi/impl"],
3333
"nccl": ["backends/ccl/nccl/impl"],
34+
"mccl": ["backends/ccl/mccl/impl"],
3435
}
3536

3637
BACKEND_COMMON_HEADERS = {
3738
"nccl": ["backends/ccl/nccl/type_map.h"],
39+
"mccl": ["backends/ccl/mccl/type_map.h"],
40+
}
41+
42+
CCL_PROVIDER_BACKENDS = {
43+
"nccl": "backends/ccl/nccl",
44+
"mccl": "backends/ccl/mccl",
3845
}
3946

4047
# =================================================================
@@ -130,9 +137,10 @@ def generate(project_root, output_dir, devices, backends):
130137

131138
manifest_lines.append(f"\n// --- BACKEND: {bb.upper()} ---")
132139

133-
if bb == "nccl":
140+
provider_root = CCL_PROVIDER_BACKENDS.get(bb)
141+
if provider_root:
134142
for dev in devices:
135-
provider_path = f"backends/ccl/nccl/{dev}/api.h"
143+
provider_path = f"{provider_root}/{dev}/api.h"
136144
if os.path.exists(os.path.join(src_dir, provider_path)):
137145
manifest_lines.append(f'#include "{provider_path}"')
138146

‎src/CMakeLists.txt‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,16 @@ if(WITH_NCCL)
235235
target_link_libraries(infiniccl PRIVATE ${NCCL_LIB})
236236
endif()
237237

238+
# MCCL
239+
if(WITH_MCCL)
240+
list(APPEND BACKEND_LIST "mccl")
241+
file(GLOB_RECURSE MCCL_SRCS "backends/ccl/mccl/*.cc" "backends/ccl/mccl/*.cpp" "backends/ccl/mccl/*.maca")
242+
243+
target_sources(infiniccl PRIVATE ${MCCL_SRCS})
244+
target_include_directories(infiniccl PRIVATE ${MCCL_INC})
245+
target_link_libraries(infiniccl PRIVATE ${MCCL_LIB})
246+
endif()
247+
238248
# =========================================================
239249
# --- File Generation ---
240250
# =========================================================

‎src/backend.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ struct BackendPriority<BackendType::kNccl> {
5858
static constexpr int value = 10;
5959
};
6060

61+
template <>
62+
struct BackendPriority<BackendType::kMccl> {
63+
static constexpr int value = 10;
64+
};
65+
6166
} // namespace infini::ccl
6267

6368
#endif // INFINI_CCL_BACKEND_H_

‎src/backend_device_map.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ template <>
2121
struct IsSupportedCombination<BackendType::kNccl, Device::Type::kIluvatar>
2222
: std::true_type {};
2323

24+
template <>
25+
struct IsSupportedCombination<BackendType::kMccl, Device::Type::kMetax>
26+
: std::true_type {};
27+
2428
}; // namespace infini::ccl
2529

2630
#endif // INFINI_CCL_BACKEND_DEVICE_MAP_H_

‎src/backends/ccl/mccl/api.h‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#ifndef INFINI_CCL_BACKENDS_CCL_MCCL_API_H_
2+
#define INFINI_CCL_BACKENDS_CCL_MCCL_API_H_
3+
4+
#include <mccl.h>
5+
6+
#include <cstddef>
7+
8+
#include "backends/ccl/common/api.h"
9+
#include "logging.h"
10+
#include "return_status_impl.h"
11+
#include "runtime.h"
12+
13+
namespace infini::ccl {
14+
15+
template <Device::Type device>
16+
struct McclApi {
17+
static constexpr BackendType kBackendType = BackendType::kMccl;
18+
static constexpr Device::Type kDeviceType = device;
19+
20+
using Comm = mcclComm_t;
21+
using UniqueId = mcclUniqueId;
22+
using Result = mcclResult_t;
23+
using DataType = mcclDataType_t;
24+
using RedOp = mcclRedOp_t;
25+
using Stream = typename Runtime<device>::Stream;
26+
27+
static ReturnStatus Check(Result result) {
28+
if (result != mcclSuccess) {
29+
LOG(mcclGetErrorString(result));
30+
return ReturnStatus::kSystemError;
31+
}
32+
return ReturnStatus::kSuccess;
33+
}
34+
35+
static Result GetUniqueId(UniqueId *id) { return mcclGetUniqueId(id); }
36+
37+
static Result CommInitRank(Comm *comm, int nranks, UniqueId id, int rank) {
38+
return mcclCommInitRank(comm, nranks, id, rank);
39+
}
40+
41+
static Result CommDestroy(Comm comm) { return mcclCommDestroy(comm); }
42+
43+
static Result AllReduce(const void *send_buff, void *recv_buff, size_t count,
44+
DataType data_type, RedOp op, Comm comm,
45+
Stream stream) {
46+
return mcclAllReduce(send_buff, recv_buff, count, data_type, op, comm,
47+
stream);
48+
}
49+
};
50+
51+
} // namespace infini::ccl
52+
53+
#endif // INFINI_CCL_BACKENDS_CCL_MCCL_API_H_

‎src/backends/ccl/mccl/checks.h‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifndef INFINI_CCL_BACKENDS_CCL_MCCL_CHECKS_H_
2+
#define INFINI_CCL_BACKENDS_CCL_MCCL_CHECKS_H_
3+
4+
#include <mccl.h>
5+
6+
#include <iostream>
7+
8+
#include "return_status_impl.h"
9+
10+
#define INFINI_CHECK_MCCL(result) \
11+
::infini::ccl::detail::CheckMcclImpl((result), __FILE__, __LINE__)
12+
13+
namespace infini::ccl {
14+
15+
namespace detail {
16+
17+
inline ReturnStatus CheckMcclImpl(mcclResult_t mccl_result, const char *file,
18+
int line) {
19+
if (mccl_result != mcclSuccess) {
20+
std::cerr << "backend(mccl) MCCL error code: " << mccl_result << " at line "
21+
<< line << " in " << file << std::endl;
22+
std::abort();
23+
}
24+
return ReturnStatus::kSuccess;
25+
}
26+
27+
} // namespace detail
28+
29+
} // namespace infini::ccl
30+
31+
#endif // INFINI_CCL_BACKENDS_CCL_MCCL_CHECKS_H_

0 commit comments

Comments
 (0)