Skip to content

Commit 76094ad

Browse files
authored
feat(hygon): add backend infrastructure (#31)
1 parent 2a2375a commit 76094ad

13 files changed

Lines changed: 487 additions & 10 deletions

File tree

.github/ci_config.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,41 @@ platforms:
149149
- name: test
150150
run: pytest tests/ --devices cambricon -n 4 -v --tb=short --junitxml=/workspace/results/test-results.xml
151151

152+
hygon:
153+
runner_label: Hygon
154+
execution_mode: agent_local
155+
image:
156+
dockerfile: images/hygon/
157+
build_args:
158+
BASE_IMAGE: image.sourcefind.cn:5000/dcu/admin/base/pytorch:2.4.1-ubuntu22.04-dtk25.04.1-py3.10
159+
APT_MIRROR: http://archive.ubuntu.com/ubuntu
160+
PIP_INDEX_URL: https://pypi.org/simple
161+
docker_args:
162+
- "--privileged"
163+
- "--network=host"
164+
- "--ipc=host"
165+
- "--device=/dev/kfd"
166+
- "--device=/dev/mkfd"
167+
- "--device=/dev/dri"
168+
- "--group-add=video"
169+
volumes:
170+
- /opt/hyhal:/opt/hyhal:ro
171+
setup: pip install .[dev] --no-build-isolation
172+
jobs:
173+
gpu:
174+
type: unittest
175+
resources:
176+
ngpus: 1
177+
gpu_style: none
178+
memory: 32GB
179+
shm_size: 64g
180+
timeout: 3600
181+
queue_timeout: 600
182+
junit_path: test-results.xml
183+
stages:
184+
- name: test
185+
run: pytest tests/ --devices hygon -n 4 -v --tb=short --junitxml=/workspace/results/test-results.xml
186+
152187
ascend:
153188
runner_label: Ascend
154189
execution_mode: agent_local

CMakeLists.txt

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(PYBIND11_ENABLE_EXTRAS ON)
1515
option(WITH_CPU "Enable CPU backend" OFF)
1616
option(WITH_NVIDIA "Enable CUDA backend" OFF)
1717
option(WITH_ILUVATAR "Enable Iluvatar GPU backend" OFF)
18+
option(WITH_HYGON "Enable Hygon GPU backend" OFF)
1819
option(WITH_METAX "Enable MetaX backend" OFF)
1920
option(WITH_CAMBRICON "Enable Cambricon backend" OFF)
2021
option(WITH_MOORE "Enable Moore backend" OFF)
@@ -33,6 +34,31 @@ option(AUTO_DETECT_DEVICES "Automatically detect available devices" OFF)
3334
option(AUTO_DETECT_BACKENDS "Automatically detect available backends" OFF)
3435
option(GENERATE_PYTHON_BINDINGS "Generate Python bindings" OFF)
3536

37+
set(_DEFAULT_HYGON_DTK_ROOT "/opt/dtk")
38+
39+
function(_infiniops_find_hygon_cuda_root out_var dtk_root)
40+
set(_candidates
41+
"${dtk_root}/cuda"
42+
"${dtk_root}/cuda/cuda"
43+
)
44+
45+
file(GLOB _versioned_cuda_dirs LIST_DIRECTORIES true "${dtk_root}/cuda/cuda-*")
46+
if(_versioned_cuda_dirs)
47+
list(SORT _versioned_cuda_dirs)
48+
list(REVERSE _versioned_cuda_dirs)
49+
list(APPEND _candidates ${_versioned_cuda_dirs})
50+
endif()
51+
52+
foreach(_candidate IN LISTS _candidates)
53+
if(EXISTS "${_candidate}/bin/nvcc")
54+
set(${out_var} "${_candidate}" PARENT_SCOPE)
55+
return()
56+
endif()
57+
endforeach()
58+
59+
set(${out_var} "" PARENT_SCOPE)
60+
endfunction()
61+
3662
if(AUTO_DETECT_DEVICES)
3763
message(STATUS "Auto-detecting available devices...")
3864

@@ -52,6 +78,24 @@ if(AUTO_DETECT_DEVICES)
5278
message(STATUS "Auto-detected Iluvatar environment.")
5379
endif()
5480

81+
set(_hygon_detected FALSE)
82+
if(DEFINED ENV{DTK_ROOT} AND NOT "$ENV{DTK_ROOT}" STREQUAL "")
83+
_infiniops_find_hygon_cuda_root(_HYGON_CUDA_DETECT_ROOT "$ENV{DTK_ROOT}")
84+
if(_HYGON_CUDA_DETECT_ROOT)
85+
set(_hygon_detected TRUE)
86+
endif()
87+
else()
88+
_infiniops_find_hygon_cuda_root(_HYGON_CUDA_DETECT_ROOT "${_DEFAULT_HYGON_DTK_ROOT}")
89+
if(_HYGON_CUDA_DETECT_ROOT)
90+
set(_hygon_detected TRUE)
91+
endif()
92+
endif()
93+
94+
if(_hygon_detected)
95+
set(WITH_HYGON ON)
96+
message(STATUS "Auto-detected Hygon environment.")
97+
endif()
98+
5599
if(DEFINED ENV{MACA_PATH})
56100
set(WITH_METAX ON)
57101
message(STATUS "Auto-detected MetaX environment from MACA_PATH")
@@ -176,6 +220,17 @@ if(WITH_TORCH)
176220
OUTPUT_STRIP_TRAILING_WHITESPACE
177221
)
178222

223+
execute_process(
224+
COMMAND ${Python_EXECUTABLE} -c "import pathlib, torch; p = pathlib.Path(torch.__file__).resolve().parent.parent / 'torch.libs'; print(str(p) if p.exists() else '')"
225+
OUTPUT_VARIABLE _torch_private_lib_dir
226+
OUTPUT_STRIP_TRAILING_WHITESPACE
227+
)
228+
229+
set(TORCH_RUNTIME_DIRS ${_torch_lib_dirs})
230+
if(_torch_private_lib_dir)
231+
list(APPEND TORCH_RUNTIME_DIRS ${_torch_private_lib_dir})
232+
endif()
233+
179234
find_library(TORCH_LIB torch HINTS ${_torch_lib_dirs} REQUIRED)
180235
find_library(TORCH_CPU_LIB torch_cpu HINTS ${_torch_lib_dirs} REQUIRED)
181236
find_library(C10_LIB c10 HINTS ${_torch_lib_dirs} REQUIRED)
@@ -225,14 +280,14 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
225280

226281
# Only one CUDA-like GPU backend can be enabled at a time.
227282
set(_gpu_backend_count 0)
228-
foreach(_gpu_backend WITH_NVIDIA WITH_ILUVATAR WITH_METAX WITH_MOORE WITH_ASCEND)
283+
foreach(_gpu_backend WITH_NVIDIA WITH_ILUVATAR WITH_HYGON WITH_METAX WITH_MOORE WITH_ASCEND)
229284
if(${_gpu_backend})
230285
math(EXPR _gpu_backend_count "${_gpu_backend_count} + 1")
231286
endif()
232287
endforeach()
233288

234289
if(_gpu_backend_count GREATER 1)
235-
message(FATAL_ERROR "`WITH_NVIDIA`, `WITH_ILUVATAR`, `WITH_METAX`, `WITH_MOORE`, and `WITH_ASCEND` are mutually exclusive. Build one GPU backend at a time.")
290+
message(FATAL_ERROR "`WITH_NVIDIA`, `WITH_ILUVATAR`, `WITH_HYGON`, `WITH_METAX`, `WITH_MOORE`, and `WITH_ASCEND` are mutually exclusive. Build one GPU backend at a time.")
236291
endif()
237292

238293
if(WITH_NVIDIA)
@@ -261,6 +316,70 @@ if(WITH_ILUVATAR)
261316
find_package(CUDAToolkit REQUIRED)
262317
endif()
263318

319+
if(WITH_HYGON)
320+
add_compile_definitions(WITH_HYGON=1)
321+
set(DTK_ROOT $ENV{DTK_ROOT})
322+
if(NOT DTK_ROOT)
323+
set(DTK_ROOT "${_DEFAULT_HYGON_DTK_ROOT}")
324+
endif()
325+
if(NOT EXISTS "${DTK_ROOT}")
326+
message(FATAL_ERROR "`WITH_HYGON` is `ON` but `DTK_ROOT` (`${DTK_ROOT}`) does not exist.")
327+
endif()
328+
329+
set(_HYGON_ARCH_DEFAULT "gfx906")
330+
if(DEFINED ENV{HYGON_ARCH} AND NOT "$ENV{HYGON_ARCH}" STREQUAL "")
331+
set(_HYGON_ARCH_DEFAULT "$ENV{HYGON_ARCH}")
332+
else()
333+
find_program(HYGON_ROCMINFO_EXECUTABLE NAMES rocminfo HINTS "${DTK_ROOT}/bin")
334+
if(HYGON_ROCMINFO_EXECUTABLE)
335+
execute_process(
336+
COMMAND ${HYGON_ROCMINFO_EXECUTABLE}
337+
OUTPUT_VARIABLE _HYGON_ROCMINFO_OUTPUT
338+
ERROR_QUIET
339+
OUTPUT_STRIP_TRAILING_WHITESPACE
340+
)
341+
string(REGEX MATCH "gfx[0-9]+" _HYGON_ARCH_AUTO "${_HYGON_ROCMINFO_OUTPUT}")
342+
if(_HYGON_ARCH_AUTO)
343+
set(_HYGON_ARCH_DEFAULT "${_HYGON_ARCH_AUTO}")
344+
endif()
345+
endif()
346+
endif()
347+
348+
set(HYGON_ARCH "${_HYGON_ARCH_DEFAULT}" CACHE STRING "Hygon GPU architecture")
349+
_infiniops_find_hygon_cuda_root(HYGON_CUDA_ROOT "${DTK_ROOT}")
350+
351+
if(NOT HYGON_CUDA_ROOT)
352+
message(FATAL_ERROR "`WITH_HYGON` is `ON` but no DTK `nvcc` was found under `${DTK_ROOT}`. Checked `${DTK_ROOT}/cuda/bin/nvcc`, `${DTK_ROOT}/cuda/cuda/bin/nvcc`, and `${DTK_ROOT}/cuda/cuda-*/bin/nvcc`.")
353+
endif()
354+
355+
set(CMAKE_CUDA_COMPILER "${HYGON_CUDA_ROOT}/bin/nvcc" CACHE FILEPATH "Hygon CUDA compiler (DTK nvcc)")
356+
set(CUDAToolkit_ROOT "${HYGON_CUDA_ROOT}" CACHE PATH "Hygon CUDA toolkit root")
357+
set(CMAKE_CUDA_ARCHITECTURES OFF CACHE STRING "Disable default CUDA arch flags for Hygon" FORCE)
358+
set(CMAKE_CUDA_FLAGS "-std=c++17 -fPIC -arch=${HYGON_ARCH} -Wno-return-type -Wno-error=unused-private-field" CACHE STRING "Hygon CUDA flags")
359+
set(CMAKE_CUDA_SEPARABLE_COMPILATION OFF CACHE BOOL "Disable RDC for Hygon")
360+
361+
# DTK's nvcc wrapper derives its toolkit root from `CUDA_PATH`.
362+
set(ENV{CUDA_PATH} "${HYGON_CUDA_ROOT}")
363+
set(ENV{CUDA_HOME} "${HYGON_CUDA_ROOT}")
364+
365+
# DTK's nvcc wrapper may invoke `nvcc` by name during compiler checks.
366+
set(ENV{PATH} "${HYGON_CUDA_ROOT}/bin:$ENV{PATH}")
367+
368+
# The actual Ninja build runs in fresh processes. Keep a launcher command
369+
# for CUDA-backed Python bindings that need the DTK wrapper environment.
370+
set(_HYGON_RULE_LAUNCH_ENV
371+
"${CMAKE_COMMAND} -E env CUDA_PATH=${HYGON_CUDA_ROOT} CUDA_HOME=${HYGON_CUDA_ROOT} PATH=${HYGON_CUDA_ROOT}/bin:$ENV{PATH}")
372+
373+
include_directories("${DTK_ROOT}/include")
374+
include_directories("${HYGON_CUDA_ROOT}/include")
375+
link_directories("${DTK_ROOT}/lib")
376+
link_directories("${HYGON_CUDA_ROOT}/lib64")
377+
378+
message(STATUS "Hygon: CUDA compiler ${CMAKE_CUDA_COMPILER}, arch ${HYGON_ARCH}, DTK root ${DTK_ROOT}")
379+
enable_language(CUDA)
380+
find_package(CUDAToolkit REQUIRED)
381+
endif()
382+
264383
if(WITH_METAX)
265384
add_compile_definitions(WITH_METAX=1)
266385

@@ -344,14 +463,18 @@ if(WITH_ASCEND)
344463
endif()
345464

346465
# If all other platforms are not enabled, CPU is enabled by default.
347-
if(NOT WITH_NVIDIA AND NOT WITH_ILUVATAR AND NOT WITH_METAX AND NOT WITH_MOORE AND NOT WITH_CAMBRICON AND NOT WITH_ASCEND)
466+
if(NOT WITH_NVIDIA AND NOT WITH_ILUVATAR AND NOT WITH_HYGON AND NOT WITH_METAX AND NOT WITH_MOORE AND NOT WITH_CAMBRICON AND NOT WITH_ASCEND)
348467
add_compile_definitions(WITH_CPU=1)
349468
endif()
350469

351470
if(WITH_TORCH OR WITH_METAX OR WITH_MOORE)
352471
set(PYBIND11_ENABLE_EXTRAS OFF)
353472
endif()
354473

474+
if(WITH_HYGON AND NOT EXISTS "${DTK_ROOT}/llvm/lib/LLVMgold.so")
475+
set(PYBIND11_ENABLE_EXTRAS OFF)
476+
endif()
477+
355478
add_subdirectory(src)
356479

357480
if(NOT GENERATE_PYTHON_BINDINGS)

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# InfiniOps
22

3-
InfiniOps is a high-performance, cross-platform operator library supporting multiple backends: CPU, Nvidia, MetaX, Iluvatar, Moore, Cambricon, and more.
3+
InfiniOps is a high-performance, cross-platform operator library supporting multiple backends: CPU, Nvidia, MetaX, Iluvatar, Hygon, Moore, Cambricon, and more.
44

55
## Prerequisites
66

@@ -31,12 +31,16 @@ pip install . -C cmake.define.WITH_CPU=ON -C cmake.define.WITH_NVIDIA=ON
3131
| `-DWITH_NVIDIA=[ON\|OFF]` | Compile the Nvidia implementation | OFF |
3232
| `-DWITH_METAX=[ON\|OFF]` | Compile the MetaX implementation | OFF |
3333
| `-DWITH_ILUVATAR=[ON\|OFF]` | Compile the Iluvatar implementation | OFF |
34+
| `-DWITH_HYGON=[ON\|OFF]` | Compile the Hygon implementation | OFF |
3435
| `-DWITH_MOORE=[ON\|OFF]` | Compile the Moore implementation | OFF |
3536
| `-DWITH_CAMBRICON=[ON\|OFF]` | Compile the Cambricon implementation | OFF |
37+
| `-DWITH_ASCEND=[ON\|OFF]` | Compile the Ascend implementation | OFF |
3638
| `-DAUTO_DETECT_DEVICES=[ON\|OFF]` | Auto-detect available platforms | ON |
3739

3840
If no accelerator options are provided and auto-detection finds nothing, `WITH_CPU` is enabled by default.
3941

42+
For Hygon builds, set `DTK_ROOT` to the DTK installation root if it is not installed at `/opt/dtk`. You can override the default DCU arch with `-DHYGON_ARCH=<arch>` when configuring CMake.
43+
4044
## Contributing
4145

4246
See [CONTRIBUTING.md](CONTRIBUTING.md) for code style, commit conventions, PR workflow, development guide, and troubleshooting.

examples/CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ foreach(source_file ${EXAMPLE_SOURCES})
99
target_link_libraries(${example_name} PRIVATE infiniops)
1010

1111
target_include_directories(${example_name} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
12-
12+
1313
get_filename_component(example_dir ${source_file} DIRECTORY)
1414

1515
target_include_directories(${example_name} PRIVATE ${example_dir})
16+
17+
if(WITH_TORCH)
18+
foreach(_torch_dir ${TORCH_RUNTIME_DIRS})
19+
target_link_options(${example_name} PRIVATE "LINKER:-rpath-link,${_torch_dir}")
20+
endforeach()
21+
endif()
1622
endforeach()

src/CMakeLists.txt

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,34 @@ if(WITH_ILUVATAR)
7070
list(APPEND DEVICE_LIST "iluvatar")
7171
endif()
7272

73+
if(WITH_HYGON)
74+
set(HYGON_PATTERNS
75+
"native/cuda/*.cc"
76+
"native/cuda/*.cpp"
77+
"native/cuda/*.cu"
78+
"native/cuda/hygon/*.cc"
79+
"native/cuda/hygon/*.cpp"
80+
"native/cuda/hygon/*.cu"
81+
)
82+
83+
file(GLOB_RECURSE HYGON_SOURCES CONFIGURE_DEPENDS ${HYGON_PATTERNS})
84+
85+
enable_language(CUDA)
86+
87+
target_compile_definitions(infiniops PUBLIC WITH_HYGON=1)
88+
target_sources(infiniops PRIVATE ${HYGON_SOURCES})
89+
90+
find_package(CUDAToolkit REQUIRED)
91+
target_link_libraries(infiniops PUBLIC CUDA::cudart CUDA::cublas)
92+
93+
set_target_properties(infiniops PROPERTIES
94+
CUDA_STANDARD 17
95+
CUDA_STANDARD_REQUIRED ON
96+
)
97+
98+
list(APPEND DEVICE_LIST "hygon")
99+
endif()
100+
73101
if(WITH_METAX)
74102
set(METAX_PATTERNS
75103
"native/cuda/*.cc"
@@ -517,7 +545,7 @@ if(GENERATE_PYTHON_BINDINGS)
517545
endif()
518546
list(APPEND PYBIND11_COMPILE_SOURCES ${PYBIND11_DISPATCH_SOURCES})
519547

520-
if(WITH_NVIDIA)
548+
if(WITH_NVIDIA OR WITH_HYGON)
521549
set_source_files_properties(${PYBIND11_COMPILE_SOURCES} PROPERTIES LANGUAGE CUDA)
522550
elseif(WITH_ILUVATAR)
523551
set(_iluvatar_dispatch_include_flags
@@ -607,6 +635,13 @@ if(GENERATE_PYTHON_BINDINGS)
607635
target_compile_options(ops PRIVATE "-x" "musa")
608636
endif()
609637

638+
if(WITH_HYGON)
639+
set_target_properties(ops PROPERTIES
640+
RULE_LAUNCH_COMPILE "${_HYGON_RULE_LAUNCH_ENV}"
641+
RULE_LAUNCH_LINK "${_HYGON_RULE_LAUNCH_ENV}"
642+
)
643+
endif()
644+
610645
target_include_directories(ops PRIVATE ${PROJECT_SOURCE_DIR})
611646
target_link_libraries(ops PRIVATE infiniops)
612647

@@ -620,9 +655,13 @@ if(GENERATE_PYTHON_BINDINGS)
620655
target_link_libraries(ops PRIVATE
621656
-Wl,--whole-archive no_workspace_kernel -Wl,--no-whole-archive)
622657
endif()
658+
set(_INFINIOPS_INSTALL_RPATH "$ORIGIN")
659+
if(WITH_TORCH)
660+
list(APPEND _INFINIOPS_INSTALL_RPATH ${TORCH_RUNTIME_DIRS})
661+
endif()
623662

624-
set_target_properties(infiniops PROPERTIES INSTALL_RPATH "$ORIGIN")
625-
set_target_properties(ops PROPERTIES INSTALL_RPATH "$ORIGIN")
663+
set_target_properties(infiniops PROPERTIES INSTALL_RPATH "${_INFINIOPS_INSTALL_RPATH}")
664+
set_target_properties(ops PROPERTIES INSTALL_RPATH "${_INFINIOPS_INSTALL_RPATH}")
626665

627666
install(TARGETS infiniops ops DESTINATION .)
628667

src/native/cuda/hygon/blas.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#ifndef INFINI_OPS_HYGON_BLAS_H_
2+
#define INFINI_OPS_HYGON_BLAS_H_
3+
4+
#include <utility>
5+
6+
// clang-format off
7+
#include "cublas_v2.h"
8+
// clang-format on
9+
10+
#include "data_type.h"
11+
#include "native/cuda/blas.h"
12+
#include "native/cuda/hygon/blas_utils.h"
13+
#include "native/cuda/hygon/runtime_.h"
14+
15+
namespace infini::ops {
16+
17+
template <>
18+
struct Blas<Device::Type::kHygon> : public Runtime<Device::Type::kHygon> {
19+
using BlasHandle = cublasHandle_t;
20+
21+
static constexpr auto BLAS_OP_N = CUBLAS_OP_N;
22+
23+
static constexpr auto BLAS_OP_T = CUBLAS_OP_T;
24+
25+
static constexpr auto BLAS_GEMM_DEFAULT = CUBLAS_GEMM_DEFAULT_TENSOR_OP;
26+
27+
static constexpr auto BlasCreate = cublasCreate;
28+
29+
static constexpr auto BlasSetStream = cublasSetStream;
30+
31+
static constexpr auto BlasDestroy = cublasDestroy;
32+
33+
static constexpr auto BlasGemmStridedBatchedEx = [](auto&&... args) {
34+
return cublasGemmStridedBatchedEx(std::forward<decltype(args)>(args)...);
35+
};
36+
};
37+
38+
} // namespace infini::ops
39+
40+
#endif

0 commit comments

Comments
 (0)