Skip to content
Merged
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
9 changes: 8 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,9 @@ if(WITH_METAX)
find_library(MACA_RUNTIME_LIB NAMES mcruntime HINTS "${MACA_PATH}/lib" REQUIRED)
endif()

if(WITH_MOORE)
if(WITH_MOORE)
include(cmake/architecture/MusaArchitecture.cmake)

set(MUSA_ROOT "")
foreach(_musa_env MUSA_ROOT MUSA_HOME MUSA_PATH)
if(NOT MUSA_ROOT AND DEFINED ENV{${_musa_env}} AND NOT "$ENV{${_musa_env}}" STREQUAL "")
Expand Down Expand Up @@ -397,6 +399,11 @@ if(WITH_MOORE)
find_library(MUSA_LIB NAMES musa HINTS "${MUSA_ROOT}/lib" REQUIRED)
find_library(MUSART_LIB NAMES musart HINTS "${MUSA_ROOT}/lib" REQUIRED)
find_library(MUBLAS_LIB NAMES mublas HINTS "${MUSA_ROOT}/lib" REQUIRED)

infiniccl_resolve_musa_architecture_config(
"${MUSA_ROOT}/include"
"${MUSART_LIB}"
)
endif()

if(WITH_CAMBRICON)
Expand Down
106 changes: 106 additions & 0 deletions cmake/architecture/MacroArchitecture.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
include_guard(GLOBAL)

# Normalize an architecture list into unique numeric architecture tokens.
# For example, with strip prefix `arch_`, `arch_31, 3.1;31` becomes `31`.
function(infiniccl_normalize_architectures input output strip_prefix description)
set(_architectures "${input}")
string(REPLACE "," ";" _architectures "${_architectures}")
string(REGEX REPLACE "[ \t\r\n]+" ";" _architectures "${_architectures}")

if("${description}" STREQUAL "")
set(_description "architecture")
else()
set(_description "${description}")
endif()

set(_normalized)
foreach(_architecture IN LISTS _architectures)
if(_architecture STREQUAL "")
continue()
endif()

set(_raw_architecture "${_architecture}")
if(NOT "${strip_prefix}" STREQUAL "")
string(REGEX REPLACE "^${strip_prefix}" "" _architecture "${_architecture}")
endif()
string(REPLACE "." "" _architecture "${_architecture}")

if(NOT _architecture MATCHES "^[0-9]+$")
if("${strip_prefix}" STREQUAL "")
set(_accepted_values "numeric values")
else()
set(_accepted_values "numeric values or `${strip_prefix}<value>`")
endif()
message(FATAL_ERROR
"Invalid ${_description} `${_raw_architecture}`. "
"Use ${_accepted_values}."
)
endif()

list(APPEND _normalized "${_architecture}")
endforeach()

list(REMOVE_DUPLICATES _normalized)
if(NOT _normalized)
message(FATAL_ERROR "At least one ${_description} is required.")
endif()

set(${output} "${_normalized}" PARENT_SCOPE)
endfunction()

# Compute one conservative SDK macro value from a normalized architecture list.
# This is for SDK headers that expose one macro-controlled API surface;
# the caller supplies the encoding scale, so `31;22` with scale `10` yields `220`.
function(infiniccl_compute_least_capable_architecture_macro architectures scale output)
if("${scale}" STREQUAL "")
message(FATAL_ERROR "Architecture macro scale is required.")
endif()

set(_macro_value)
foreach(_architecture IN LISTS architectures)
math(EXPR _architecture_macro_value "${_architecture} * ${scale}")
if(NOT _macro_value OR _architecture_macro_value LESS _macro_value)
set(_macro_value "${_architecture_macro_value}")
endif()
endforeach()

if(NOT _macro_value)
message(FATAL_ERROR "At least one architecture is required to compute a macro value.")
endif()

set(${output} "${_macro_value}" PARENT_SCOPE)
endfunction()

# Convert normalized architectures to compiler options using a vendor prefix,
# for example `31;22` plus `--arch=` yields `--arch=31` and `--arch=22`.
function(infiniccl_make_architecture_compile_options architectures option_prefix output)
set(_compile_options)
foreach(_architecture IN LISTS architectures)
list(APPEND _compile_options "${option_prefix}${_architecture}")
endforeach()

set(${output} "${_compile_options}" PARENT_SCOPE)
endfunction()

# Apply an SDK-visible architecture macro and matching compiler options to one
# target only, avoiding global CMake flags that can leak into other platforms.
function(infiniccl_configure_macro_architecture_target target macro_name macro_value compile_options)
if(NOT TARGET ${target})
message(FATAL_ERROR "Cannot configure unknown target `${target}`.")
endif()
if("${macro_name}" STREQUAL "")
message(FATAL_ERROR "Architecture macro name is required for target `${target}`.")
endif()
if("${macro_value}" STREQUAL "")
message(FATAL_ERROR "Architecture macro value is required for target `${target}`.")
endif()

foreach(_compile_option IN LISTS compile_options)
target_compile_options(${target} PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:${_compile_option}>
)
endforeach()
target_compile_definitions(${target} PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:${macro_name}=${macro_value}>
)
endfunction()
139 changes: 139 additions & 0 deletions cmake/architecture/MusaArchitecture.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
include_guard(GLOBAL)

include("${CMAKE_CURRENT_LIST_DIR}/MacroArchitecture.cmake")

# Normalize MUSA architecture spellings accepted from CMake cache, environment,
# or device probing; for example `mp_31`, `3.1`, and `31` all become `31`.
function(infiniccl_normalize_musa_architectures input output)
infiniccl_normalize_architectures(
"${input}"
_architectures
"mp_"
"MUSA architecture"
)
set(${output} "${_architectures}" PARENT_SCOPE)
endfunction()

# Convert MUSA architectures to the two settings needed by Moore MCCL: `mcc`
# device flags such as `--offload-arch=mp_31`, and the `MARCH_TYPE` macro used
# by `mccl.h` to expose architecture-dependent datatypes.
function(infiniccl_compute_musa_architecture_config input architectures_output march_type_output flags_output)
infiniccl_normalize_musa_architectures("${input}" _architectures)

# `mccl.h` exposes data types globally from one `MARCH_TYPE`. Use the least
# capable target so a fat binary never advertises a type that one of its
# target architectures cannot execute.
infiniccl_compute_least_capable_architecture_macro("${_architectures}" 10 _march_type)
infiniccl_make_architecture_compile_options("${_architectures}" "--offload-arch=mp_" _flags)

set(${architectures_output} "${_architectures}" PARENT_SCOPE)
set(${march_type_output} "${_march_type}" PARENT_SCOPE)
set(${flags_output} "${_flags}" PARENT_SCOPE)
endfunction()

# Resolve MUSA architecture settings in priority order: explicit
# `MUSA_ARCHITECTURES`, then `TORCH_MUSA_ARCH_LIST`, then installed GPU probing.
# The resolved values are exported for later target setup in `src` and examples.
function(infiniccl_resolve_musa_architecture_config musa_include_dir musart_library)
set(_musa_architectures_help
"MUSA GPU architectures (for example `31;22`); detected from installed GPUs when empty")
set(MUSA_ARCHITECTURES "" CACHE STRING "${_musa_architectures_help}")

set(_musa_architectures "${MUSA_ARCHITECTURES}")
if(NOT _musa_architectures
AND DEFINED ENV{TORCH_MUSA_ARCH_LIST}
AND NOT "$ENV{TORCH_MUSA_ARCH_LIST}" STREQUAL "")
set(_musa_architectures "$ENV{TORCH_MUSA_ARCH_LIST}")
message(STATUS "Using MUSA architectures from `TORCH_MUSA_ARCH_LIST`.")
endif()

if(NOT _musa_architectures)
infiniccl_detect_musa_architectures(
"${musa_include_dir}"
"${musart_library}"
_musa_architectures
)
message(STATUS "Auto-detected MUSA architectures from installed GPUs.")
endif()

infiniccl_compute_musa_architecture_config(
"${_musa_architectures}"
_normalized_musa_architectures
_musa_march_type
_musa_arch_compile_options
)

set(MUSA_ARCHITECTURES "${_normalized_musa_architectures}"
CACHE STRING "${_musa_architectures_help}" FORCE)
set(MUSA_ARCHITECTURES "${_normalized_musa_architectures}" PARENT_SCOPE)
set(MUSA_MARCH_TYPE "${_musa_march_type}" PARENT_SCOPE)
set(MUSA_ARCH_COMPILE_OPTIONS "${_musa_arch_compile_options}" PARENT_SCOPE)
message(STATUS
"MUSA architectures: ${_normalized_musa_architectures} (`MARCH_TYPE=${_musa_march_type}`)")
endfunction()

# Add MUSA architecture settings to a target after it has been created, so only
# Moore/MUSA sources see `MARCH_TYPE` and `--offload-arch`.
function(infiniccl_configure_musa_target target)
if(NOT TARGET ${target})
message(FATAL_ERROR "Cannot configure unknown MUSA target `${target}`.")
endif()

infiniccl_configure_macro_architecture_target(
${target}
MARCH_TYPE
"${MUSA_MARCH_TYPE}"
"${MUSA_ARCH_COMPILE_OPTIONS}"
)
endfunction()

# Build and run a tiny MUSA runtime probe to return installed GPU capabilities
# as values like `31`, matching `musaDeviceProp.major/minor`.
function(infiniccl_detect_musa_architectures musa_include_dir musart_library output)
set(_source "${CMAKE_CURRENT_BINARY_DIR}/get_musa_compute_capabilities.cpp")
file(WRITE "${_source}" [=[
#include <musa_runtime.h>

#include <cstdio>

int main() {
int device_count = 0;
if (musaGetDeviceCount(&device_count) != musaSuccess || device_count == 0) {
return 1;
}

for (int device = 0; device < device_count; ++device) {
musaDeviceProp properties;
if (musaGetDeviceProperties(&properties, device) != musaSuccess) {
return 1;
}
std::printf("%d%d ", properties.major, properties.minor);
}
return 0;
}
]=])

try_run(
_run_result
_compile_result
"${CMAKE_CURRENT_BINARY_DIR}"
"${_source}"
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${musa_include_dir}"
LINK_LIBRARIES "${musart_library}"
RUN_OUTPUT_VARIABLE _detected_architectures
)

if(NOT _compile_result OR NOT "${_run_result}" STREQUAL "0")
message(FATAL_ERROR
"Could not detect the architecture of the installed MUSA GPUs. "
"Set `MUSA_ARCHITECTURES` explicitly, for example "
"`-DMUSA_ARCHITECTURES=31`."
)
endif()

infiniccl_normalize_musa_architectures(
"${_detected_architectures}"
_detected_architectures
)
set(${output} "${_detected_architectures}" PARENT_SCOPE)
endfunction()
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ foreach(source_file ${EXAMPLE_SOURCES})
if(WITH_MOORE)
target_link_libraries(${target_name} PRIVATE ${MUSART_LIB})
target_compile_options(${target_name} PRIVATE "-x" "musa")
infiniccl_configure_musa_target(${target_name})
endif()

if(WITH_CAMBRICON)
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ if(WITH_MOORE)
target_include_directories(infiniccl PRIVATE "${MUSA_ROOT}/include")
target_link_libraries(infiniccl PRIVATE ${MUSA_LIB} ${MUSART_LIB} ${MUBLAS_LIB})
target_compile_options(infiniccl PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-x musa>)
infiniccl_configure_musa_target(infiniccl)
endif()

# Cambricon
Expand Down
Loading