diff --git a/CMakeLists.txt b/CMakeLists.txt index f052c92..6ce48b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,38 +33,21 @@ option(AUTO_DETECT_DEVICES "Automatically detect available devices" ON) option(AUTO_DETECT_BACKENDS "Automatically detect available backends" OFF) option(BUILD_EXAMPLES "Build internal examples" ON) -function(_collect_thead_hints out_var) - if(NOT DEFINED _THEAD_HINTS_MEMO) - set(_hints - /usr/local/PPU_SDK - /usr/local/PPU_SDK/CUDA_SDK - ) - - foreach(_env IN ITEMS PPU_SDK PPU_HOME PPU_PATH) - if(DEFINED ENV{${_env}} AND NOT "$ENV{${_env}}" STREQUAL "") - list(APPEND _hints - "$ENV{${_env}}" - "$ENV{${_env}}/CUDA_SDK" - ) - endif() - endforeach() - - foreach(_env IN ITEMS CUDA_SDK CUDA_HOME CUDA_PATH CUDA_TOOLKIT_ROOT) - if(DEFINED ENV{${_env}} AND NOT "$ENV{${_env}}" STREQUAL "") - list(APPEND _hints - "$ENV{${_env}}" - "$ENV{${_env}}/.." - ) - endif() - endforeach() - - list(REMOVE_DUPLICATES _hints) - set(_THEAD_HINTS_MEMO "${_hints}") - set(_THEAD_HINTS_MEMO "${_hints}" PARENT_SCOPE) - endif() - - set(${out_var} "${_THEAD_HINTS_MEMO}" PARENT_SCOPE) -endfunction() +# Device modules provide platform probes and SDK configuration helpers. +include(cmake/devices/DeviceDetection.cmake) +include(cmake/devices/Nvidia.cmake) +include(cmake/devices/Iluvatar.cmake) +include(cmake/devices/MetaX.cmake) +include(cmake/devices/Moore.cmake) +include(cmake/devices/Cambricon.cmake) +include(cmake/devices/Hygon.cmake) +include(cmake/devices/THead.cmake) + +# Backend modules provide backend probes and required dependency resolution. +include(cmake/backends/MPI.cmake) +include(cmake/backends/NCCL.cmake) +include(cmake/backends/MCCL.cmake) +include(cmake/backends/CNCL.cmake) # ========================================================= # --- AUTO-DETECTION: DEVICES --- @@ -74,229 +57,39 @@ if(AUTO_DETECT_DEVICES) # NVIDIA set(NVIDIA_REQUESTED ${WITH_NVIDIA}) - set(NVIDIA_FOUND FALSE) - - file(GLOB NVIDIA_DEV_FILES "/dev/nvidia0") - - if(NVIDIA_DEV_FILES) - set(NVIDIA_FOUND TRUE) - elseif(NOT NVIDIA_FOUND) - find_program(NVIDIA_SMI_PATH nvidia-smi) - if(NVIDIA_SMI_PATH) - execute_process( - COMMAND ${NVIDIA_SMI_PATH} -L - RESULT_VARIABLE SMI_RESULT - OUTPUT_QUIET - ERROR_QUIET - ) - if(SMI_RESULT EQUAL 0) - set(NVIDIA_FOUND TRUE) - endif() - endif() - endif() + infiniccl_resolve_device_detection( + WITH_NVIDIA "NVIDIA" infiniccl_detect_nvidia NVIDIA_FOUND) # Iluvatar - set(ILUVATAR_FOUND FALSE) - - file(GLOB ILUVATAR_DEV_FILES "/dev/iluvatar*") - - if(ILUVATAR_DEV_FILES) - set(ILUVATAR_FOUND TRUE) - elseif(NOT ILUVATAR_FOUND) - find_program(ILUVATAR_SMI_PATH ixsmi) - if(ILUVATAR_SMI_PATH) - execute_process( - COMMAND ${ILUVATAR_SMI_PATH} -L - RESULT_VARIABLE SMI_RESULT - OUTPUT_QUIET - ERROR_QUIET - ) - if(SMI_RESULT EQUAL 0) - set(ILUVATAR_FOUND TRUE) - endif() - endif() - endif() - - if(ILUVATAR_FOUND) - set(WITH_ILUVATAR ON) - message(STATUS "Auto-detected Iluvatar environment.") - else() - message(STATUS "Iluvatar environment not detected.") - endif() + infiniccl_resolve_device_detection( + WITH_ILUVATAR "Iluvatar" infiniccl_detect_iluvatar ILUVATAR_FOUND) # MetaX - if(DEFINED ENV{MACA_PATH}) - set(WITH_METAX ON) - message(STATUS "Auto-detected MetaX environment from `MACA_PATH`") - else() - execute_process( - COMMAND sh -c "grep -h 9999 /sys/bus/pci/devices/*/vendor 2>/dev/null" - OUTPUT_VARIABLE _pci_vendor_output - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - string(FIND "${_pci_vendor_output}" "9999" _found_pos) - - if(_found_pos GREATER -1) - set(WITH_METAX ON) - message(STATUS "Detected MetaX GPU from PCI vendor ID 0x9999") - else() - set(WITH_METAX OFF) - message(STATUS "No MetaX GPU detected") - endif() - endif() + infiniccl_resolve_device_detection( + WITH_METAX "MetaX" infiniccl_detect_metax METAX_FOUND) # MThreads (Moore) - set(MOORE_FOUND FALSE) - - file(GLOB MOORE_DEV_FILES "/dev/mtgpu*") - - if(DEFINED ENV{MUSA_ROOT} OR DEFINED ENV{MUSA_HOME} OR DEFINED ENV{MUSA_PATH}) - set(MOORE_FOUND TRUE) - elseif(MOORE_DEV_FILES) - set(MOORE_FOUND TRUE) - elseif(NOT MOORE_FOUND) - find_program(MOORE_SMI_PATH mthreads-gmi) - - if(MOORE_SMI_PATH) - execute_process( - COMMAND ${MOORE_SMI_PATH} -L - RESULT_VARIABLE SMI_RESULT - OUTPUT_QUIET - ERROR_QUIET - ) - if(SMI_RESULT EQUAL 0) - set(MOORE_FOUND TRUE) - endif() - endif() - endif() - - if(MOORE_FOUND) - set(WITH_MOORE ON) - message(STATUS "Auto-detected Moore environment.") - else() - message(STATUS "Moore environment not detected.") - endif() + infiniccl_resolve_device_detection( + WITH_MOORE "Moore" infiniccl_detect_moore MOORE_FOUND) # Cambricon - set(CAMBRICON_FOUND FALSE) - - if(DEFINED ENV{NEUWARE_HOME}) - set(CAMBRICON_FOUND TRUE) - message(STATUS "Auto-detected Cambricon environment from `NEUWARE_HOME`") - else() - find_program(CNMON_PATH cnmon) - if(CNMON_PATH) - execute_process( - COMMAND ${CNMON_PATH} -l - RESULT_VARIABLE CNMON_RESULT - OUTPUT_QUIET - ERROR_QUIET - ) - if(CNMON_RESULT EQUAL 0) - set(CAMBRICON_FOUND TRUE) - endif() - endif() - endif() + infiniccl_resolve_device_detection( + WITH_CAMBRICON "Cambricon" infiniccl_detect_cambricon CAMBRICON_FOUND) - if(CAMBRICON_FOUND) - set(WITH_CAMBRICON ON) - message(STATUS "Cambricon environment detected.") - else() - set(WITH_CAMBRICON OFF) - message(STATUS "Cambricon environment not detected.") - endif() - - # Hygon DCU - if(NOT WITH_HYGON) - set(HYGON_FOUND FALSE) - - if((DEFINED ENV{DTKROOT} OR DEFINED ENV{DTK_ROOT} OR DEFINED ENV{ROCM_PATH}) - AND EXISTS "/dev/kfd") - set(HYGON_FOUND TRUE) - elseif(EXISTS "/opt/dtk" AND EXISTS "/dev/kfd") - set(HYGON_FOUND TRUE) - else() - find_program(HYGON_SMI_PATH - NAMES hy-smi rocm-smi - HINTS /opt/hyhal/bin /opt/dtk/bin - ) - if(HYGON_SMI_PATH) - execute_process( - COMMAND ${HYGON_SMI_PATH} - RESULT_VARIABLE SMI_RESULT - OUTPUT_QUIET - ERROR_QUIET - ) - if(SMI_RESULT EQUAL 0) - set(HYGON_FOUND TRUE) - endif() - endif() - endif() - - if(HYGON_FOUND) - set(WITH_HYGON ON) - endif() - endif() - - if(WITH_HYGON) - message(STATUS "Hygon environment detected.") - else() - message(STATUS "Hygon environment not detected.") - endif() + # HYGON + infiniccl_resolve_device_detection( + WITH_HYGON "Hygon" infiniccl_detect_hygon HYGON_FOUND) # T-Head - set(THEAD_FOUND FALSE) - - if(WITH_THEAD) - set(THEAD_FOUND TRUE) - else() - _collect_thead_hints(_THEAD_HINTS) - foreach(_thead_hint IN LISTS _THEAD_HINTS) - if(EXISTS "${_thead_hint}/CUDA_SDK" OR EXISTS "${_thead_hint}/bin/ppu-smi" OR EXISTS "${_thead_hint}/ppu-smi/bin/ppu-smi") - set(THEAD_FOUND TRUE) - endif() - endforeach() - - if(NOT THEAD_FOUND) - find_program(THEAD_SMI_PATH - NAMES ppu-smi nvidia-smi - HINTS /usr/local/PPU_SDK/bin /usr/local/PPU_SDK/ppu-smi/bin - ) - if(THEAD_SMI_PATH) - execute_process( - COMMAND ${THEAD_SMI_PATH} -L - RESULT_VARIABLE SMI_RESULT - OUTPUT_VARIABLE SMI_OUTPUT - ERROR_QUIET - ) - if(SMI_RESULT EQUAL 0 AND SMI_OUTPUT MATCHES "PPU") - set(THEAD_FOUND TRUE) - endif() - endif() - endif() - endif() - - if(THEAD_FOUND) - set(WITH_THEAD ON) - message(STATUS "Auto-detected T-Head environment.") - else() - message(STATUS "T-Head environment not detected.") - endif() + infiniccl_resolve_device_detection( + WITH_THEAD "T-Head" infiniccl_detect_thead THEAD_FOUND) + # NVIDIA Final Resolution: resolve conflicts. if(THEAD_FOUND AND NVIDIA_FOUND AND NOT NVIDIA_REQUESTED) set(NVIDIA_FOUND FALSE) set(WITH_NVIDIA OFF CACHE BOOL "Enable NVIDIA GPU support" FORCE) message(STATUS "T-Head environment detected; ignoring NVIDIA auto-detection.") endif() - - if(NVIDIA_FOUND) - set(WITH_NVIDIA ON) - message(STATUS "Auto-detected NVIDIA environment.") - else() - message(STATUS "NVIDIA environment not detected.") - endif() - endif() # ========================================================= @@ -306,78 +99,19 @@ if(AUTO_DETECT_BACKENDS) message(STATUS "Auto-detecting available communication backends...") # Detect MPI Dependencies - find_program(MPIRUN_PATH NAMES mpirun mpiexec) - find_program(MPICC_PATH NAMES mpicc) - - if(MPIRUN_PATH AND MPICC_PATH) - # Query the active `mpirun` variant. - execute_process( - COMMAND ${MPIRUN_PATH} --version - OUTPUT_VARIABLE MPI_VERSION_OUT - ERROR_VARIABLE MPI_VERSION_ERR - ) - set(MPI_VERSION_INFO "${MPI_VERSION_OUT}${MPI_VERSION_ERR}") - - if(MPI_VERSION_INFO MATCHES "Open MPI" OR MPI_VERSION_INFO MATCHES "PRRTE") - set(WITH_OMPI ON) - message(STATUS "Auto-detected OpenMPI environment.") - elseif(MPI_VERSION_INFO MATCHES "MPICH" OR MPI_VERSION_INFO MATCHES "Hydra" OR MPI_VERSION_INFO MATCHES "Intel\\(R\\) MPI") - set(WITH_MPICH ON) - message(STATUS "Auto-detected MPICH/Hydra environment.") - else() - # Fallback to OMPI if it's an unrecognized wrapper. - set(WITH_OMPI ON) - message(STATUS "Unknown MPI implementation. Defaulting to `WITH_OMPI=ON`") - endif() + infiniccl_detect_mpi(MPI_IMPLEMENTATION) + if(MPI_IMPLEMENTATION STREQUAL "OMPI") + set(WITH_OMPI ON) + message(STATUS "Auto-detected OpenMPI environment.") + elseif(MPI_IMPLEMENTATION STREQUAL "MPICH") + set(WITH_MPICH ON) + message(STATUS "Auto-detected MPICH/Hydra environment.") endif() # Detect NCCL Dependencies if(WITH_NVIDIA OR WITH_THEAD OR WITH_ILUVATAR OR WITH_HYGON) - set(_NCCL_HINTS) - set(_NCCL_HEADER_NAMES nccl.h) - set(_NCCL_LIBRARY_NAMES nccl) - set(_NCCL_INCLUDE_SUFFIXES include) - set(_NCCL_LIBRARY_SUFFIXES lib lib64) - - if(WITH_THEAD) - _collect_thead_hints(_THEAD_HINTS) - set(_NCCL_HINTS ${_THEAD_HINTS}) - list(APPEND _NCCL_INCLUDE_SUFFIXES targets/x86_64-linux/include) - list(APPEND _NCCL_LIBRARY_SUFFIXES targets/x86_64-linux/lib) - list(REMOVE_DUPLICATES _NCCL_HINTS) - message(STATUS "T-Head detected. Searching for NCCL in ${_NCCL_HINTS}") - elseif(WITH_ILUVATAR) - set(_NCCL_HINTS /usr/local/corex) - message(STATUS "Iluvatar detected. Searching for NCCL in ${_NCCL_HINTS}") - elseif(WITH_HYGON) - foreach(_hygon_nccl_env DTKROOT DTK_ROOT ROCM_PATH) - if(DEFINED ENV{${_hygon_nccl_env}} AND NOT "$ENV{${_hygon_nccl_env}}" STREQUAL "") - list(APPEND _NCCL_HINTS "$ENV{${_hygon_nccl_env}}") - endif() - endforeach() - - if(DEFINED ENV{HIP_PATH} AND NOT "$ENV{HIP_PATH}" STREQUAL "") - get_filename_component(_HYGON_NCCL_ROOT_FROM_HIP "$ENV{HIP_PATH}/.." ABSOLUTE) - list(APPEND _NCCL_HINTS "${_HYGON_NCCL_ROOT_FROM_HIP}") - endif() - - list(APPEND _NCCL_HINTS /opt/dtk /opt/dtk/rccl) - set(_NCCL_HEADER_NAMES rccl/rccl.h rccl.h) - set(_NCCL_LIBRARY_NAMES rccl) - list(APPEND _NCCL_LIBRARY_SUFFIXES rccl/lib) - message(STATUS "Hygon detected. Searching for NCCL-compatible RCCL in ${_NCCL_HINTS}") - endif() - - find_path(AUTO_NCCL_INC NAMES ${_NCCL_HEADER_NAMES} - HINTS ${_NCCL_HINTS} - PATH_SUFFIXES ${_NCCL_INCLUDE_SUFFIXES} - QUIET) - find_library(AUTO_NCCL_LIB NAMES ${_NCCL_LIBRARY_NAMES} - HINTS ${_NCCL_HINTS} - PATH_SUFFIXES ${_NCCL_LIBRARY_SUFFIXES} - QUIET) - - if(AUTO_NCCL_INC AND AUTO_NCCL_LIB) + infiniccl_probe_nccl(NCCL_FOUND) + if(NCCL_FOUND) set(WITH_NCCL ON) message(STATUS "Auto-detected NCCL backend.") else() @@ -388,39 +122,13 @@ if(AUTO_DETECT_BACKENDS) endif() # Detect MCCL Dependencies - if(WITH_METAX) - set(_MCCL_HINTS) - if(DEFINED ENV{MACA_PATH}) - list(APPEND _MCCL_HINTS "$ENV{MACA_PATH}") - endif() - list(APPEND _MCCL_HINTS /opt/maca) - - find_path(AUTO_MCCL_INC NAMES mccl.h HINTS ${_MCCL_HINTS} PATH_SUFFIXES include QUIET) - find_library(AUTO_MCCL_LIB NAMES mccl HINTS ${_MCCL_HINTS} PATH_SUFFIXES lib lib64 QUIET) - - if(AUTO_MCCL_INC AND AUTO_MCCL_LIB) + if(WITH_METAX OR WITH_MOORE) + infiniccl_probe_mccl(MCCL_FOUND) + if(MCCL_FOUND) set(WITH_MCCL ON) message(STATUS "Auto-detected MCCL backend.") else() - message(STATUS "MCCL library/headers not found in MetaX paths.") - endif() - elseif(WITH_MOORE) - set(_MCCL_HINTS) - foreach(_musa_env MUSA_ROOT MUSA_HOME MUSA_PATH) - if(DEFINED ENV{${_musa_env}} AND NOT "$ENV{${_musa_env}}" STREQUAL "") - list(APPEND _MCCL_HINTS "$ENV{${_musa_env}}") - endif() - endforeach() - list(APPEND _MCCL_HINTS /usr/local/musa) - - find_path(AUTO_MCCL_INC NAMES mccl.h HINTS ${_MCCL_HINTS} PATH_SUFFIXES include QUIET) - find_library(AUTO_MCCL_LIB NAMES mccl HINTS ${_MCCL_HINTS} PATH_SUFFIXES lib lib64 QUIET) - - if(AUTO_MCCL_INC AND AUTO_MCCL_LIB) - set(WITH_MCCL ON) - message(STATUS "Auto-detected MCCL backend.") - else() - message(STATUS "MCCL library/headers not found in Moore paths.") + message(STATUS "MCCL library/headers not found in configured paths.") endif() else() message(STATUS "No suitable device environment, skipping MCCL detection.") @@ -428,10 +136,8 @@ if(AUTO_DETECT_BACKENDS) # 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) + infiniccl_probe_cncl(CNCL_FOUND) + if(CNCL_FOUND) set(WITH_CNCL ON) message(STATUS "Auto-detected CNCL backend.") else() @@ -450,25 +156,9 @@ endif() # --- DEPENDENCY DISCOVERY --- # ========================================================= if(WITH_THEAD) - _collect_thead_hints(_THEAD_CUDA_HINTS) - list(APPEND _THEAD_CUDA_HINTS /usr/local/cuda) - list(REMOVE_DUPLICATES _THEAD_CUDA_HINTS) - - set(THEAD_CUDA_ROOT "") - foreach(_thead_cuda_hint ${_THEAD_CUDA_HINTS}) - if(NOT THEAD_CUDA_ROOT AND EXISTS "${_thead_cuda_hint}/include/cuda_runtime.h") - set(THEAD_CUDA_ROOT "${_thead_cuda_hint}") - endif() - endforeach() - - if(NOT THEAD_CUDA_ROOT) - message(FATAL_ERROR "`WITH_THEAD` is `ON` but the T-Head CUDA-compatible SDK was not found. Set `PPU_SDK`, `PPU_HOME`, `CUDA_SDK`, `CUDA_HOME`, or `CUDA_PATH`.") - endif() - - set(CUDAToolkit_ROOT "${THEAD_CUDA_ROOT}" CACHE PATH "T-Head CUDA-compatible toolkit root" FORCE) - list(APPEND _NCCL_HINTS ${_THEAD_CUDA_HINTS}) - list(REMOVE_DUPLICATES _NCCL_HINTS) - + infiniccl_resolve_thead_cuda(THEAD_CUDA_ROOT _THEAD_CUDA_HINTS) + set(CUDAToolkit_ROOT "${THEAD_CUDA_ROOT}" + CACHE PATH "T-Head CUDA-compatible toolkit root" FORCE) enable_language(CUDA) find_package(CUDAToolkit REQUIRED) endif() @@ -479,145 +169,26 @@ if(WITH_NVIDIA) endif() if(WITH_ILUVATAR) - find_program(ILUVATAR_CUDA_COMPILER NAMES clang++ HINTS /usr/local/corex/bin) - - if(NOT ILUVATAR_CUDA_COMPILER) - message(FATAL_ERROR "`WITH_ILUVATAR` is `ON` but CoreX `clang++` was not found.") - endif() - - get_filename_component(ILUVATAR_CUDA_BIN_DIR "${ILUVATAR_CUDA_COMPILER}" DIRECTORY) - get_filename_component(ILUVATAR_CUDA_ROOT "${ILUVATAR_CUDA_BIN_DIR}/.." ABSOLUTE) - - set(CUDAToolkit_ROOT "${ILUVATAR_CUDA_ROOT}" CACHE PATH "Iluvatar CoreX toolkit root" FORCE) - find_package(CUDAToolkit REQUIRED) - - set(ILUVATAR_INCLUDE_DIR "${ILUVATAR_CUDA_ROOT}/include") - set(ILUVATAR_LIB_DIR "${ILUVATAR_CUDA_ROOT}/lib" "${ILUVATAR_CUDA_ROOT}/lib64") - - set(ILUVATAR_CUDA_FLAGS - "-fPIC;-Wno-error=unused-variable;-Wno-error=unused-private-field;-Wno-unused-variable;-std=c++17;--cuda-path=${ILUVATAR_CUDA_ROOT};-x;ivcore" - CACHE STRING "Iluvatar CUDA compiler flags") - - message(STATUS "Iluvatar: CUDA compiler ${ILUVATAR_CUDA_COMPILER}, arch ${ILUVATAR_ARCH}, toolkit ${ILUVATAR_CUDA_ROOT}") + infiniccl_configure_iluvatar() + message(STATUS + "Iluvatar: CUDA compiler ${ILUVATAR_CUDA_COMPILER}, " + "arch ${ILUVATAR_ARCH}, toolkit ${ILUVATAR_CUDA_ROOT}") endif() if(WITH_METAX) - set(MACA_PATH $ENV{MACA_PATH}) - if(NOT MACA_PATH) - # Normally can be found at: `/opt/maca/`. - set(MACA_PATH "/opt/maca") - message(WARNING "MACA_PATH environment variable not set. Defaulting to /opt/maca/. Please verify this path is correct.") - endif() - - get_filename_component(MXCC_WRAPPER_ABS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/devices/mxcc_wrapper.sh" ABSOLUTE) - - set(CMAKE_C_COMPILER "${MXCC_WRAPPER_ABS}") - set(CMAKE_CXX_COMPILER "${MXCC_WRAPPER_ABS}") - - include_directories("${MACA_PATH}/include") - link_directories("${MACA_PATH}/lib") - - find_library(MACA_RUNTIME_LIB NAMES mcruntime HINTS "${MACA_PATH}/lib" REQUIRED) + infiniccl_configure_metax() endif() 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 "") - set(MUSA_ROOT "$ENV{${_musa_env}}") - endif() - endforeach() - - if(NOT MUSA_ROOT AND EXISTS "/usr/local/musa") - set(MUSA_ROOT "/usr/local/musa") - endif() - - if(NOT MUSA_ROOT) - message(FATAL_ERROR "`WITH_MOORE` is `ON` but `MUSA_ROOT`/`MUSA_HOME`/`MUSA_PATH` is not set and `/usr/local/musa` was not found.") - endif() - - if(NOT EXISTS "${MUSA_ROOT}/bin/mcc") - message(FATAL_ERROR "Could not find `mcc` under `${MUSA_ROOT}/bin`.") - endif() - - get_filename_component(MCC_WRAPPER_ABS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/devices/mcc_wrapper.sh" ABSOLUTE) - file(CHMOD "${MCC_WRAPPER_ABS}" - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - set(CMAKE_C_COMPILER "${MCC_WRAPPER_ABS}") - set(CMAKE_CXX_COMPILER "${MCC_WRAPPER_ABS}") - - include_directories("${MUSA_ROOT}/include") - link_directories("${MUSA_ROOT}/lib") - - 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}" - ) + infiniccl_configure_moore() endif() if(WITH_CAMBRICON) - set(NEUWARE_HOME $ENV{NEUWARE_HOME}) - - include_directories("${NEUWARE_HOME}/include") - link_directories("${NEUWARE_HOME}/lib") - link_directories("${NEUWARE_HOME}/lib64") - - # Libraries: `cnrt` / `cnnl` / `cnnl_extra` / `cnpapi`. - find_library(CAMBRICON_RUNTIME_LIB NAMES cnrt HINTS "${NEUWARE_HOME}/lib64" REQUIRED) - find_library(CAMBRICON_CNNL_LIB NAMES cnnl HINTS "${NEUWARE_HOME}/lib64" REQUIRED) - find_library(CAMBRICON_CNNL_EXTRA_LIB NAMES cnnl_extra HINTS "${NEUWARE_HOME}/lib64" REQUIRED) - find_library(CAMBRICON_PAPI_LIB NAMES cnpapi HINTS "${NEUWARE_HOME}/lib64" REQUIRED) + infiniccl_configure_cambricon() endif() if(WITH_HYGON) - set(HYGON_DTK_ROOT "") - foreach(_hygon_env DTKROOT DTK_ROOT ROCM_PATH) - if(NOT HYGON_DTK_ROOT AND DEFINED ENV{${_hygon_env}} AND NOT "$ENV{${_hygon_env}}" STREQUAL "") - set(HYGON_DTK_ROOT "$ENV{${_hygon_env}}") - endif() - endforeach() - - if(NOT HYGON_DTK_ROOT AND DEFINED ENV{HIP_PATH} AND NOT "$ENV{HIP_PATH}" STREQUAL "") - get_filename_component(HYGON_DTK_ROOT "$ENV{HIP_PATH}/.." ABSOLUTE) - endif() - - if(NOT HYGON_DTK_ROOT AND EXISTS "/opt/dtk") - set(HYGON_DTK_ROOT "/opt/dtk") - endif() - - if(NOT HYGON_DTK_ROOT) - message(FATAL_ERROR "`WITH_HYGON` is `ON` but DTK was not found. Set `DTKROOT`, `DTK_ROOT`, `ROCM_PATH`, or `HIP_PATH`.") - endif() - - set(HYGON_HIP_HINTS "${HYGON_DTK_ROOT}" "${HYGON_DTK_ROOT}/hip") - find_path(HYGON_HIP_INCLUDE_DIR - NAMES hip/hip_runtime.h - HINTS ${HYGON_HIP_HINTS} - PATH_SUFFIXES include hip/include - REQUIRED - ) - find_library(HYGON_HIP_RUNTIME_LIB - NAMES amdhip64 - HINTS ${HYGON_HIP_HINTS} - PATH_SUFFIXES lib lib64 hip/lib - REQUIRED - ) - find_program(HYGON_HIPCC_COMPILER - NAMES hipcc - HINTS ${HYGON_HIP_HINTS} - PATH_SUFFIXES bin hip/bin - REQUIRED - ) - - set(CMAKE_CXX_COMPILER "${HYGON_HIPCC_COMPILER}" CACHE FILEPATH "Hygon DTK hipcc compiler" FORCE) - set(HYGON_HIP_DEFINITIONS __HIP_PLATFORM_AMD__) - include_directories(${HYGON_HIP_INCLUDE_DIR}) + infiniccl_configure_hygon() endif() if(WITH_OMPI OR WITH_MPICH) @@ -625,73 +196,17 @@ if(WITH_OMPI OR WITH_MPICH) endif() if(WITH_NCCL) - if (NOT WITH_NVIDIA AND NOT WITH_THEAD AND NOT WITH_ILUVATAR AND NOT WITH_HYGON) - message(FATAL_ERROR "NCCL backend requires NVIDIA, T-Head, Iluvatar, or Hygon GPU support. Please enable `WITH_NVIDIA`, `WITH_THEAD`, `WITH_ILUVATAR`, or `WITH_HYGON`.") - endif() - - set(_NCCL_HEADER_NAMES nccl.h) - set(_NCCL_LIBRARY_NAMES nccl) - set(NCCL_COMPILE_DEFINITIONS) - set(_NCCL_INCLUDE_SUFFIXES include) - set(_NCCL_LIBRARY_SUFFIXES lib lib64) - - if(WITH_THEAD) - set(_NCCL_HINTS ${_THEAD_CUDA_HINTS}) - list(APPEND _NCCL_INCLUDE_SUFFIXES targets/x86_64-linux/include) - list(APPEND _NCCL_LIBRARY_SUFFIXES targets/x86_64-linux/lib) - elseif(WITH_HYGON) - list(APPEND _NCCL_HINTS "${HYGON_DTK_ROOT}" "${HYGON_DTK_ROOT}/rccl") - set(_NCCL_HEADER_NAMES rccl/rccl.h rccl.h) - set(_NCCL_LIBRARY_NAMES rccl) - set(NCCL_COMPILE_DEFINITIONS INFINI_CCL_USE_RCCL) - list(APPEND _NCCL_LIBRARY_SUFFIXES rccl/lib) - endif() - - list(REMOVE_DUPLICATES _NCCL_HINTS) - find_library(NCCL_LIB NAMES ${_NCCL_LIBRARY_NAMES} - HINTS ${_NCCL_HINTS} - PATH_SUFFIXES ${_NCCL_LIBRARY_SUFFIXES} - REQUIRED) - find_path(NCCL_INC NAMES ${_NCCL_HEADER_NAMES} - HINTS ${_NCCL_HINTS} - PATH_SUFFIXES ${_NCCL_INCLUDE_SUFFIXES} - REQUIRED) - + infiniccl_configure_nccl(NCCL_INC NCCL_LIB NCCL_COMPILE_DEFINITIONS) include_directories(${NCCL_INC}) endif() if(WITH_MCCL) - if (NOT WITH_METAX AND NOT WITH_MOORE) - message(FATAL_ERROR "MCCL backend requires MetaX or Moore GPU support. Please enable `WITH_METAX` or `WITH_MOORE`.") - endif() - - set(_MCCL_HINTS) - if(MACA_PATH) - list(APPEND _MCCL_HINTS "${MACA_PATH}") - endif() - if(DEFINED ENV{MACA_PATH}) - list(APPEND _MCCL_HINTS "$ENV{MACA_PATH}") - endif() - list(APPEND _MCCL_HINTS /opt/maca) - - if(WITH_MOORE) - set(_MCCL_HINTS "${MUSA_ROOT}" /usr/local/musa) - endif() - - find_library(MCCL_LIB NAMES mccl HINTS ${_MCCL_HINTS} PATH_SUFFIXES lib lib64 REQUIRED) - find_path(MCCL_INC NAMES mccl.h HINTS ${_MCCL_HINTS} PATH_SUFFIXES include REQUIRED) - + infiniccl_configure_mccl(MCCL_INC MCCL_LIB) 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) - + infiniccl_configure_cncl(CNCL_INC CNCL_LIB) include_directories(${CNCL_INC}) endif() diff --git a/README.md b/README.md index 3ffeb67..ca8fe86 100644 --- a/README.md +++ b/README.md @@ -161,8 +161,9 @@ These options are available in any CMake project and can be passed during config | `CMAKE_BUILD_TYPE` | Build type (`Release`, `Debug`, `RelWithDebInfo`, `MinSizeRel`) | (empty, but `build.sh` sets `Release`) | > **Notes**: -> - `AUTO_DETECT_DEVICES` overrides device options like `WITH_NVIDIA` when detection succeeds. -> - `AUTO_DETECT_BACKENDS` overrides backend options like `WITH_OMPI` when detection succeeds. +> - `AUTO_DETECT_DEVICES` enables detected devices in addition to devices explicitly enabled with `WITH_*=ON`; explicit selections are preserved. +> - `AUTO_DETECT_BACKENDS` enables detected backends in addition to backends explicitly enabled with `WITH_*=ON`; explicit selections are preserved. +> - Disable the corresponding auto-detection option for a strictly manual configuration. diff --git a/cmake/backends/CNCL.cmake b/cmake/backends/CNCL.cmake new file mode 100644 index 0000000..24fd883 --- /dev/null +++ b/cmake/backends/CNCL.cmake @@ -0,0 +1,40 @@ +include_guard(GLOBAL) + +function(_infiniccl_find_cncl prefix required include_output library_output) + infiniccl_collect_cambricon_hints(_hints) + set(_include_var "${prefix}_INC") + set(_library_var "${prefix}_LIB") + + if(required) + find_path(${_include_var} NAMES cncl.h + HINTS ${_hints} PATH_SUFFIXES include REQUIRED) + find_library(${_library_var} NAMES cncl + HINTS ${_hints} PATH_SUFFIXES lib lib64 REQUIRED) + else() + find_path(${_include_var} NAMES cncl.h + HINTS ${_hints} PATH_SUFFIXES include QUIET) + find_library(${_library_var} NAMES cncl + HINTS ${_hints} PATH_SUFFIXES lib lib64 QUIET) + endif() + + set(${include_output} "${${_include_var}}" PARENT_SCOPE) + set(${library_output} "${${_library_var}}" PARENT_SCOPE) +endfunction() + +function(infiniccl_probe_cncl output) + _infiniccl_find_cncl(_INFINICCL_AUTO_CNCL FALSE _include _library) + if(_include AND _library) + set(${output} TRUE PARENT_SCOPE) + else() + set(${output} FALSE PARENT_SCOPE) + endif() +endfunction() + +function(infiniccl_configure_cncl include_output library_output) + if(NOT WITH_CAMBRICON) + message(FATAL_ERROR "CNCL backend requires Cambricon device support. Please enable `WITH_CAMBRICON`.") + endif() + _infiniccl_find_cncl(_INFINICCL_CNCL TRUE _include _library) + set(${include_output} "${_include}" PARENT_SCOPE) + set(${library_output} "${_library}" PARENT_SCOPE) +endfunction() diff --git a/cmake/backends/MCCL.cmake b/cmake/backends/MCCL.cmake new file mode 100644 index 0000000..4402311 --- /dev/null +++ b/cmake/backends/MCCL.cmake @@ -0,0 +1,63 @@ +include_guard(GLOBAL) + +function(_infiniccl_find_mccl prefix provider required include_output library_output) + if(provider STREQUAL "METAX") + infiniccl_collect_metax_hints(_hints) + elseif(provider STREQUAL "MOORE") + infiniccl_collect_moore_hints(_hints) + else() + message(FATAL_ERROR "Unknown MCCL provider `${provider}`.") + endif() + + set(_include_var "${prefix}_INC") + set(_library_var "${prefix}_LIB") + if(required) + find_path(${_include_var} NAMES mccl.h + HINTS ${_hints} PATH_SUFFIXES include REQUIRED) + find_library(${_library_var} NAMES mccl + HINTS ${_hints} PATH_SUFFIXES lib lib64 REQUIRED) + else() + find_path(${_include_var} NAMES mccl.h + HINTS ${_hints} PATH_SUFFIXES include QUIET) + find_library(${_library_var} NAMES mccl + HINTS ${_hints} PATH_SUFFIXES lib lib64 QUIET) + endif() + + set(${include_output} "${${_include_var}}" PARENT_SCOPE) + set(${library_output} "${${_library_var}}" PARENT_SCOPE) +endfunction() + +function(infiniccl_probe_mccl output) + if(WITH_METAX) + set(_provider METAX) + elseif(WITH_MOORE) + set(_provider MOORE) + else() + set(${output} FALSE PARENT_SCOPE) + return() + endif() + + _infiniccl_find_mccl(_INFINICCL_AUTO_MCCL ${_provider} FALSE _include _library) + if(_include AND _library) + set(${output} TRUE PARENT_SCOPE) + else() + set(${output} FALSE PARENT_SCOPE) + endif() +endfunction() + +function(infiniccl_configure_mccl include_output library_output) + if(NOT WITH_METAX AND NOT WITH_MOORE) + message(FATAL_ERROR + "MCCL backend requires MetaX or Moore GPU support. " + "Please enable `WITH_METAX` or `WITH_MOORE`.") + endif() + + if(WITH_MOORE) + set(_provider MOORE) + else() + set(_provider METAX) + endif() + _infiniccl_find_mccl(_INFINICCL_MCCL ${_provider} TRUE _include _library) + set(${include_output} "${_include}" PARENT_SCOPE) + set(${library_output} "${_library}" PARENT_SCOPE) +endfunction() diff --git a/cmake/backends/MPI.cmake b/cmake/backends/MPI.cmake new file mode 100644 index 0000000..db6c365 --- /dev/null +++ b/cmake/backends/MPI.cmake @@ -0,0 +1,29 @@ +include_guard(GLOBAL) + +function(infiniccl_detect_mpi output) + set(_implementation) + find_program(_INFINICCL_MPIRUN_PATH NAMES mpirun mpiexec) + find_program(_INFINICCL_MPICC_PATH NAMES mpicc) + + if(_INFINICCL_MPIRUN_PATH AND _INFINICCL_MPICC_PATH) + execute_process( + COMMAND ${_INFINICCL_MPIRUN_PATH} --version + OUTPUT_VARIABLE _version_out + ERROR_VARIABLE _version_err + ) + set(_version_info "${_version_out}${_version_err}") + + if(_version_info MATCHES "Open MPI" OR _version_info MATCHES "PRRTE") + set(_implementation OMPI) + elseif(_version_info MATCHES "MPICH" + OR _version_info MATCHES "Hydra" + OR _version_info MATCHES "Intel\\(R\\) MPI") + set(_implementation MPICH) + else() + set(_implementation OMPI) + message(STATUS "Unknown MPI implementation. Defaulting to `WITH_OMPI=ON`") + endif() + endif() + + set(${output} "${_implementation}" PARENT_SCOPE) +endfunction() diff --git a/cmake/backends/NCCL.cmake b/cmake/backends/NCCL.cmake new file mode 100644 index 0000000..905a60e --- /dev/null +++ b/cmake/backends/NCCL.cmake @@ -0,0 +1,87 @@ +include_guard(GLOBAL) + +function(_infiniccl_find_nccl prefix required include_output library_output definitions_output) + set(_hints) + set(_header_names nccl.h) + set(_library_names nccl) + set(_include_suffixes include) + set(_library_suffixes lib lib64) + set(_definitions) + + if(WITH_THEAD) + if(_THEAD_CUDA_HINTS) + set(_hints ${_THEAD_CUDA_HINTS}) + else() + infiniccl_collect_thead_hints(_hints) + endif() + list(APPEND _include_suffixes targets/x86_64-linux/include) + list(APPEND _library_suffixes targets/x86_64-linux/lib) + message(STATUS "T-Head detected. Searching for NCCL in ${_hints}") + elseif(WITH_ILUVATAR) + set(_hints /usr/local/corex) + message(STATUS "Iluvatar detected. Searching for NCCL in ${_hints}") + elseif(WITH_HYGON) + infiniccl_collect_hygon_hints(_hints) + if(HYGON_DTK_ROOT) + list(PREPEND _hints "${HYGON_DTK_ROOT}") + endif() + set(_roots ${_hints}) + foreach(_root IN LISTS _roots) + list(APPEND _hints "${_root}/rccl") + endforeach() + set(_header_names rccl/rccl.h rccl.h) + set(_library_names rccl) + set(_definitions INFINI_CCL_USE_RCCL) + list(APPEND _library_suffixes rccl/lib) + message(STATUS "Hygon detected. Searching for NCCL-compatible RCCL in ${_hints}") + endif() + list(REMOVE_DUPLICATES _hints) + + set(_include_var "${prefix}_INC") + set(_library_var "${prefix}_LIB") + if(required) + find_path(${_include_var} NAMES ${_header_names} + HINTS ${_hints} + PATH_SUFFIXES ${_include_suffixes} + REQUIRED) + find_library(${_library_var} NAMES ${_library_names} + HINTS ${_hints} + PATH_SUFFIXES ${_library_suffixes} + REQUIRED) + else() + find_path(${_include_var} NAMES ${_header_names} + HINTS ${_hints} + PATH_SUFFIXES ${_include_suffixes} + QUIET) + find_library(${_library_var} NAMES ${_library_names} + HINTS ${_hints} + PATH_SUFFIXES ${_library_suffixes} + QUIET) + endif() + + set(${include_output} "${${_include_var}}" PARENT_SCOPE) + set(${library_output} "${${_library_var}}" PARENT_SCOPE) + set(${definitions_output} "${_definitions}" PARENT_SCOPE) +endfunction() + +function(infiniccl_probe_nccl output) + _infiniccl_find_nccl(_INFINICCL_AUTO_NCCL FALSE _include _library _definitions) + if(_include AND _library) + set(${output} TRUE PARENT_SCOPE) + else() + set(${output} FALSE PARENT_SCOPE) + endif() +endfunction() + +function(infiniccl_configure_nccl include_output library_output definitions_output) + if(NOT WITH_NVIDIA AND NOT WITH_THEAD AND NOT WITH_ILUVATAR AND NOT WITH_HYGON) + message(FATAL_ERROR + "NCCL backend requires NVIDIA, T-Head, Iluvatar, or Hygon GPU support. " + "Please enable `WITH_NVIDIA`, `WITH_THEAD`, `WITH_ILUVATAR`, or `WITH_HYGON`.") + endif() + + _infiniccl_find_nccl(_INFINICCL_NCCL TRUE _include _library _definitions) + set(${include_output} "${_include}" PARENT_SCOPE) + set(${library_output} "${_library}" PARENT_SCOPE) + set(${definitions_output} "${_definitions}" PARENT_SCOPE) +endfunction() diff --git a/cmake/devices/Cambricon.cmake b/cmake/devices/Cambricon.cmake new file mode 100644 index 0000000..f25f42f --- /dev/null +++ b/cmake/devices/Cambricon.cmake @@ -0,0 +1,53 @@ +include_guard(GLOBAL) + +function(infiniccl_collect_cambricon_hints output) + set(_hints) + if(DEFINED ENV{NEUWARE_HOME} AND NOT "$ENV{NEUWARE_HOME}" STREQUAL "") + list(APPEND _hints "$ENV{NEUWARE_HOME}") + endif() + list(APPEND _hints /usr/local/neuware) + list(REMOVE_DUPLICATES _hints) + set(${output} "${_hints}" PARENT_SCOPE) +endfunction() + +function(infiniccl_detect_cambricon output) + set(_found FALSE) + if(DEFINED ENV{NEUWARE_HOME}) + set(_found TRUE) + else() + find_program(_INFINICCL_CAMBRICON_CNMON_PATH cnmon) + if(_INFINICCL_CAMBRICON_CNMON_PATH) + execute_process( + COMMAND ${_INFINICCL_CAMBRICON_CNMON_PATH} -l + RESULT_VARIABLE _cnmon_result + OUTPUT_QUIET + ERROR_QUIET + ) + if(_cnmon_result EQUAL 0) + set(_found TRUE) + endif() + endif() + endif() + set(${output} ${_found} PARENT_SCOPE) +endfunction() + +function(infiniccl_configure_cambricon) + set(_neuware_home "$ENV{NEUWARE_HOME}") + + include_directories("${_neuware_home}/include") + link_directories("${_neuware_home}/lib" "${_neuware_home}/lib64") + find_library(_INFINICCL_CAMBRICON_RUNTIME_LIB + NAMES cnrt HINTS "${_neuware_home}/lib64" REQUIRED) + find_library(_INFINICCL_CAMBRICON_CNNL_LIB + NAMES cnnl HINTS "${_neuware_home}/lib64" REQUIRED) + find_library(_INFINICCL_CAMBRICON_CNNL_EXTRA_LIB + NAMES cnnl_extra HINTS "${_neuware_home}/lib64" REQUIRED) + find_library(_INFINICCL_CAMBRICON_PAPI_LIB + NAMES cnpapi HINTS "${_neuware_home}/lib64" REQUIRED) + + set(NEUWARE_HOME "${_neuware_home}" PARENT_SCOPE) + set(CAMBRICON_RUNTIME_LIB "${_INFINICCL_CAMBRICON_RUNTIME_LIB}" PARENT_SCOPE) + set(CAMBRICON_CNNL_LIB "${_INFINICCL_CAMBRICON_CNNL_LIB}" PARENT_SCOPE) + set(CAMBRICON_CNNL_EXTRA_LIB "${_INFINICCL_CAMBRICON_CNNL_EXTRA_LIB}" PARENT_SCOPE) + set(CAMBRICON_PAPI_LIB "${_INFINICCL_CAMBRICON_PAPI_LIB}" PARENT_SCOPE) +endfunction() diff --git a/cmake/devices/DeviceDetection.cmake b/cmake/devices/DeviceDetection.cmake new file mode 100644 index 0000000..eced611 --- /dev/null +++ b/cmake/devices/DeviceDetection.cmake @@ -0,0 +1,28 @@ +include_guard(GLOBAL) + +# Preserve explicitly enabled device options and probe only devices that have +# not been requested. The caller retains responsibility for cross-device +# policies after all individual device results are available. +function(infiniccl_resolve_device_detection option display_name detector result_output) + if(NOT COMMAND ${detector}) + message(FATAL_ERROR "Unknown device detector `${detector}` for `${display_name}`.") + endif() + + set(_requested ${${option}}) + if(_requested) + set(_found TRUE) + message(STATUS "${display_name} support explicitly enabled.") + else() + cmake_language(CALL ${detector} _found) + if(_found) + message(STATUS "Auto-detected ${display_name} environment.") + else() + message(STATUS "${display_name} environment not detected.") + endif() + endif() + + if(_found) + set(${option} ON PARENT_SCOPE) + endif() + set(${result_output} ${_found} PARENT_SCOPE) +endfunction() diff --git a/cmake/devices/Hygon.cmake b/cmake/devices/Hygon.cmake new file mode 100644 index 0000000..3fe0dec --- /dev/null +++ b/cmake/devices/Hygon.cmake @@ -0,0 +1,98 @@ +include_guard(GLOBAL) + +function(infiniccl_collect_hygon_hints output) + set(_hints) + foreach(_env DTKROOT DTK_ROOT ROCM_PATH) + if(DEFINED ENV{${_env}} AND NOT "$ENV{${_env}}" STREQUAL "") + list(APPEND _hints "$ENV{${_env}}") + endif() + endforeach() + if(DEFINED ENV{HIP_PATH} AND NOT "$ENV{HIP_PATH}" STREQUAL "") + get_filename_component(_root_from_hip "$ENV{HIP_PATH}/.." ABSOLUTE) + list(APPEND _hints "${_root_from_hip}") + endif() + list(APPEND _hints /opt/dtk) + list(REMOVE_DUPLICATES _hints) + set(${output} "${_hints}" PARENT_SCOPE) +endfunction() + +function(infiniccl_detect_hygon output) + set(_found FALSE) + if((DEFINED ENV{DTKROOT} OR DEFINED ENV{DTK_ROOT} OR DEFINED ENV{ROCM_PATH}) + AND EXISTS "/dev/kfd") + set(_found TRUE) + elseif(EXISTS "/opt/dtk" AND EXISTS "/dev/kfd") + set(_found TRUE) + else() + find_program(_INFINICCL_HYGON_SMI_PATH + NAMES hy-smi rocm-smi + HINTS /opt/hyhal/bin /opt/dtk/bin + ) + if(_INFINICCL_HYGON_SMI_PATH) + execute_process( + COMMAND ${_INFINICCL_HYGON_SMI_PATH} + RESULT_VARIABLE _smi_result + OUTPUT_QUIET + ERROR_QUIET + ) + if(_smi_result EQUAL 0) + set(_found TRUE) + endif() + endif() + endif() + set(${output} ${_found} PARENT_SCOPE) +endfunction() + +function(infiniccl_configure_hygon) + set(_dtk_root) + foreach(_env DTKROOT DTK_ROOT ROCM_PATH) + if(NOT _dtk_root AND DEFINED ENV{${_env}} AND NOT "$ENV{${_env}}" STREQUAL "") + set(_dtk_root "$ENV{${_env}}") + endif() + endforeach() + + if(NOT _dtk_root AND DEFINED ENV{HIP_PATH} AND NOT "$ENV{HIP_PATH}" STREQUAL "") + get_filename_component(_dtk_root "$ENV{HIP_PATH}/.." ABSOLUTE) + endif() + + if(NOT _dtk_root AND EXISTS "/opt/dtk") + set(_dtk_root "/opt/dtk") + endif() + if(NOT _dtk_root) + message(FATAL_ERROR + "`WITH_HYGON` is `ON` but DTK was not found. " + "Set `DTKROOT`, `DTK_ROOT`, `ROCM_PATH`, or `HIP_PATH`.") + endif() + + set(_hip_hints "${_dtk_root}" "${_dtk_root}/hip") + find_path(_INFINICCL_HYGON_HIP_INCLUDE_DIR + NAMES hip/hip_runtime.h + HINTS ${_hip_hints} + PATH_SUFFIXES include hip/include + REQUIRED + ) + find_library(_INFINICCL_HYGON_HIP_RUNTIME_LIB + NAMES amdhip64 + HINTS ${_hip_hints} + PATH_SUFFIXES lib lib64 hip/lib + REQUIRED + ) + find_program(_INFINICCL_HYGON_HIPCC_COMPILER + NAMES hipcc + HINTS ${_hip_hints} + PATH_SUFFIXES bin hip/bin + REQUIRED + ) + + set(CMAKE_CXX_COMPILER "${_INFINICCL_HYGON_HIPCC_COMPILER}" + CACHE FILEPATH "Hygon DTK hipcc compiler" FORCE) + set(CMAKE_CXX_COMPILER "${_INFINICCL_HYGON_HIPCC_COMPILER}" + PARENT_SCOPE) + include_directories(${_INFINICCL_HYGON_HIP_INCLUDE_DIR}) + + set(HYGON_DTK_ROOT "${_dtk_root}" PARENT_SCOPE) + set(HYGON_HIP_INCLUDE_DIR "${_INFINICCL_HYGON_HIP_INCLUDE_DIR}" PARENT_SCOPE) + set(HYGON_HIP_RUNTIME_LIB "${_INFINICCL_HYGON_HIP_RUNTIME_LIB}" PARENT_SCOPE) + set(HYGON_HIPCC_COMPILER "${_INFINICCL_HYGON_HIPCC_COMPILER}" PARENT_SCOPE) + set(HYGON_HIP_DEFINITIONS __HIP_PLATFORM_AMD__ PARENT_SCOPE) +endfunction() diff --git a/cmake/devices/Iluvatar.cmake b/cmake/devices/Iluvatar.cmake new file mode 100644 index 0000000..e0f85d8 --- /dev/null +++ b/cmake/devices/Iluvatar.cmake @@ -0,0 +1,54 @@ +include_guard(GLOBAL) + +function(infiniccl_detect_iluvatar output) + set(_found FALSE) + file(GLOB _device_files "/dev/iluvatar*") + + if(_device_files) + set(_found TRUE) + else() + find_program(_INFINICCL_ILUVATAR_SMI_PATH ixsmi) + if(_INFINICCL_ILUVATAR_SMI_PATH) + execute_process( + COMMAND ${_INFINICCL_ILUVATAR_SMI_PATH} -L + RESULT_VARIABLE _smi_result + OUTPUT_QUIET + ERROR_QUIET + ) + if(_smi_result EQUAL 0) + set(_found TRUE) + endif() + endif() + endif() + + set(${output} ${_found} PARENT_SCOPE) +endfunction() + +function(infiniccl_configure_iluvatar) + find_program(_INFINICCL_ILUVATAR_CUDA_COMPILER NAMES clang++ HINTS /usr/local/corex/bin) + if(NOT _INFINICCL_ILUVATAR_CUDA_COMPILER) + message(FATAL_ERROR "`WITH_ILUVATAR` is `ON` but CoreX `clang++` was not found.") + endif() + + get_filename_component(_cuda_bin_dir "${_INFINICCL_ILUVATAR_CUDA_COMPILER}" DIRECTORY) + get_filename_component(_cuda_root "${_cuda_bin_dir}/.." ABSOLUTE) + set(CUDAToolkit_ROOT "${_cuda_root}" CACHE PATH "Iluvatar CoreX toolkit root" FORCE) + find_package(CUDAToolkit REQUIRED) + + set(_cuda_flags "-fPIC" + "-Wno-error=unused-variable" + "-Wno-error=unused-private-field" + "-Wno-unused-variable" + "-std=c++17" + "--cuda-path=${_cuda_root}" + "-x" + "ivcore") + set(ILUVATAR_CUDA_FLAGS "${_cuda_flags}" + CACHE STRING "Iluvatar CUDA compiler flags") + + set(ILUVATAR_CUDA_COMPILER "${_INFINICCL_ILUVATAR_CUDA_COMPILER}" PARENT_SCOPE) + set(ILUVATAR_CUDA_ROOT "${_cuda_root}" PARENT_SCOPE) + set(ILUVATAR_INCLUDE_DIR "${_cuda_root}/include" PARENT_SCOPE) + set(ILUVATAR_LIB_DIR "${_cuda_root}/lib;${_cuda_root}/lib64" PARENT_SCOPE) + set(ILUVATAR_CUDA_FLAGS "${ILUVATAR_CUDA_FLAGS}" PARENT_SCOPE) +endfunction() diff --git a/cmake/devices/MetaX.cmake b/cmake/devices/MetaX.cmake new file mode 100644 index 0000000..c1ae7ab --- /dev/null +++ b/cmake/devices/MetaX.cmake @@ -0,0 +1,51 @@ +include_guard(GLOBAL) + +function(infiniccl_collect_metax_hints output) + set(_hints) + if(DEFINED ENV{MACA_PATH} AND NOT "$ENV{MACA_PATH}" STREQUAL "") + list(APPEND _hints "$ENV{MACA_PATH}") + endif() + list(APPEND _hints /opt/maca) + list(REMOVE_DUPLICATES _hints) + set(${output} "${_hints}" PARENT_SCOPE) +endfunction() + +function(infiniccl_detect_metax output) + set(_found FALSE) + if(DEFINED ENV{MACA_PATH}) + set(_found TRUE) + else() + execute_process( + COMMAND sh -c "grep -h 9999 /sys/bus/pci/devices/*/vendor 2>/dev/null" + OUTPUT_VARIABLE _pci_vendor_output + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + string(FIND "${_pci_vendor_output}" "9999" _found_pos) + if(_found_pos GREATER -1) + set(_found TRUE) + endif() + endif() + set(${output} ${_found} PARENT_SCOPE) +endfunction() + +function(infiniccl_configure_metax) + infiniccl_collect_metax_hints(_maca_hints) + list(GET _maca_hints 0 _maca_path) + if(NOT DEFINED ENV{MACA_PATH} OR "$ENV{MACA_PATH}" STREQUAL "") + message(WARNING + "MACA_PATH environment variable not set. Defaulting to /opt/maca/. " + "Please verify this path is correct.") + endif() + + get_filename_component(_wrapper + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/devices/mxcc_wrapper.sh" ABSOLUTE) + include_directories("${_maca_path}/include") + link_directories("${_maca_path}/lib") + find_library(_INFINICCL_METAX_RUNTIME_LIB + NAMES mcruntime HINTS "${_maca_path}/lib" REQUIRED) + + set(CMAKE_C_COMPILER "${_wrapper}" PARENT_SCOPE) + set(CMAKE_CXX_COMPILER "${_wrapper}" PARENT_SCOPE) + set(MACA_PATH "${_maca_path}" PARENT_SCOPE) + set(MACA_RUNTIME_LIB "${_INFINICCL_METAX_RUNTIME_LIB}" PARENT_SCOPE) +endfunction() diff --git a/cmake/devices/Moore.cmake b/cmake/devices/Moore.cmake new file mode 100644 index 0000000..3303027 --- /dev/null +++ b/cmake/devices/Moore.cmake @@ -0,0 +1,89 @@ +include_guard(GLOBAL) + +include("${CMAKE_CURRENT_LIST_DIR}/../architecture/MusaArchitecture.cmake") + +function(infiniccl_collect_moore_hints output) + set(_hints) + foreach(_env MUSA_ROOT MUSA_HOME MUSA_PATH) + if(DEFINED ENV{${_env}} AND NOT "$ENV{${_env}}" STREQUAL "") + list(APPEND _hints "$ENV{${_env}}") + endif() + endforeach() + list(APPEND _hints /usr/local/musa) + list(REMOVE_DUPLICATES _hints) + set(${output} "${_hints}" PARENT_SCOPE) +endfunction() + +function(infiniccl_detect_moore output) + set(_found FALSE) + file(GLOB _device_files "/dev/mtgpu*") + + if(DEFINED ENV{MUSA_ROOT} OR DEFINED ENV{MUSA_HOME} OR DEFINED ENV{MUSA_PATH}) + set(_found TRUE) + elseif(_device_files) + set(_found TRUE) + else() + find_program(_INFINICCL_MOORE_SMI_PATH mthreads-gmi) + if(_INFINICCL_MOORE_SMI_PATH) + execute_process( + COMMAND ${_INFINICCL_MOORE_SMI_PATH} -L + RESULT_VARIABLE _smi_result + OUTPUT_QUIET + ERROR_QUIET + ) + if(_smi_result EQUAL 0) + set(_found TRUE) + endif() + endif() + endif() + + set(${output} ${_found} PARENT_SCOPE) +endfunction() + +function(infiniccl_configure_moore) + set(_musa_root) + foreach(_env MUSA_ROOT MUSA_HOME MUSA_PATH) + if(NOT _musa_root AND DEFINED ENV{${_env}} AND NOT "$ENV{${_env}}" STREQUAL "") + set(_musa_root "$ENV{${_env}}") + endif() + endforeach() + + if(NOT _musa_root AND EXISTS "/usr/local/musa") + set(_musa_root "/usr/local/musa") + endif() + + if(NOT _musa_root) + message(FATAL_ERROR + "`WITH_MOORE` is `ON` but `MUSA_ROOT`/`MUSA_HOME`/`MUSA_PATH` " + "is not set and `/usr/local/musa` was not found.") + endif() + if(NOT EXISTS "${_musa_root}/bin/mcc") + message(FATAL_ERROR "Could not find `mcc` under `${_musa_root}/bin`.") + endif() + + get_filename_component(_wrapper + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/devices/mcc_wrapper.sh" ABSOLUTE) + file(CHMOD "${_wrapper}" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + + include_directories("${_musa_root}/include") + link_directories("${_musa_root}/lib") + find_library(_INFINICCL_MUSA_LIB NAMES musa HINTS "${_musa_root}/lib" REQUIRED) + find_library(_INFINICCL_MUSART_LIB NAMES musart HINTS "${_musa_root}/lib" REQUIRED) + find_library(_INFINICCL_MUBLAS_LIB NAMES mublas HINTS "${_musa_root}/lib" REQUIRED) + + infiniccl_resolve_musa_architecture_config( + "${_musa_root}/include" + "${_INFINICCL_MUSART_LIB}" + ) + + set(CMAKE_C_COMPILER "${_wrapper}" PARENT_SCOPE) + set(CMAKE_CXX_COMPILER "${_wrapper}" PARENT_SCOPE) + set(MUSA_ROOT "${_musa_root}" PARENT_SCOPE) + set(MUSA_LIB "${_INFINICCL_MUSA_LIB}" PARENT_SCOPE) + set(MUSART_LIB "${_INFINICCL_MUSART_LIB}" PARENT_SCOPE) + set(MUBLAS_LIB "${_INFINICCL_MUBLAS_LIB}" PARENT_SCOPE) + set(MUSA_ARCHITECTURES "${MUSA_ARCHITECTURES}" PARENT_SCOPE) + set(MUSA_MARCH_TYPE "${MUSA_MARCH_TYPE}" PARENT_SCOPE) + set(MUSA_ARCH_COMPILE_OPTIONS "${MUSA_ARCH_COMPILE_OPTIONS}" PARENT_SCOPE) +endfunction() diff --git a/cmake/devices/Nvidia.cmake b/cmake/devices/Nvidia.cmake new file mode 100644 index 0000000..6872f59 --- /dev/null +++ b/cmake/devices/Nvidia.cmake @@ -0,0 +1,25 @@ +include_guard(GLOBAL) + +function(infiniccl_detect_nvidia output) + set(_found FALSE) + file(GLOB _device_files "/dev/nvidia0") + + if(_device_files) + set(_found TRUE) + else() + find_program(_INFINICCL_NVIDIA_SMI_PATH nvidia-smi) + if(_INFINICCL_NVIDIA_SMI_PATH) + execute_process( + COMMAND ${_INFINICCL_NVIDIA_SMI_PATH} -L + RESULT_VARIABLE _smi_result + OUTPUT_QUIET + ERROR_QUIET + ) + if(_smi_result EQUAL 0) + set(_found TRUE) + endif() + endif() + endif() + + set(${output} ${_found} PARENT_SCOPE) +endfunction() diff --git a/cmake/devices/THead.cmake b/cmake/devices/THead.cmake new file mode 100644 index 0000000..9a74d28 --- /dev/null +++ b/cmake/devices/THead.cmake @@ -0,0 +1,85 @@ +include_guard(GLOBAL) + +function(infiniccl_collect_thead_hints output) + get_property(_hints GLOBAL PROPERTY INFINICCL_THEAD_HINTS) + if(NOT _hints) + set(_hints + /usr/local/PPU_SDK + /usr/local/PPU_SDK/CUDA_SDK + ) + + foreach(_env IN ITEMS PPU_SDK PPU_HOME PPU_PATH) + if(DEFINED ENV{${_env}} AND NOT "$ENV{${_env}}" STREQUAL "") + list(APPEND _hints + "$ENV{${_env}}" + "$ENV{${_env}}/CUDA_SDK" + ) + endif() + endforeach() + + foreach(_env IN ITEMS CUDA_SDK CUDA_HOME CUDA_PATH CUDA_TOOLKIT_ROOT) + if(DEFINED ENV{${_env}} AND NOT "$ENV{${_env}}" STREQUAL "") + list(APPEND _hints + "$ENV{${_env}}" + "$ENV{${_env}}/.." + ) + endif() + endforeach() + + list(REMOVE_DUPLICATES _hints) + set_property(GLOBAL PROPERTY INFINICCL_THEAD_HINTS "${_hints}") + endif() + set(${output} "${_hints}" PARENT_SCOPE) +endfunction() + +function(infiniccl_detect_thead output) + set(_found FALSE) + infiniccl_collect_thead_hints(_hints) + foreach(_hint IN LISTS _hints) + if(EXISTS "${_hint}/CUDA_SDK" + OR EXISTS "${_hint}/bin/ppu-smi" + OR EXISTS "${_hint}/ppu-smi/bin/ppu-smi") + set(_found TRUE) + endif() + endforeach() + + if(NOT _found) + find_program(_INFINICCL_THEAD_SMI_PATH + NAMES ppu-smi nvidia-smi + HINTS /usr/local/PPU_SDK/bin /usr/local/PPU_SDK/ppu-smi/bin + ) + if(_INFINICCL_THEAD_SMI_PATH) + execute_process( + COMMAND ${_INFINICCL_THEAD_SMI_PATH} -L + RESULT_VARIABLE _smi_result + OUTPUT_VARIABLE _smi_output + ERROR_QUIET + ) + if(_smi_result EQUAL 0 AND _smi_output MATCHES "PPU") + set(_found TRUE) + endif() + endif() + endif() + set(${output} ${_found} PARENT_SCOPE) +endfunction() + +function(infiniccl_resolve_thead_cuda root_output hints_output) + infiniccl_collect_thead_hints(_hints) + list(APPEND _hints /usr/local/cuda) + list(REMOVE_DUPLICATES _hints) + + set(_cuda_root) + foreach(_hint IN LISTS _hints) + if(NOT _cuda_root AND EXISTS "${_hint}/include/cuda_runtime.h") + set(_cuda_root "${_hint}") + endif() + endforeach() + if(NOT _cuda_root) + message(FATAL_ERROR + "`WITH_THEAD` is `ON` but the T-Head CUDA-compatible SDK was not found. " + "Set `PPU_SDK`, `PPU_HOME`, `CUDA_SDK`, `CUDA_HOME`, or `CUDA_PATH`.") + endif() + + set(${root_output} "${_cuda_root}" PARENT_SCOPE) + set(${hints_output} "${_hints}" PARENT_SCOPE) +endfunction() diff --git a/examples/ccl/reduce_scatter.cc b/examples/ccl/reduce_scatter.cc index 55a0210..268aa35 100644 --- a/examples/ccl/reduce_scatter.cc +++ b/examples/ccl/reduce_scatter.cc @@ -88,6 +88,7 @@ void PrintResult(const std::vector& output, int rank, int size, std::cout << "Sample: " << output.front() << " (expected " << ExpectedValue(size, static_cast(rank)) << ")" << std::endl; + return; } void PrintMetrics(double elapsed_ms, size_t send_bytes, int size) {