Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
* text=auto eol=lf
*.sh text eol=lf
*.mlu text eol=lf
*.cc text eol=lf
*.h text eol=lf
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@
*.log
*.report.rank*
*.records.log.rank*

# MLU provider local artifacts
*.cndump
core
core.*
__pycache__/
/backends/mlu/tests/math_selftest/math_selftest
/backends/mlu/tests/math_selftest/*.o
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ process may register at most one provider for `DeviceType::kPrivateUse1`.
| Backend | Runtime | Collectives | Model examples |
| ------- | ------- | ----------- | -------------- |
| [MACA](backends/maca/README.md) | MACA | MCCL (optional) | GPT-2, LLaMA 3, Mixtral |
| [MLU](backends/mlu/README.md) (work in progress) | CNRT | — | GPT-2 |

The model sources normally come from the pinned InfiniTrain submodule. Each
backend supplies the runtime, kernels, collective implementation, and build
Expand Down Expand Up @@ -114,6 +115,23 @@ CMake cannot replace a compiler after a language has been enabled.
See [formatting and static checks](scripts/README.md) for clang-format,
clang-tidy and IWYU setup, scope and manual usage (in Chinese).

## Cambricon MLU provider (work in progress)

`backends/mlu` registers a `PrivateUse1` backend named `mlu` for Cambricon MLU
devices. Small-shape FP32 operators and the device math functions are covered by
regression tools; device GEMM, full GPT-2 10-step accuracy, BF16 and multi-card
collectives are **not** done yet.

```bash
cmake -S . -B build-mlu -G Ninja \
-DINFINITRAIN_BACKEND=mlu -DUSE_CUDA=OFF -DBUILD_TEST=OFF
cmake --build build-mlu --target mlu_gpt2 mlu_op_test -j
```

See [the MLU provider guide](backends/mlu/README.md) for the SDK requirements and
[its validation status](backends/mlu/docs/validation.md) for what has actually
been run.

## License

InfiniTrain Backends is released under the [MIT License](LICENSE).
16 changes: 16 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ InfiniTrain 子模块。每个构建目录只选择一个后端,每个进程
| 后端 | 运行时 | 集合通信 | 模型示例 |
| ---- | ------ | -------- | -------- |
| [MACA](backends/maca/README.zh-CN.md) | MACA | MCCL(可选) | GPT-2、LLaMA 3、Mixtral |
| [MLU](backends/mlu/README.md)(开发中) | CNRT | — | GPT-2 |

模型源码通常来自锁定版本的 InfiniTrain 子模块。各后端提供运行时、算子、集合通信
实现和构建集成,以便在对应加速器上运行其支持的模型示例。环境配置和使用方式见上表
Expand Down Expand Up @@ -104,6 +105,21 @@ CMake 无法在启用某种语言后更换其编译器。
clang-format、clang-tidy 和 IWYU 的范围、依赖及手动使用方式见
[代码格式和静态检查](scripts/README.md)。

## 寒武纪 MLU 后端(开发中)

`backends/mlu` 通过 `PrivateUse1` 注册名为 `mlu` 的后端。小 shape 的 FP32 算子
和设备数学函数已有回归工具覆盖;设备 GEMM、完整 GPT-2 十步精度、BF16 和多卡
集合通信**尚未完成**。

```bash
cmake -S . -B build-mlu -G Ninja \
-DINFINITRAIN_BACKEND=mlu -DUSE_CUDA=OFF -DBUILD_TEST=OFF
cmake --build build-mlu --target mlu_gpt2 mlu_op_test -j
```

SDK 依赖见 [MLU 后端指南](backends/mlu/README.md),实际验证状态见
[验证状态](backends/mlu/docs/validation.md)。

## 许可证

InfiniTrain Backends 使用 [MIT 许可证](LICENSE)。
136 changes: 136 additions & 0 deletions backends/mlu/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Cambricon MLU provider.
#
# Registers a PrivateUse1 backend named "mlu": the runtime, the kernel host
# integration and the BANG C device code all live under this directory, so no
# InfiniTrain source file is modified. BANG C sources are compiled by cncc with
# a custom command; host sources are ordinary C++ compiled by the selected host
# compiler.

find_program(CNCC_EXECUTABLE cncc HINTS "${NEUWARE_HOME}/bin" REQUIRED)
find_library(CNRT_LIBRARY cnrt HINTS "${NEUWARE_HOME}/lib64" REQUIRED)

# CNNL ships separately from the base Neuware image. When it is missing the
# build still produces a working runtime and kernels; only the BLAS handle is
# left out. No operator calls CNNL yet - GEMM still uses the host fallback.
option(INFINITRAIN_MLU_WITH_CNNL "Compile the CNNL BLAS handle support" ON)
if(INFINITRAIN_MLU_WITH_CNNL)
find_library(CNNL_LIBRARY cnnl HINTS "${NEUWARE_HOME}/lib64")
if(NOT CNNL_LIBRARY OR NOT EXISTS "${NEUWARE_HOME}/include/cnnl.h")
message(WARNING
"CNNL was not found under ${NEUWARE_HOME}; configuring without BLAS "
"handle support. Install CNNL and reconfigure to enable it.")
set(INFINITRAIN_MLU_WITH_CNNL OFF)
endif()
endif()

# BANG C target architecture; empty lets cncc use its default.
set(MLU_ARCH "" CACHE STRING "BANG C target arch, for example mtp_592")

option(INFINITRAIN_MLU_BUILD_TEST_TOOLS
"Build the MLU operator and device-math regression tools" ON)

# ------------------------------------------------------------------------------
# Runtime, registration entry and kernel host integration (host compiler)
# ------------------------------------------------------------------------------
set(MLU_BACKEND_SOURCES
src/backend.cc
src/runtime/mlu_runtime_common.cc
src/runtime/mlu_guard_impl.cc
src/kernels/no_op.cc
src/kernels/fill.cc
src/kernels/cast.cc
src/kernels/accumulate_grad.cc
src/kernels/elementwise.cc
src/kernels/embedding.cc
src/kernels/layernorm.cc
src/kernels/softmax.cc
src/kernels/cross_entropy.cc
src/kernels/transform.cc
src/kernels/linear.cc
)

add_library(infini_train_mlu STATIC ${MLU_BACKEND_SOURCES})
add_library(InfiniTrain::Backend::MLU ALIAS infini_train_mlu)

# Only include/infini_train_mlu is public: examples and tools consume the
# registration entry point, never the provider's internal layout. Internal
# headers (common/, runtime/, kernels/) resolve against src/, which stays
# PRIVATE and is added explicitly by the targets that need it.
target_include_directories(infini_train_mlu
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/src"
"${INFINITRAIN_SOURCE_DIR}"
"${NEUWARE_HOME}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/bang_host"
)

target_link_libraries(infini_train_mlu PUBLIC
InfiniTrain::infini_train
${CNRT_LIBRARY}
)

if(INFINITRAIN_MLU_WITH_CNNL)
target_compile_definitions(infini_train_mlu PUBLIC USE_CNNL=1)
target_link_libraries(infini_train_mlu PUBLIC ${CNNL_LIBRARY})
endif()

# ------------------------------------------------------------------------------
# BANG C kernels (*.mlu): CMake has no BANG C language, so cncc is invoked
# directly and the resulting objects form their own archive.
# ------------------------------------------------------------------------------
file(GLOB MLU_KERNEL_SOURCES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/kernels/*.mlu")

set(MLU_KERNEL_OBJECTS)
foreach(src ${MLU_KERNEL_SOURCES})
get_filename_component(name ${src} NAME_WE)
set(obj "${CMAKE_CURRENT_BINARY_DIR}/${name}.o")
set(arch_flags)
if(MLU_ARCH)
list(APPEND arch_flags --bang-mlu-arch=${MLU_ARCH})
endif()
add_custom_command(
OUTPUT ${obj}
COMMAND ${CMAKE_COMMAND} -E env NEUWARE_HOME=${NEUWARE_HOME}
${CNCC_EXECUTABLE} -std=c++17 -fPIC -c ${src} -o ${obj} ${arch_flags}
"-I${CMAKE_CURRENT_SOURCE_DIR}/src"
"-I${NEUWARE_HOME}/include"
DEPENDS ${src}
"${CMAKE_CURRENT_SOURCE_DIR}/src/kernels/mlu_kernel_api.h"
COMMENT "cncc ${name}.mlu"
VERBATIM
)
list(APPEND MLU_KERNEL_OBJECTS ${obj})
endforeach()

add_library(infini_train_mlu_kernels STATIC ${MLU_KERNEL_OBJECTS})
set_target_properties(infini_train_mlu_kernels PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(infini_train_mlu_kernels PUBLIC infini_train_mlu)

# Static registrations (framework, CPU kernels, MLU runtime and MLU kernels) are
# only discovered through global initialization, so final executables must link
# them whole-archive. Reuse the framework helper instead of spelling out the
# link-group rules here.
add_library(infini_train_backend_mlu_executable INTERFACE)
add_library(InfiniTrain::Backend::MLUExecutable ALIAS
infini_train_backend_mlu_executable)
link_infini_train_exe(infini_train_backend_mlu_executable
EXTRA_ARCHIVES infini_train_mlu infini_train_mlu_kernels)

if(BUILD_TEST)
message(FATAL_ERROR
"The MLU provider does not wire the shared InfiniTrain test suites yet. "
"Configure with -DBUILD_TEST=OFF and use the MLU regression tools "
"(-DINFINITRAIN_MLU_BUILD_TEST_TOOLS=ON) instead of reporting CPU test "
"results for the MLU device.")
endif()

if(INFINITRAIN_MLU_BUILD_TEST_TOOLS)
add_subdirectory(tests)
endif()

if(INFINITRAIN_BACKENDS_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
98 changes: 98 additions & 0 deletions backends/mlu/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# MLU backend (Cambricon)

`backends/mlu` registers a `PrivateUse1` backend named `mlu` for Cambricon MLU devices. It is a
**work-in-progress** integration: see [`docs/validation.md`](docs/validation.md) for what has
actually been run and what has not.

## Architecture in one paragraph

InfiniTrain exposes third-party devices through the `PrivateUse1` mechanism: no new
`DeviceType` enum and no InfiniTrain source file changes. This provider registers the backend
from `src/backend.cc` (`infini_train::backends::mlu::RegisterBackend`):

- `src/runtime/` - device guard, stream (CNRT queue), event (notifier), dispatch helpers;
- `src/kernels/*.mlu` - pure BANG C device code, compiled by `cncc`;
- `src/kernels/*.cc` - host-side integration (dispatch + `REGISTER_KERNEL`), compiled by the host compiler;
- `src/kernels/mlu_kernel_api.h` - the launcher interface between the two;
- `include/infini_train_mlu/backend.h` - the only public header: the registration entry point
used by examples and tools;
- `third_party/bang_host/` - two MIT-licensed Cambricon headers (`bang_fp16.h`, `bang_bf16.h`)
vendored for host compilation; see the README there for why and for the single local
modification.

## Requirements

| Item | Version used during development |
|---|---|
| Device | MLU590 (tested on MLU590-M9) |
| Driver | v6.5.52 |
| CNRT | 7.7.3 |
| cncc | 5.7.6 (clang 11.1 based) |
| Host compiler | GCC 13 (the framework needs C++20; GCC 11 lacks `<format>`) |
| CMake / Ninja | CMake >= 3.28, Ninja |
| InfiniTrain | the pinned submodule (`v0.7.0`) |

`CNNL` is optional at configure time: if `cnnl.h` / `libcnnl` are not found the build prints a
warning and disables BLAS handle support. **`INFINITRAIN_MLU_WITH_CNNL=ON` currently only
controls whether the CNNL handle is compiled in; no kernel calls CNNL yet** (GEMM still uses the
host fallback, see [`docs/validation.md`](docs/validation.md)).

## Build

```bash
git submodule update --init --recursive

# CMAKE_POLICY_VERSION_MINIMUM=3.5 is required with CMake 4.x (third_party/gflags in the
# framework declares an older minimum).
cmake -S . -B build-mlu -G Ninja \
-DINFINITRAIN_BACKEND=mlu -DUSE_CUDA=OFF -DBUILD_TEST=OFF \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
cmake --build build-mlu --target mlu_gpt2 mlu_op_test -j
```

Targets: `infini_train_mlu` (runtime + host kernel integration), `infini_train_mlu_kernels`
(BANG C objects), `mlu_gpt2` (upstream GPT-2 example with this backend registered, written as
`gpt2` in the build root) and `mlu_op_test` (operator regression tool, written as `op_test`).
`-DINFINITRAIN_MLU_BUILD_TEST_TOOLS=OFF` skips the regression tool;
`-DINFINITRAIN_BACKENDS_BUILD_EXAMPLES=OFF` skips the example.

`BUILD_TEST=ON` is rejected on purpose: this provider does not wire the shared InfiniTrain test
suites yet, and CPU test results must not stand in for MLU validation. Use the MLU regression
tools instead.

## Run

```bash
GLOG_logtostderr=1 OMP_NUM_THREADS=64 ./build-mlu/gpt2 \
--device mlu \
--input_bin <DATA>/tiny_shakespeare_train.bin \
--llmc_filepath <WEIGHTS>/gpt2_124M.bin \
--num_iteration 1
```

`GLOG_logtostderr=1` is required to see the step logs: glog otherwise writes them to
`/tmp/gpt2.*.INFO.*`.

The command above is the configuration under validation - **not** a verified 10-step run.

## Regression tools

```bash
./build-mlu/op_test # operator vs CPU comparison (device test)
./build-mlu/op_test --inject-finite # negative check: the comparator must fail
./build-mlu/op_test --debug-status-test failure # controlled fatal path (no device fault)
cd backends/mlu/tests/math_selftest && bash build_and_run.sh # device math functions (this cwd)
```

`tests/math_selftest` has no framework dependency: it compiles its own `.mlu` with `cncc` and
the host part with `g++`, so it runs outside the CMake build.

## Debug switches

| Variable | Effect |
|---|---|
| `MLU_DEBUG_SYNC=1` | synchronize the queue after every kernel launch and log its name; an SDK failure aborts the process |
| `MLU_DEBUG_CHECK=1` | copy back a sample of every kernel output and log dtype / sampled count / non-finite count / min / max |

Both parse `0`/`1`; unset or `0` disables them. They add synchronization and must be off for
any timing or acceptance run.
30 changes: 30 additions & 0 deletions backends/mlu/cmake/pre_project.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Cambricon MLU provider: settings that must be known before project().
#
# The host compiler stays whatever the user selected (the framework needs C++20,
# GCC 13 in the validated environment). BANG C device sources are compiled by
# cncc through a custom command in this provider's CMakeLists, so no compiler
# replacement happens here.

set(_MLU_DEFAULT_NEUWARE "$ENV{NEUWARE_HOME}")
if(NOT _MLU_DEFAULT_NEUWARE)
set(_MLU_DEFAULT_NEUWARE "/usr/local/neuware")
endif()
set(NEUWARE_HOME "${_MLU_DEFAULT_NEUWARE}" CACHE PATH
"Cambricon Neuware SDK root (CNRT, cncc and optional CNNL/CNCL)")
unset(_MLU_DEFAULT_NEUWARE)

if(NOT EXISTS "${NEUWARE_HOME}/bin/cncc")
message(FATAL_ERROR
"The BANG C compiler was not found at ${NEUWARE_HOME}/bin/cncc. "
"Set NEUWARE_HOME or pass -DNEUWARE_HOME=<sdk-root>.")
endif()
if(NOT EXISTS "${NEUWARE_HOME}/include/cnrt.h")
message(FATAL_ERROR
"CNRT headers were not found at ${NEUWARE_HOME}/include/cnrt.h.")
endif()

# The framework is built for its CPU backend; CUDA/NCCL belong to other
# providers and multi-card collectives are not implemented for MLU yet.
set(USE_CUDA OFF)
set(USE_NCCL OFF)
set(BUILD_SHARED_LIBS OFF)
Loading