mirror of
https://github.com/xmrig/xmrig.git
synced 2025-12-07 16:05:05 -05:00
Compare commits
3 Commits
dev
...
22feb9e1e7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22feb9e1e7 | ||
|
|
f0f6d1666c | ||
|
|
0399b6b6bb |
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -17,9 +17,6 @@ Steps to reproduce the behavior.
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Required data**
|
||||
- XMRig version
|
||||
- Either the exact link to a release you downloaded from https://github.com/xmrig/xmrig/releases
|
||||
- Or the exact command lines that you used to build XMRig
|
||||
- Miner log as text or screenshot
|
||||
- Config file or command line (without wallets)
|
||||
- OS: [e.g. Windows]
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,4 +4,3 @@ scripts/deps
|
||||
/CMakeLists.txt.user
|
||||
/.idea
|
||||
/src/backend/opencl/cl/cn/cryptonight_gen.cl
|
||||
.vscode
|
||||
|
||||
68
CHANGELOG.md
68
CHANGELOG.md
@@ -1,71 +1,3 @@
|
||||
# v6.24.0
|
||||
- [#3671](https://github.com/xmrig/xmrig/pull/3671) Fixed detection of L2 cache size for some complex NUMA topologies.
|
||||
- [#3674](https://github.com/xmrig/xmrig/pull/3674) Fixed ARMv7 build.
|
||||
- [#3677](https://github.com/xmrig/xmrig/pull/3677) Fixed auto-config for AMD CPUs with less than 2 MB L3 cache per thread.
|
||||
- [#3678](https://github.com/xmrig/xmrig/pull/3678) Improved IPv6 support: the new default settings use IPv6 equally with IPv4.
|
||||
|
||||
# v6.23.0
|
||||
- [#3668](https://github.com/xmrig/xmrig/issues/3668) Added support for Windows ARM64.
|
||||
- [#3665](https://github.com/xmrig/xmrig/pull/3665) Tweaked auto-config for AMD CPUs with < 2 MB L3 cache per thread.
|
||||
|
||||
# v6.22.3
|
||||
- [#3605](https://github.com/xmrig/xmrig/pull/3605) CUDA backend: added missing RandomX dataset update.
|
||||
- [#3646](https://github.com/xmrig/xmrig/pull/3646) Optimized auto-config for AMD CPUs with less than 2 MB L3 cache per thread.
|
||||
- [#3652](https://github.com/xmrig/xmrig/pull/3652) Fixed possible crash when submitting RandomX benchmark.
|
||||
- [#3662](https://github.com/xmrig/xmrig/pull/3662) Fixed OpenCL kernel compilation error on some platforms.
|
||||
|
||||
# v6.22.2
|
||||
- [#3569](https://github.com/xmrig/xmrig/pull/3569) Fixed corrupted API output in some rare conditions.
|
||||
- [#3571](https://github.com/xmrig/xmrig/pull/3571) Fixed number of threads on the new Intel Core Ultra CPUs.
|
||||
|
||||
# v6.22.1
|
||||
- [#3531](https://github.com/xmrig/xmrig/pull/3531) Always reset nonce on RandomX dataset change.
|
||||
- [#3534](https://github.com/xmrig/xmrig/pull/3534) Fixed threads auto-config on Zen5.
|
||||
- [#3535](https://github.com/xmrig/xmrig/pull/3535) RandomX: tweaks for Zen5.
|
||||
- [#3539](https://github.com/xmrig/xmrig/pull/3539) Added Zen5 to `randomx_boost.sh`.
|
||||
- [#3540](https://github.com/xmrig/xmrig/pull/3540) Detect AMD engineering samples in `randomx_boost.sh`.
|
||||
|
||||
# v6.22.0
|
||||
- [#2411](https://github.com/xmrig/xmrig/pull/2411) Added support for [Yada](https://yadacoin.io/) (`rx/yada` algorithm).
|
||||
- [#3492](https://github.com/xmrig/xmrig/pull/3492) Fixed `--background` option on Unix systems.
|
||||
- [#3518](https://github.com/xmrig/xmrig/pull/3518) Possible fix for corrupted API output in rare cases.
|
||||
- [#3522](https://github.com/xmrig/xmrig/pull/3522) Removed `rx/keva` algorithm.
|
||||
- [#3525](https://github.com/xmrig/xmrig/pull/3525) Added Zen5 detection.
|
||||
- [#3528](https://github.com/xmrig/xmrig/pull/3528) Added `rx/yada` OpenCL support.
|
||||
|
||||
# v6.21.3
|
||||
- [#3462](https://github.com/xmrig/xmrig/pull/3462) RandomX: correct memcpy size for JIT initialization.
|
||||
|
||||
# v6.21.2
|
||||
- The dependencies of all prebuilt releases have been updated. Support for old Ubuntu releases has been dropped.
|
||||
- [#2800](https://github.com/xmrig/xmrig/issues/2800) Fixed donation with GhostRider algorithm for builds without KawPow algorithm.
|
||||
- [#3436](https://github.com/xmrig/xmrig/pull/3436) Fixed, the file log writer was not thread-safe.
|
||||
- [#3450](https://github.com/xmrig/xmrig/pull/3450) Fixed RandomX crash when compiled with fortify_source.
|
||||
|
||||
# v6.21.1
|
||||
- [#3391](https://github.com/xmrig/xmrig/pull/3391) Added support for townforge (monero fork using randomx).
|
||||
- [#3399](https://github.com/xmrig/xmrig/pull/3399) Fixed Zephyr mining (OpenCL).
|
||||
- [#3420](https://github.com/xmrig/xmrig/pull/3420) Fixed segfault in HTTP API rebind.
|
||||
|
||||
# v6.21.0
|
||||
- [#3302](https://github.com/xmrig/xmrig/pull/3302) [#3312](https://github.com/xmrig/xmrig/pull/3312) Enabled keepalive for Windows (>= Vista).
|
||||
- [#3320](https://github.com/xmrig/xmrig/pull/3320) Added "built for OS/architecture/bits" to "ABOUT".
|
||||
- [#3339](https://github.com/xmrig/xmrig/pull/3339) Added SNI option for TLS connections.
|
||||
- [#3342](https://github.com/xmrig/xmrig/pull/3342) Update `cn_main_loop.asm`.
|
||||
- [#3346](https://github.com/xmrig/xmrig/pull/3346) ARM64 JIT: don't use `x18` register.
|
||||
- [#3348](https://github.com/xmrig/xmrig/pull/3348) Update to latest `sse2neon.h`.
|
||||
- [#3356](https://github.com/xmrig/xmrig/pull/3356) Updated pricing record size for **Zephyr** solo mining.
|
||||
- [#3358](https://github.com/xmrig/xmrig/pull/3358) **Zephyr** solo mining: handle multiple outputs.
|
||||
|
||||
# v6.20.0
|
||||
- Added new ARM CPU names.
|
||||
- [#2394](https://github.com/xmrig/xmrig/pull/2394) Added new CMake options `ARM_V8` and `ARM_V7`.
|
||||
- [#2830](https://github.com/xmrig/xmrig/pull/2830) Added API rebind polling.
|
||||
- [#2927](https://github.com/xmrig/xmrig/pull/2927) Fixed compatibility with hwloc 1.11.x.
|
||||
- [#3060](https://github.com/xmrig/xmrig/pull/3060) Added x86 to `README.md`.
|
||||
- [#3236](https://github.com/xmrig/xmrig/pull/3236) Fixed: receive CUDA loader error on Linux too.
|
||||
- [#3290](https://github.com/xmrig/xmrig/pull/3290) Added [Zephyr](https://www.zephyrprotocol.com/) coin support for solo mining.
|
||||
|
||||
# v6.19.3
|
||||
- [#3245](https://github.com/xmrig/xmrig/issues/3245) Improved algorithm negotiation for donation rounds by sending extra information about current mining job.
|
||||
- [#3254](https://github.com/xmrig/xmrig/pull/3254) Tweaked auto-tuning for Intel CPUs.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(xmrig)
|
||||
|
||||
option(WITH_HWLOC "Enable hwloc support" ON)
|
||||
@@ -32,6 +32,7 @@ option(WITH_VAES "Enable VAES instructions for Cryptonight" ON)
|
||||
option(WITH_BENCHMARK "Enable builtin RandomX benchmark and stress test" ON)
|
||||
option(WITH_SECURE_JIT "Enable secure access to JIT memory" OFF)
|
||||
option(WITH_DMI "Enable DMI/SMBIOS reader" ON)
|
||||
option(WITH_BUNDLED_FMT "Force use of bundled fmt library" ON)
|
||||
|
||||
option(BUILD_STATIC "Build static binary" OFF)
|
||||
option(ARM_V8 "Force ARMv8 (64 bit) architecture, use with caution if automatic detection fails, but you sure it may work" OFF)
|
||||
@@ -95,7 +96,7 @@ set(HEADERS_CRYPTO
|
||||
src/crypto/common/VirtualMemory.h
|
||||
)
|
||||
|
||||
if (XMRIG_ARM OR XMRIG_RISCV)
|
||||
if (XMRIG_ARM)
|
||||
set(HEADERS_CRYPTO "${HEADERS_CRYPTO}" src/crypto/cn/CryptoNight_arm.h)
|
||||
else()
|
||||
set(HEADERS_CRYPTO "${HEADERS_CRYPTO}" src/crypto/cn/CryptoNight_x86.h)
|
||||
@@ -162,7 +163,7 @@ if (XMRIG_OS_WIN)
|
||||
src/crypto/common/VirtualMemory_win.cpp
|
||||
)
|
||||
|
||||
set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv dbghelp)
|
||||
set(EXTRA_LIBS ws2_32 psapi iphlpapi userenv)
|
||||
elseif (XMRIG_OS_APPLE)
|
||||
list(APPEND SOURCES_OS
|
||||
src/App_unix.cpp
|
||||
@@ -198,6 +199,7 @@ add_definitions(-D__STDC_FORMAT_MACROS -DUNICODE -D_FILE_OFFSET_BITS=64)
|
||||
find_package(UV REQUIRED)
|
||||
|
||||
include(cmake/flags.cmake)
|
||||
include(cmake/fmt.cmake)
|
||||
include(cmake/randomx.cmake)
|
||||
include(cmake/argon2.cmake)
|
||||
include(cmake/kawpow.cmake)
|
||||
@@ -229,7 +231,7 @@ include(src/hw/api/api.cmake)
|
||||
include(src/hw/dmi/dmi.cmake)
|
||||
|
||||
include_directories(src)
|
||||
include_directories(src/3rdparty)
|
||||
include_directories(src/3rdparty/CL)
|
||||
include_directories(${UV_INCLUDE_DIR})
|
||||
|
||||
if (WITH_DEBUG_LOG)
|
||||
@@ -237,13 +239,10 @@ if (WITH_DEBUG_LOG)
|
||||
endif()
|
||||
|
||||
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${TLS_SOURCES} ${XMRIG_ASM_SOURCES})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB} ${ARGON2_LIBRARY} ${ETHASH_LIBRARY} ${GHOSTRIDER_LIBRARY})
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} ${XMRIG_ASM_LIBRARY} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB} ${ARGON2_LIBRARY} ${ETHASH_LIBRARY} ${GHOSTRIDER_LIBRARY} ${FMT_LIBRARY})
|
||||
|
||||
if (WIN32)
|
||||
if (NOT ARM_TARGET)
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/bin/WinRing0/WinRing0x64.sys" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/bin/WinRing0/WinRing0x64.sys" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/scripts/benchmark_1M.cmd" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/scripts/benchmark_10M.cmd" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/scripts/pool_mine_example.cmd" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||
@@ -252,5 +251,5 @@ if (WIN32)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_BUILD_TYPE STREQUAL Release AND NOT CMAKE_GENERATOR STREQUAL Xcode)
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} "$<TARGET_FILE:${CMAKE_PROJECT_NAME}>")
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
XMRig is a high performance, open source, cross platform RandomX, KawPow, CryptoNight and [GhostRider](https://github.com/xmrig/xmrig/tree/master/src/crypto/ghostrider#readme) unified CPU/GPU miner and [RandomX benchmark](https://xmrig.com/benchmark). Official binaries are available for Windows, Linux, macOS and FreeBSD.
|
||||
|
||||
## Mining backends
|
||||
- **CPU** (x86/x64/ARMv7/ARMv8/RISC-V)
|
||||
- **CPU** (x86/x64/ARMv7/ARMv8)
|
||||
- **OpenCL** for AMD GPUs.
|
||||
- **CUDA** for NVIDIA GPUs via external [CUDA plugin](https://github.com/xmrig/xmrig-cuda).
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if (WITH_ASM AND NOT XMRIG_ARM AND NOT XMRIG_RISCV AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
if (WITH_ASM AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(XMRIG_ASM_LIBRARY "xmrig-asm")
|
||||
|
||||
if (CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
|
||||
@@ -21,19 +21,6 @@ if (NOT VAES_SUPPORTED)
|
||||
set(WITH_VAES OFF)
|
||||
endif()
|
||||
|
||||
# Detect RISC-V architecture early (before it's used below)
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv64|riscv|rv64)$")
|
||||
set(RISCV_TARGET 64)
|
||||
set(XMRIG_RISCV ON)
|
||||
add_definitions(-DXMRIG_RISCV)
|
||||
message(STATUS "Detected RISC-V 64-bit architecture (${CMAKE_SYSTEM_PROCESSOR})")
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv32|rv32)$")
|
||||
set(RISCV_TARGET 32)
|
||||
set(XMRIG_RISCV ON)
|
||||
add_definitions(-DXMRIG_RISCV)
|
||||
message(STATUS "Detected RISC-V 32-bit architecture (${CMAKE_SYSTEM_PROCESSOR})")
|
||||
endif()
|
||||
|
||||
if (XMRIG_64_BIT AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64)$")
|
||||
add_definitions(-DRAPIDJSON_SSE2)
|
||||
else()
|
||||
@@ -42,59 +29,6 @@ else()
|
||||
set(WITH_VAES OFF)
|
||||
endif()
|
||||
|
||||
# Disable x86-specific features for RISC-V
|
||||
if (XMRIG_RISCV)
|
||||
set(WITH_SSE4_1 OFF)
|
||||
set(WITH_AVX2 OFF)
|
||||
set(WITH_VAES OFF)
|
||||
|
||||
# default build uses the RV64GC baseline
|
||||
set(RVARCH "rv64gc")
|
||||
|
||||
# for native builds, enable Zba and Zbb if supported by the CPU
|
||||
if(ARCH STREQUAL "native")
|
||||
enable_language(ASM)
|
||||
|
||||
try_run(RANDOMX_VECTOR_RUN_FAIL
|
||||
RANDOMX_VECTOR_COMPILE_OK
|
||||
${CMAKE_CURRENT_BINARY_DIR}/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/crypto/randomx/tests/riscv64_vector.s
|
||||
COMPILE_DEFINITIONS "-march=rv64gcv_zicbop")
|
||||
|
||||
if (RANDOMX_VECTOR_COMPILE_OK AND NOT RANDOMX_VECTOR_RUN_FAIL)
|
||||
set(RVARCH "${RVARCH}v_zicbop")
|
||||
add_definitions(-DXMRIG_RVV_ENABLED)
|
||||
message(STATUS "RISC-V vector extension detected")
|
||||
endif()
|
||||
|
||||
try_run(RANDOMX_ZBA_RUN_FAIL
|
||||
RANDOMX_ZBA_COMPILE_OK
|
||||
${CMAKE_CURRENT_BINARY_DIR}/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/crypto/randomx/tests/riscv64_zba.s
|
||||
COMPILE_DEFINITIONS "-march=rv64gc_zba")
|
||||
|
||||
if (RANDOMX_ZBA_COMPILE_OK AND NOT RANDOMX_ZBA_RUN_FAIL)
|
||||
set(RVARCH "${RVARCH}_zba")
|
||||
message(STATUS "RISC-V zba extension detected")
|
||||
endif()
|
||||
|
||||
try_run(RANDOMX_ZBB_RUN_FAIL
|
||||
RANDOMX_ZBB_COMPILE_OK
|
||||
${CMAKE_CURRENT_BINARY_DIR}/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/crypto/randomx/tests/riscv64_zbb.s
|
||||
COMPILE_DEFINITIONS "-march=rv64gc_zbb")
|
||||
|
||||
if (RANDOMX_ZBB_COMPILE_OK AND NOT RANDOMX_ZBB_RUN_FAIL)
|
||||
set(RVARCH "${RVARCH}_zbb")
|
||||
message(STATUS "RISC-V zbb extension detected")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Using -march=${RVARCH}")
|
||||
endif()
|
||||
|
||||
add_definitions(-DRAPIDJSON_WRITE_DEFAULT_FLAGS=6) # rapidjson::kWriteNanAndInfFlag | rapidjson::kWriteNanAndInfNullFlag
|
||||
|
||||
if (ARM_V8)
|
||||
set(ARM_TARGET 8)
|
||||
elseif (ARM_V7)
|
||||
@@ -102,9 +36,9 @@ elseif (ARM_V7)
|
||||
endif()
|
||||
|
||||
if (NOT ARM_TARGET)
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64|armv8-a)$")
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|armv8-a)$")
|
||||
set(ARM_TARGET 8)
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7|armv7f|armv7s|armv7k|armv7-a|armv7l|armv7ve|armv8l)$")
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7|armv7f|armv7s|armv7k|armv7-a|armv7l|armv7ve)$")
|
||||
set(ARM_TARGET 7)
|
||||
endif()
|
||||
endif()
|
||||
@@ -115,7 +49,7 @@ if (ARM_TARGET AND ARM_TARGET GREATER 6)
|
||||
|
||||
message(STATUS "Use ARM_TARGET=${ARM_TARGET} (${CMAKE_SYSTEM_PROCESSOR})")
|
||||
|
||||
if (ARM_TARGET EQUAL 8 AND (CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Clang))
|
||||
if (ARM_TARGET EQUAL 8)
|
||||
CHECK_CXX_COMPILER_FLAG(-march=armv8-a+crypto XMRIG_ARM_CRYPTO)
|
||||
|
||||
if (XMRIG_ARM_CRYPTO)
|
||||
|
||||
@@ -26,13 +26,8 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM8_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM8_CXX_FLAGS} -flax-vector-conversions")
|
||||
elseif (ARM_TARGET EQUAL 7)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfpu=neon -flax-vector-conversions")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfpu=neon")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mfpu=neon -flax-vector-conversions")
|
||||
elseif (XMRIG_RISCV)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${RVARCH}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${RVARCH}")
|
||||
|
||||
add_definitions(-DHAVE_ROTR)
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
|
||||
@@ -46,8 +41,6 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -Wl,--large-address-aware")
|
||||
endif()
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc")
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||
endif()
|
||||
@@ -70,10 +63,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -funroll-loops -fmerge-all-constants")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -funroll-loops -fmerge-all-constants")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexceptions -fno-rtti -Wno-missing-braces")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -funroll-loops -fmerge-all-constants")
|
||||
|
||||
if (ARM_TARGET EQUAL 8)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARM8_CXX_FLAGS}")
|
||||
@@ -81,11 +74,6 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
elseif (ARM_TARGET EQUAL 7)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -march=${CMAKE_SYSTEM_PROCESSOR}")
|
||||
elseif (XMRIG_RISCV)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${RVARCH}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${RVARCH}")
|
||||
|
||||
add_definitions(-DHAVE_ROTR)
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
|
||||
@@ -96,9 +84,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if ((WIN32 AND ARM_TARGET) OR BUILD_STATIC)
|
||||
if (BUILD_STATIC)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (NOT WIN32)
|
||||
|
||||
13
cmake/fmt.cmake
Normal file
13
cmake/fmt.cmake
Normal file
@@ -0,0 +1,13 @@
|
||||
# SPDX-FileCopyrightText: © 2023 Jean-Pierre De Jesus DIAZ <me@jeandudey.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
||||
if(WITH_BUNDLED_FMT)
|
||||
add_library(fmt INTERFACE)
|
||||
target_sources(fmt INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src/3rdparty/fmt/format.cc)
|
||||
target_include_directories(fmt INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/src/3rdparty/fmt)
|
||||
else()
|
||||
set(FMT_LIBRARY fmt)
|
||||
find_package(fmt REQUIRED)
|
||||
set(FMT_LIBRARY fmt::fmt)
|
||||
endif()
|
||||
@@ -17,13 +17,10 @@ else()
|
||||
set(XMRIG_OS_LINUX ON)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL DragonFly)
|
||||
set(XMRIG_OS_FREEBSD ON)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL OpenBSD)
|
||||
set(XMRIG_OS_OPENBSD ON)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
|
||||
set(XMRIG_OS_HAIKU ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
if (XMRIG_OS_WIN)
|
||||
add_definitions(-DWIN32 -DXMRIG_OS_WIN)
|
||||
elseif(XMRIG_OS_APPLE)
|
||||
@@ -47,10 +44,6 @@ elseif(XMRIG_OS_UNIX)
|
||||
add_definitions(-DXMRIG_OS_LINUX)
|
||||
elseif (XMRIG_OS_FREEBSD)
|
||||
add_definitions(-DXMRIG_OS_FREEBSD)
|
||||
elseif (XMRIG_OS_OPENBSD)
|
||||
add_definitions(-DXMRIG_OS_OPENBSD)
|
||||
elseif (XMRIG_OS_HAIKU)
|
||||
add_definitions(-DXMRIG_OS_HAIKU)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
if (WITH_RANDOMX)
|
||||
include(CheckSymbolExists)
|
||||
|
||||
if (WIN32)
|
||||
check_symbol_exists(_aligned_malloc "stdlib.h" HAVE_ALIGNED_MALLOC)
|
||||
if (HAVE_ALIGNED_MALLOC)
|
||||
add_compile_definitions(HAVE_ALIGNED_MALLOC)
|
||||
endif()
|
||||
else()
|
||||
check_symbol_exists(posix_memalign "stdlib.h" HAVE_POSIX_MEMALIGN)
|
||||
if (HAVE_POSIX_MEMALIGN)
|
||||
add_compile_definitions(HAVE_POSIX_MEMALIGN)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_definitions(/DXMRIG_ALGO_RANDOMX)
|
||||
set(WITH_ARGON2 ON)
|
||||
|
||||
@@ -62,7 +48,7 @@ if (WITH_RANDOMX)
|
||||
src/crypto/randomx/jit_compiler_x86_static.asm
|
||||
src/crypto/randomx/jit_compiler_x86.cpp
|
||||
)
|
||||
elseif (WITH_ASM AND NOT XMRIG_ARM AND NOT XMRIG_RISCV AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
elseif (WITH_ASM AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
list(APPEND SOURCES_CRYPTO
|
||||
src/crypto/randomx/jit_compiler_x86_static.S
|
||||
src/crypto/randomx/jit_compiler_x86.cpp
|
||||
@@ -80,16 +66,6 @@ if (WITH_RANDOMX)
|
||||
else()
|
||||
set_property(SOURCE src/crypto/randomx/jit_compiler_a64_static.S PROPERTY LANGUAGE C)
|
||||
endif()
|
||||
elseif (XMRIG_RISCV AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
list(APPEND SOURCES_CRYPTO
|
||||
src/crypto/randomx/jit_compiler_rv64_static.S
|
||||
src/crypto/randomx/jit_compiler_rv64_vector_static.S
|
||||
src/crypto/randomx/jit_compiler_rv64.cpp
|
||||
src/crypto/randomx/jit_compiler_rv64_vector.cpp
|
||||
)
|
||||
# cheat because cmake and ccache hate each other
|
||||
set_property(SOURCE src/crypto/randomx/jit_compiler_rv64_static.S PROPERTY LANGUAGE C)
|
||||
set_property(SOURCE src/crypto/randomx/jit_compiler_rv64_vector_static.S PROPERTY LANGUAGE C)
|
||||
else()
|
||||
list(APPEND SOURCES_CRYPTO
|
||||
src/crypto/randomx/jit_compiler_fallback.cpp
|
||||
@@ -126,7 +102,7 @@ if (WITH_RANDOMX)
|
||||
)
|
||||
endif()
|
||||
|
||||
if (WITH_MSR AND NOT XMRIG_ARM AND NOT XMRIG_RISCV AND CMAKE_SIZEOF_VOID_P EQUAL 8 AND (XMRIG_OS_WIN OR XMRIG_OS_LINUX))
|
||||
if (WITH_MSR AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8 AND (XMRIG_OS_WIN OR XMRIG_OS_LINUX))
|
||||
add_definitions(/DXMRIG_FEATURE_MSR)
|
||||
add_definitions(/DXMRIG_FIX_RYZEN)
|
||||
message("-- WITH_MSR=ON")
|
||||
|
||||
@@ -13,6 +13,7 @@ Option `coin` useful for pools without [algorithm negotiation](https://xmrig.com
|
||||
| Name | Memory | Version | Description | Notes |
|
||||
|------|--------|---------|-------------|-------|
|
||||
| `kawpow` | - | 6.0.0+ | KawPow (Ravencoin) | GPU only |
|
||||
| `rx/keva` | 1 MB | 5.9.0+ | RandomKEVA (RandomX variant for Keva). | |
|
||||
| `astrobwt` | 20 MB | 5.8.0+ | AstroBWT (Dero). | |
|
||||
| `cn-pico/tlo` | 256 KB | 5.5.0+ | CryptoNight-Pico (Talleo). | |
|
||||
| `rx/sfx` | 2 MB | 5.4.0+ | RandomSFX (RandomX variant for Safex). | |
|
||||
|
||||
@@ -256,7 +256,7 @@
|
||||
|
||||
# v2.8.0
|
||||
- **[#753](https://github.com/xmrig/xmrig/issues/753) Added new algorithm [CryptoNight variant 2](https://github.com/xmrig/xmrig/issues/753) for Monero fork, thanks [@SChernykh](https://github.com/SChernykh).**
|
||||
- Added global and per thread option `"asm"` and command line equivalent.
|
||||
- Added global and per thread option `"asm"` and and command line equivalent.
|
||||
- **[#758](https://github.com/xmrig/xmrig/issues/758) Added SSL/TLS support for secure connections to pools.**
|
||||
- Added per pool options `"tls"` and `"tls-fingerprint"` and command line equivalents.
|
||||
- [#767](https://github.com/xmrig/xmrig/issues/767) Added config autosave feature, same with GPU miners.
|
||||
|
||||
@@ -1,365 +0,0 @@
|
||||
# RISC-V Performance Optimization Guide
|
||||
|
||||
This guide provides comprehensive instructions for optimizing XMRig on RISC-V architectures.
|
||||
|
||||
## Build Optimizations
|
||||
|
||||
### Compiler Flags Applied Automatically
|
||||
|
||||
The CMake build now applies aggressive RISC-V-specific optimizations:
|
||||
|
||||
```cmake
|
||||
# RISC-V ISA with extensions
|
||||
-march=rv64gcv_zba_zbb_zbc_zbs
|
||||
|
||||
# Aggressive compiler optimizations
|
||||
-funroll-loops # Unroll loops for ILP (instruction-level parallelism)
|
||||
-fomit-frame-pointer # Free up frame pointer register (RISC-V has limited registers)
|
||||
-fno-common # Better code generation for global variables
|
||||
-finline-functions # Inline more functions for better cache locality
|
||||
-ffast-math # Relaxed FP semantics (safe for mining)
|
||||
-flto # Link-time optimization for cross-module inlining
|
||||
|
||||
# Release build additions
|
||||
-minline-atomics # Inline atomic operations for faster synchronization
|
||||
```
|
||||
|
||||
### Optimal Build Command
|
||||
|
||||
```bash
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
**Expected build time**: 5-15 minutes depending on CPU
|
||||
|
||||
## Runtime Optimizations
|
||||
|
||||
### 1. Memory Configuration (Most Important)
|
||||
|
||||
Enable huge pages to reduce TLB misses and fragmentation:
|
||||
|
||||
#### Enable 2MB Huge Pages
|
||||
```bash
|
||||
# Calculate required huge pages (1 page = 2MB)
|
||||
# For 2 GB dataset: 1024 pages
|
||||
# For cache + dataset: 1536 pages minimum
|
||||
sudo sysctl -w vm.nr_hugepages=2048
|
||||
```
|
||||
|
||||
Verify:
|
||||
```bash
|
||||
grep HugePages /proc/meminfo
|
||||
# Expected: HugePages_Free should be close to nr_hugepages
|
||||
```
|
||||
|
||||
#### Enable 1GB Huge Pages (Optional but Recommended)
|
||||
|
||||
```bash
|
||||
# Run provided helper script
|
||||
sudo ./scripts/enable_1gb_pages.sh
|
||||
|
||||
# Verify 1GB pages are available
|
||||
cat /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
|
||||
# Should be: >= 1 (one 1GB page)
|
||||
```
|
||||
|
||||
Update config.json:
|
||||
```json
|
||||
{
|
||||
"cpu": {
|
||||
"huge-pages": true
|
||||
},
|
||||
"randomx": {
|
||||
"1gb-pages": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. RandomX Mode Selection
|
||||
|
||||
| Mode | Memory | Init Time | Throughput | Recommendation |
|
||||
|------|--------|-----------|-----------|-----------------|
|
||||
| **light** | 256 MB | 10 sec | Low | Testing, resource-constrained |
|
||||
| **fast** | 2 GB | 2-5 min* | High | Production (with huge pages) |
|
||||
| **auto** | 2 GB | Varies | High | Default (uses fast if possible) |
|
||||
|
||||
*With optimizations; can be 30+ minutes without huge pages
|
||||
|
||||
**For RISC-V, use fast mode with huge pages enabled.**
|
||||
|
||||
### 3. Dataset Initialization Threads
|
||||
|
||||
Optimal thread count = 60-75% of CPU cores (leaves headroom for OS/other tasks)
|
||||
|
||||
```json
|
||||
{
|
||||
"randomx": {
|
||||
"init": 4
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Or auto-detect (rewritten for RISC-V):
|
||||
```json
|
||||
{
|
||||
"randomx": {
|
||||
"init": -1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. CPU Affinity (Optional)
|
||||
|
||||
Pin threads to specific cores for better cache locality:
|
||||
|
||||
```json
|
||||
{
|
||||
"cpu": {
|
||||
"rx/0": [
|
||||
{ "threads": 1, "affinity": 0 },
|
||||
{ "threads": 1, "affinity": 1 },
|
||||
{ "threads": 1, "affinity": 2 },
|
||||
{ "threads": 1, "affinity": 3 }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. CPU Governor (Linux)
|
||||
|
||||
Set to performance mode for maximum throughput:
|
||||
|
||||
```bash
|
||||
# Check current governor
|
||||
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
||||
|
||||
# Set to performance (requires root)
|
||||
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
|
||||
|
||||
# Verify
|
||||
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
||||
# Should output: performance
|
||||
```
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
### Minimum (Testing)
|
||||
```json
|
||||
{
|
||||
"randomx": {
|
||||
"mode": "light"
|
||||
},
|
||||
"cpu": {
|
||||
"huge-pages": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Recommended (Balanced)
|
||||
```json
|
||||
{
|
||||
"randomx": {
|
||||
"mode": "auto",
|
||||
"init": 4,
|
||||
"1gb-pages": true
|
||||
},
|
||||
"cpu": {
|
||||
"huge-pages": true,
|
||||
"priority": 2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Maximum Performance (Production)
|
||||
```json
|
||||
{
|
||||
"randomx": {
|
||||
"mode": "fast",
|
||||
"init": -1,
|
||||
"1gb-pages": true,
|
||||
"scratchpad_prefetch_mode": 1
|
||||
},
|
||||
"cpu": {
|
||||
"huge-pages": true,
|
||||
"priority": 3,
|
||||
"yield": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## CLI Equivalents
|
||||
|
||||
```bash
|
||||
# Light mode
|
||||
./xmrig --randomx-mode=light
|
||||
|
||||
# Fast mode with 4 init threads
|
||||
./xmrig --randomx-mode=fast --randomx-init=4
|
||||
|
||||
# Benchmark
|
||||
./xmrig --bench=1M --algo=rx/0
|
||||
|
||||
# Benchmark Wownero variant (1 MB scratchpad)
|
||||
./xmrig --bench=1M --algo=rx/wow
|
||||
|
||||
# Mine to pool
|
||||
./xmrig -o pool.example.com:3333 -u YOUR_WALLET -p x
|
||||
```
|
||||
|
||||
## Performance Diagnostics
|
||||
|
||||
### Check if Vector Extensions are Detected
|
||||
|
||||
Look for `FEATURES:` line in output:
|
||||
```
|
||||
* CPU: ky,x60 (uarch ky,x1)
|
||||
* FEATURES: rv64imafdcv zba zbb zbc zbs
|
||||
```
|
||||
|
||||
- `v`: Vector extension (RVV) ✓
|
||||
- `zba`, `zbb`, `zbc`, `zbs`: Bit manipulation ✓
|
||||
- If missing, make sure build used `-march=rv64gcv_zba_zbb_zbc_zbs`
|
||||
|
||||
### Verify Huge Pages at Runtime
|
||||
|
||||
```bash
|
||||
# Run xmrig with --bench=1M and check output
|
||||
./xmrig --bench=1M
|
||||
|
||||
# Look for line like:
|
||||
# HUGE PAGES 100% 1 / 1 (1024 MB)
|
||||
```
|
||||
|
||||
- Should show 100% for dataset AND threads
|
||||
- If less, increase `vm.nr_hugepages` and reboot
|
||||
|
||||
### Monitor Performance
|
||||
|
||||
```bash
|
||||
# Run benchmark multiple times to find stable hashrate
|
||||
./xmrig --bench=1M --algo=rx/0
|
||||
./xmrig --bench=10M --algo=rx/0
|
||||
./xmrig --bench=100M --algo=rx/0
|
||||
|
||||
# Check system load and memory during mining
|
||||
while true; do free -h; grep HugePages /proc/meminfo; sleep 2; done
|
||||
```
|
||||
|
||||
## Expected Performance
|
||||
|
||||
### Hardware: Orange Pi RV2 (Ky X1, 8 cores @ ~1.5 GHz)
|
||||
|
||||
| Config | Mode | Hashrate | Init Time |
|
||||
|--------|------|----------|-----------|
|
||||
| Scalar (baseline) | fast | 30 H/s | 10 min |
|
||||
| Scalar + huge pages | fast | 33 H/s | 2 min |
|
||||
| RVV (if enabled) | fast | 70-100 H/s | 3 min |
|
||||
|
||||
*Actual results depend on CPU frequency, memory speed, and load*
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Long Initialization Times (30+ minutes)
|
||||
|
||||
**Cause**: Huge pages not enabled, system using swap
|
||||
**Solution**:
|
||||
1. Enable huge pages: `sudo sysctl -w vm.nr_hugepages=2048`
|
||||
2. Reboot: `sudo reboot`
|
||||
3. Reduce mining threads to free memory
|
||||
4. Check available memory: `free -h`
|
||||
|
||||
### Low Hashrate (50% of expected)
|
||||
|
||||
**Cause**: CPU governor set to power-save, no huge pages, high contention
|
||||
**Solution**:
|
||||
1. Set governor to performance: `echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor`
|
||||
2. Enable huge pages
|
||||
3. Reduce number of mining threads
|
||||
4. Check system load: `top` or `htop`
|
||||
|
||||
### Dataset Init Crashes or Hangs
|
||||
|
||||
**Cause**: Insufficient memory, corrupted huge pages
|
||||
**Solution**:
|
||||
1. Disable huge pages temporarily: set `huge-pages: false` in config
|
||||
2. Reduce mining threads
|
||||
3. Reboot and re-enable huge pages
|
||||
4. Try light mode: `--randomx-mode=light`
|
||||
|
||||
### Out of Memory During Benchmark
|
||||
|
||||
**Cause**: Not enough RAM for dataset + cache + threads
|
||||
**Solution**:
|
||||
1. Use light mode: `--randomx-mode=light`
|
||||
2. Reduce mining threads: `--threads=1`
|
||||
3. Increase available memory (kill other processes)
|
||||
4. Check: `free -h` before mining
|
||||
|
||||
## Advanced Tuning
|
||||
|
||||
### Vector Length (VLEN) Detection
|
||||
|
||||
RISC-V vector extension variable length (VLEN) affects performance:
|
||||
|
||||
```bash
|
||||
# Check VLEN on your CPU
|
||||
cat /proc/cpuinfo | grep vlen
|
||||
|
||||
# Expected values:
|
||||
# - 128 bits (16 bytes) = minimum
|
||||
# - 256 bits (32 bytes) = common
|
||||
# - 512 bits (64 bytes) = high performance
|
||||
```
|
||||
|
||||
Larger VLEN generally means better performance for vectorized operations.
|
||||
|
||||
### Prefetch Optimization
|
||||
|
||||
The code automatically optimizes memory prefetching for RISC-V:
|
||||
|
||||
```
|
||||
scratchpad_prefetch_mode: 0 = disabled (slowest)
|
||||
scratchpad_prefetch_mode: 1 = prefetch.r (default, recommended)
|
||||
scratchpad_prefetch_mode: 2 = prefetch.w (experimental)
|
||||
```
|
||||
|
||||
### Memory Bandwidth Saturation
|
||||
|
||||
If experiencing memory bandwidth saturation (high latency):
|
||||
|
||||
1. Reduce mining threads
|
||||
2. Increase L2/L3 cache by mining fewer threads per core
|
||||
3. Enable cache QoS (AMD Ryzen): `cache_qos: true`
|
||||
|
||||
## Building with Custom Flags
|
||||
|
||||
To build with custom RISC-V flags:
|
||||
|
||||
```bash
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_C_FLAGS="-march=rv64gcv_zba_zbb_zbc_zbs -O3 -funroll-loops -fomit-frame-pointer" \
|
||||
..
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
## Future Optimizations
|
||||
|
||||
- [ ] Zbk* (crypto) support detection and usage
|
||||
- [ ] Optimal VLEN-aware algorithm selection
|
||||
- [ ] Per-core memory affinity (NUMA support)
|
||||
- [ ] Dynamic thread count adjustment based on thermals
|
||||
- [ ] Cross-compile optimizations for various RISC-V cores
|
||||
|
||||
## References
|
||||
|
||||
- [RISC-V Vector Extension Spec](https://github.com/riscv/riscv-v-spec)
|
||||
- [RISC-V Bit Manipulation Spec](https://github.com/riscv/riscv-bitmanip)
|
||||
- [RISC-V Crypto Spec](https://github.com/riscv/riscv-crypto)
|
||||
- [XMRig Documentation](https://xmrig.com/docs)
|
||||
|
||||
---
|
||||
|
||||
For further optimization, enable RVV intrinsics by replacing `sse2rvv.h` with `sse2rvv_optimized.h` in the build.
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/bin/sh -e
|
||||
#!/bin/bash -e
|
||||
|
||||
HWLOC_VERSION_MAJOR="2"
|
||||
HWLOC_VERSION_MINOR="12"
|
||||
HWLOC_VERSION_PATCH="1"
|
||||
HWLOC_VERSION_MINOR="9"
|
||||
HWLOC_VERSION_PATCH="0"
|
||||
|
||||
HWLOC_VERSION="${HWLOC_VERSION_MAJOR}.${HWLOC_VERSION_MINOR}.${HWLOC_VERSION_PATCH}"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh -e
|
||||
#!/bin/bash -e
|
||||
|
||||
HWLOC_VERSION="1.11.13"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh -e
|
||||
#!/bin/bash -e
|
||||
|
||||
LIBRESSL_VERSION="3.5.2"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh -e
|
||||
#!/bin/bash -e
|
||||
|
||||
OPENSSL_VERSION="1.1.1u"
|
||||
OPENSSL_VERSION="1.1.1s"
|
||||
|
||||
mkdir -p deps
|
||||
mkdir -p deps/include
|
||||
@@ -8,7 +8,7 @@ mkdir -p deps/lib
|
||||
|
||||
mkdir -p build && cd build
|
||||
|
||||
wget https://openssl.org/source/old/1.1.1/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
|
||||
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
|
||||
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
|
||||
|
||||
cd openssl-${OPENSSL_VERSION}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh -e
|
||||
#!/bin/bash -e
|
||||
|
||||
OPENSSL_VERSION="3.0.16"
|
||||
OPENSSL_VERSION="3.0.7"
|
||||
|
||||
mkdir -p deps
|
||||
mkdir -p deps/include
|
||||
@@ -8,7 +8,7 @@ mkdir -p deps/lib
|
||||
|
||||
mkdir -p build && cd build
|
||||
|
||||
wget https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VERSION}/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
|
||||
wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz -O openssl-${OPENSSL_VERSION}.tar.gz
|
||||
tar -xzf openssl-${OPENSSL_VERSION}.tar.gz
|
||||
|
||||
cd openssl-${OPENSSL_VERSION}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh -e
|
||||
#!/bin/bash -e
|
||||
|
||||
UV_VERSION="1.51.0"
|
||||
UV_VERSION="1.44.2"
|
||||
|
||||
mkdir -p deps
|
||||
mkdir -p deps/include
|
||||
@@ -8,10 +8,10 @@ mkdir -p deps/lib
|
||||
|
||||
mkdir -p build && cd build
|
||||
|
||||
wget https://dist.libuv.org/dist/v${UV_VERSION}/libuv-v${UV_VERSION}.tar.gz -O v${UV_VERSION}.tar.gz
|
||||
wget https://github.com/libuv/libuv/archive/v${UV_VERSION}.tar.gz -O v${UV_VERSION}.tar.gz
|
||||
tar -xzf v${UV_VERSION}.tar.gz
|
||||
|
||||
cd libuv-v${UV_VERSION}
|
||||
cd libuv-${UV_VERSION}
|
||||
sh autogen.sh
|
||||
./configure --disable-shared
|
||||
make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh -e
|
||||
#!/bin/bash -e
|
||||
|
||||
./build.uv.sh
|
||||
./build.hwloc.sh
|
||||
./build.openssl3.sh
|
||||
./build.openssl.sh
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh -e
|
||||
#!/bin/bash -e
|
||||
|
||||
# https://xmrig.com/docs/miner/hugepages#onegb-huge-pages
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { text2h, text2h_bundle, addIncludes } = require('./js/opencl');
|
||||
const { opencl_minify } = require('./js/opencl_minify');
|
||||
const cwd = process.cwd();
|
||||
|
||||
|
||||
function cn()
|
||||
@@ -49,6 +50,7 @@ function rx()
|
||||
'randomx_constants_monero.h',
|
||||
'randomx_constants_wow.h',
|
||||
'randomx_constants_arqma.h',
|
||||
'randomx_constants_keva.h',
|
||||
'randomx_constants_graft.h',
|
||||
'aes.cl',
|
||||
'blake2b.cl',
|
||||
@@ -75,24 +77,18 @@ function kawpow()
|
||||
fs.writeFileSync('kawpow_dag_cl.h', text2h(kawpow_dag, 'xmrig', 'kawpow_dag_cl'));
|
||||
}
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
if (fs.existsSync('src/backend/opencl/cl/OclSource.h')) {
|
||||
break;
|
||||
}
|
||||
|
||||
process.chdir('..');
|
||||
}
|
||||
process.chdir(path.resolve('src/backend/opencl/cl/cn'));
|
||||
|
||||
process.chdir(path.resolve('src/backend/opencl/cl'));
|
||||
|
||||
const cwd = process.cwd();
|
||||
|
||||
process.chdir(path.resolve(cwd, 'cn'));
|
||||
cn();
|
||||
cn_r();
|
||||
|
||||
process.chdir(path.resolve(cwd, 'rx'));
|
||||
process.chdir(cwd);
|
||||
process.chdir(path.resolve('src/backend/opencl/cl/rx'));
|
||||
|
||||
rx();
|
||||
|
||||
process.chdir(path.resolve(cwd, 'kawpow'));
|
||||
process.chdir(cwd);
|
||||
process.chdir(path.resolve('src/backend/opencl/cl/kawpow'));
|
||||
|
||||
kawpow();
|
||||
|
||||
@@ -8,11 +8,11 @@ else
|
||||
modprobe msr allow_writes=on
|
||||
fi
|
||||
|
||||
if grep -E 'AMD Ryzen|AMD EPYC|AuthenticAMD' /proc/cpuinfo > /dev/null;
|
||||
if grep -E 'AMD Ryzen|AMD EPYC' /proc/cpuinfo > /dev/null;
|
||||
then
|
||||
if grep "cpu family[[:space:]]\{1,\}:[[:space:]]25" /proc/cpuinfo > /dev/null;
|
||||
then
|
||||
if grep "model[[:space:]]\{1,\}:[[:space:]]\(97\|117\)" /proc/cpuinfo > /dev/null;
|
||||
if grep "model[[:space:]]\{1,\}:[[:space:]]97" /proc/cpuinfo > /dev/null;
|
||||
then
|
||||
echo "Detected Zen4 CPU"
|
||||
wrmsr -a 0xc0011020 0x4400000000000
|
||||
@@ -28,14 +28,6 @@ if grep -E 'AMD Ryzen|AMD EPYC|AuthenticAMD' /proc/cpuinfo > /dev/null;
|
||||
wrmsr -a 0xc001102b 0x2000cc10
|
||||
echo "MSR register values for Zen3 applied"
|
||||
fi
|
||||
elif grep "cpu family[[:space:]]\{1,\}:[[:space:]]26" /proc/cpuinfo > /dev/null;
|
||||
then
|
||||
echo "Detected Zen5 CPU"
|
||||
wrmsr -a 0xc0011020 0x4400000000000
|
||||
wrmsr -a 0xc0011021 0x4000000000040
|
||||
wrmsr -a 0xc0011022 0x8680000401570000
|
||||
wrmsr -a 0xc001102b 0x2040cc10
|
||||
echo "MSR register values for Zen5 applied"
|
||||
else
|
||||
echo "Detected Zen1/Zen2 CPU"
|
||||
wrmsr -a 0xc0011020 0
|
||||
|
||||
4
src/3rdparty/argon2/CMakeLists.txt
vendored
4
src/3rdparty/argon2/CMakeLists.txt
vendored
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(argon2 C)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
@@ -35,7 +35,7 @@ if (CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
add_feature_impl(xop "" HAVE_XOP)
|
||||
add_feature_impl(avx2 "/arch:AVX2" HAVE_AVX2)
|
||||
add_feature_impl(avx512f "/arch:AVX512F" HAVE_AVX512F)
|
||||
elseif (NOT XMRIG_ARM AND NOT XMRIG_RISCV AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
elseif (NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
function(add_feature_impl FEATURE GCC_FLAG DEF)
|
||||
add_library(argon2-${FEATURE} STATIC arch/x86_64/lib/argon2-${FEATURE}.c)
|
||||
target_include_directories(argon2-${FEATURE} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../)
|
||||
|
||||
2
src/3rdparty/cl.h
vendored
2
src/3rdparty/cl.h
vendored
@@ -29,7 +29,7 @@
|
||||
#if defined(__APPLE__)
|
||||
# include <OpenCL/cl.h>
|
||||
#else
|
||||
# include "3rdparty/CL/cl.h"
|
||||
# include <CL/cl.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
2
src/3rdparty/epee/README.md
vendored
2
src/3rdparty/epee/README.md
vendored
@@ -1 +1 @@
|
||||
epee - is a small library of helpers, wrappers, tools and so on, used to make my life easier.
|
||||
epee - is a small library of helpers, wrappers, tools and and so on, used to make my life easier.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "3rdparty/fmt/format-inl.h"
|
||||
#include "fmt/format-inl.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace detail {
|
||||
2
src/3rdparty/hwloc/CMakeLists.txt
vendored
2
src/3rdparty/hwloc/CMakeLists.txt
vendored
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project (hwloc C)
|
||||
|
||||
include_directories(include)
|
||||
|
||||
218
src/3rdparty/hwloc/NEWS
vendored
218
src/3rdparty/hwloc/NEWS
vendored
@@ -1,5 +1,5 @@
|
||||
Copyright © 2009 CNRS
|
||||
Copyright © 2009-2025 Inria. All rights reserved.
|
||||
Copyright © 2009-2022 Inria. All rights reserved.
|
||||
Copyright © 2009-2013 Université Bordeaux
|
||||
Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
Copyright © 2020 Hewlett Packard Enterprise. All rights reserved.
|
||||
@@ -17,214 +17,6 @@ bug fixes (and other actions) for each version of hwloc since version
|
||||
0.9.
|
||||
|
||||
|
||||
Version 2.12.1
|
||||
--------------
|
||||
* Add hwloc-calc's --default-nodes option to hwloc-bind and hwloc-info.
|
||||
* Improve the --best-memattr "default" fallback, try to use "default"
|
||||
memory nodes, and add verbose messages and warnings if some
|
||||
performance info are incomplete or missing.
|
||||
Thanks to Antoine Morvan for the report.
|
||||
* Fix CPU and memory binding on different locations,
|
||||
thanks to Antoine Morvan for the report.
|
||||
* Add HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY and enable it by
|
||||
default in hwloc-calc --local-memory for finding local NUMA nodes
|
||||
that do not exactly match input locations.
|
||||
Thanks to Antoine Morvan for the report.
|
||||
* Fix a possible crash in the x86 backend when Qemu is configured to
|
||||
expose multicore/thread CPUs that are actually single-core/thread.
|
||||
Thanks to Georg Pfuetzenreuter.
|
||||
|
||||
|
||||
Version 2.12.0
|
||||
--------------
|
||||
* Add hwloc_topology_get_default_nodeset() for the set of default
|
||||
NUMA nodes.
|
||||
- hwloc-calc now has --default-nodes option.
|
||||
* Rework oneAPI LevelZero support to use zesInit() and avoid the need
|
||||
to set ZES_ENABLE_SYSMAN=1 in the environment.
|
||||
- zesDriverGetDeviceByUuidExp() is now required in the L0 runtime.
|
||||
- ZES/Sysman variants were added in hwloc/levelzero.h to specifically
|
||||
handle ZES/Sysman device handles.
|
||||
* Fix the locality of AMD GPU partitions, thanks to Edgar Leon for
|
||||
reporting and debugging the issue.
|
||||
* Better detect Cray Slingshot NICs, thanks to Edgar Leon.
|
||||
* Add support for Die objects and Module groups on Windows.
|
||||
* Only filter-out Dies that are identical to their Packages
|
||||
when it applies to all Dies.
|
||||
* Improve hwloc-calc to handle CPU-less NUMA nodes or platforms with
|
||||
heterogeneous memory without requiring --nodeset-output.
|
||||
* hwloc-calc now accepts counting/listing cpukinds and memory tiers
|
||||
with -N and -I cpukind/memorytier.
|
||||
* The systemd-dbus-api output of hwloc-calc has changed, and
|
||||
--nodeset-output-format was added, to support NUMA node outputs.
|
||||
Thanks to Pierre Neyron.
|
||||
* Update NVLink bandwidth and CUDA capabilities up to NVIDIA Blackwell.
|
||||
* Fix some NUMA syscalls on Linux for platforms with old libc headers.
|
||||
* Some minor fixes in distances.
|
||||
|
||||
|
||||
Version 2.11.2
|
||||
--------------
|
||||
* Add missing CPU info attrs on aarch64 on Linux.
|
||||
* Use ACPI CPPC on Linux to get better information about cpukinds,
|
||||
at least on AMD CPUs.
|
||||
* Fix crash when manipulating cpukinds after topology
|
||||
duplication, thanks to Hadrien Grasland for the report.
|
||||
* Fix missing input target checks in memattr functions,
|
||||
thanks to Hadrien Grasland for the report.
|
||||
* Fix a memory leak when ignoring NUMA distances on FreeBSD.
|
||||
* Fix build failure on old Linux distributions without accessat().
|
||||
* Fix non-Windows importing of XML topologies and CPUID dumps exported
|
||||
on Windows.
|
||||
* hwloc-calc --cpuset-output-format systemd-dbus-api now allows
|
||||
to generate AllowedCPUs information for systemd slices.
|
||||
See the hwloc-calc manpage for examples. Thanks to Pierre Neyron.
|
||||
* Some fixes in manpage EXAMPLES and split them into subsections.
|
||||
|
||||
|
||||
Version 2.11.1
|
||||
--------------
|
||||
* Fix bash completions, thanks Tavis Rudd.
|
||||
|
||||
|
||||
Version 2.11.0
|
||||
--------------
|
||||
* API
|
||||
+ Add HWLOC_MEMBIND_WEIGHTED_INTERLEAVE memory binding policy on
|
||||
Linux 6.9+. Thanks to Honggyu Kim for the patch.
|
||||
- weighted_interleave_membind is added to membind support bits.
|
||||
- The "weighted" policy is added to the hwloc-bind tool.
|
||||
+ Add hwloc_obj_set_subtype(). Thanks to Hadrien Grasland for the report.
|
||||
* GPU support
|
||||
+ Don't hide the GPU NUMA node on NVIDIA Grace Hopper.
|
||||
+ Get Intel GPU OpenCL device locality.
|
||||
+ Add bandwidths between subdevices in the LevelZero XeLinkBandwidth
|
||||
matrix.
|
||||
+ Fix PCI Gen4+ link speed of NVIDIA GPU obtained from NVML,
|
||||
thanks to Akram Sbaih for the report.
|
||||
* Windows support
|
||||
+ Fix Windows support when UNICODE is enabled, several hwloc features
|
||||
were missing, thanks to Martin for the report.
|
||||
+ Fix the enabling of CUDA in Windows CMake build,
|
||||
Thanks to Moritz Kreutzer for the patch.
|
||||
+ Fix CUDA/OpenCL test source path in Windows CMake.
|
||||
* Tools
|
||||
+ Option --best-memattr may now return multiple nodes. Additional
|
||||
configuration flags may be given to tweak its behavior.
|
||||
+ hwloc-info has a new --get-attr option to get a single attribute.
|
||||
+ hwloc-info now supports "levels", "support" and "topology"
|
||||
special keywords for backward compatibility for hwloc 3.0.
|
||||
+ The --taskset command-line option is superseded by the new
|
||||
--cpuset-output-format which also allows to export as list.
|
||||
+ hwloc-calc may now import bitmasks described as a list of bits
|
||||
with the new "--cpuset-input-format list".
|
||||
* Misc
|
||||
+ The MemoryTiersNr info attribute in the root object now says how many
|
||||
memory tiers were built. Thanks to Antoine Morvan for the report.
|
||||
+ Fix the management of infinite cpusets in the bitmap printf/sscanf
|
||||
API as well as in command-line tools.
|
||||
+ Add section "Compiling software on top of hwloc's C API" in the
|
||||
documentation with examples for GNU Make and CMake,
|
||||
thanks to Florent Pruvost for the help.
|
||||
|
||||
|
||||
Version 2.10.0
|
||||
--------------
|
||||
* Heterogeneous Memory core improvements
|
||||
+ Better heuristics to identify the subtype of memory such as HBM,
|
||||
DRAM, NVM, CXL-DRAM, etc.
|
||||
+ Build memory tiers, i.e. sets of NUMA nodes with the same subtype
|
||||
and similar performance.
|
||||
- NUMA node tier ranks are exposed in the new MemoryTier info
|
||||
attribute (starts from 0 for highest bandwidth tier)..
|
||||
+ See the new Heterogeneous Memory section in the documentation.
|
||||
* API
|
||||
+ Add hwloc_topology_free_group_object() to discard a Group created
|
||||
by hwloc_topology_alloc_group_object().
|
||||
* Linux backend
|
||||
+ Fix cpukinds on NVIDIA Grace to report identical cores even if they
|
||||
actually have very small frequency differences.
|
||||
Thanks to John C. Linford for the report.
|
||||
+ Add CXLDevice attributes to CXL DAX objects and NUMA nodes to show
|
||||
which PCI device implements which window.
|
||||
+ Ignore buggy memory-side caches and memory attributes when fake NUMA
|
||||
emulation is enabled on the Linux kernel command-line.
|
||||
+ Add more info attributes in MemoryModule Misc objects,
|
||||
thanks to Zubiao Xiong for the patch.
|
||||
+ Get CPUModel and CPUFamily info attributes on LoongArch platforms.
|
||||
* x86 backend
|
||||
+ Add support for new AMD CPUID leaf 0x80000026 for better detection
|
||||
of Core Complex and Die on Zen4 processors.
|
||||
+ Improve Zhaoxin CPU topology detection.
|
||||
* Tools
|
||||
+ Input locations and many command-line options (e.g. hwloc-calc -I -N -H,
|
||||
lstopo --only) now accept filters such as "NUMA[HBM]" so that only
|
||||
objects are that type and subtype are considered.
|
||||
- NUMA[tier=1] is also accepted for selecting NUMA nodes depending
|
||||
on their MemoryTier info attribute.
|
||||
+ Add --object-output to hwloc-calc to report the type as a prefix to
|
||||
object indexes, e.g. Core:2 instead of 2 in the output of -I.
|
||||
+ hwloc-info --ancestor and --descendants now accepts kinds of objects
|
||||
instead of single types.
|
||||
- The new --first option only shows the first matching object.
|
||||
+ Add --children-of-pid to hwloc-ps to show a hierarchy of processes.
|
||||
Thanks to Antoine Morvan for the suggestion.
|
||||
+ Add --misc-from to lstopo to add Misc objects described in a file.
|
||||
- To be combined with the new hwloc-ps --lstopo-misc for a customizable
|
||||
lstopo --top replacement.
|
||||
* Misc
|
||||
+ lstopo may now configure the layout of memory object placed above,
|
||||
for instance with --children-order memory:above:vert.
|
||||
+ Fix XML import from memory or stdin when using libxml2 2.12.
|
||||
+ Fix installation failures when configuring with --target,
|
||||
thanks to Clement Foyer for the patch.
|
||||
+ Fix support for 128bit pointer architectures.
|
||||
+ Remove Netloc.
|
||||
|
||||
|
||||
Version 2.9.3
|
||||
-------------
|
||||
* Handle Linux glibc allocation errors in binding routines (CVE-2022-47022).
|
||||
* Fix hwloc-calc when searching objects on heterogeneous memory platforms,
|
||||
thanks to Antoine Morvan for the report.
|
||||
* Fix hwloc_get_next_child() when there are some memory-side caches.
|
||||
* Don't crash if the topology is empty because Linux cgroups are wrong.
|
||||
* Improve some hwloc-bind warnings in case of command-line parsing errors.
|
||||
* Many documentation improvements all over the place, including:
|
||||
+ hwloc_topology_restrict() and hwloc_topology_insert_group() may reorder
|
||||
children, causing the logical indexes of objects to change.
|
||||
|
||||
|
||||
Version 2.9.2
|
||||
-------------
|
||||
* Don't forget L3i when defining filters for multiple levels of caches
|
||||
with hwloc_topology_set_cache/icache_types_filter().
|
||||
* Fix object total_memory after hwloc_topology_insert_group_object().
|
||||
* Fix the (non-yet) exporting in synthetic description for complex memory
|
||||
hierarchies with memory-side caches, etc.
|
||||
* Fix some default size attributes when building synthetic topologies.
|
||||
* Fix size units in hwloc-annotate.
|
||||
* Improve bitmap reallocation error management in many functions.
|
||||
* Documentation improvements:
|
||||
+ Better document return values of functions.
|
||||
+ Add "Error reporting" section (in hwloc.h and in the doxygen doc).
|
||||
+ Add FAQ entry "What may I disable to make hwloc faster?"
|
||||
+ Improve FAQ entries "Why is lstopo slow?" and
|
||||
"I only need ..., why should I use hwloc?"
|
||||
+ Clarify how to deal with cpukinds in hwloc-calc and hwloc-bind
|
||||
manpages.
|
||||
|
||||
|
||||
Version 2.9.1
|
||||
-------------
|
||||
* Don't forget to apply object type filters to "perflevel" caches detected
|
||||
on recent Mac OS X releases, thanks to Michel Lesoinne for the report.
|
||||
* Fix a failed assertion in hwloc_topology_restrict() when some NUMA nodes
|
||||
are removed because of HWLOC_RESTRICT_FLAG_REMOVE_CPULESS but no PUs are.
|
||||
Thanks to Mark Grondona for reporting the issue.
|
||||
* Mark HPE Cray Slingshot NICs with subtype "Slingshot".
|
||||
|
||||
|
||||
Version 2.9.0
|
||||
-------------
|
||||
* Backends
|
||||
@@ -269,14 +61,6 @@ Version 2.8.0
|
||||
file from the documentation.
|
||||
|
||||
|
||||
Version 2.7.2
|
||||
-------------
|
||||
* Fix a crash when LevelZero devices have multiple subdevices,
|
||||
e.g. on PonteVecchio GPUs, thanks to Jonathan Peyton.
|
||||
* Fix a leak when importing cpukinds from XML,
|
||||
thanks to Hui Zhou.
|
||||
|
||||
|
||||
Version 2.7.1
|
||||
-------------
|
||||
* Workaround crashes when virtual machines report incoherent x86 CPUID
|
||||
|
||||
490
src/3rdparty/hwloc/README
vendored
490
src/3rdparty/hwloc/README
vendored
@@ -1,8 +1,4 @@
|
||||
This is a truncated and poorly-formatted version of the documentation main page.
|
||||
See https://www.open-mpi.org/projects/hwloc/doc/ for more.
|
||||
|
||||
|
||||
hwloc Overview
|
||||
Introduction
|
||||
|
||||
The Hardware Locality (hwloc) software project aims at easing the process of
|
||||
discovering hardware resources in parallel architectures. It offers
|
||||
@@ -12,450 +8,66 @@ high-performance computing (HPC) applications, but is also applicable to any
|
||||
project seeking to exploit code and/or data locality on modern computing
|
||||
platforms.
|
||||
|
||||
hwloc provides command line tools and a C API to obtain the hierarchical map of
|
||||
key computing elements within a node, such as: NUMA memory nodes, shared
|
||||
caches, processor packages, dies and cores, processing units (logical
|
||||
processors or "threads") and even I/O devices. hwloc also gathers various
|
||||
attributes such as cache and memory information, and is portable across a
|
||||
variety of different operating systems and platforms.
|
||||
hwloc is actually made of two subprojects distributed together:
|
||||
|
||||
hwloc primarily aims at helping high-performance computing (HPC) applications,
|
||||
but is also applicable to any project seeking to exploit code and/or data
|
||||
locality on modern computing platforms.
|
||||
* The original hwloc project for describing the internals of computing nodes.
|
||||
It is described in details starting at section Hardware Locality (hwloc)
|
||||
Introduction.
|
||||
* The network-oriented companion called netloc (Network Locality), described
|
||||
in details starting with section Network Locality (netloc).
|
||||
|
||||
hwloc supports the following operating systems:
|
||||
See also the Related pages tab above for links to other sections.
|
||||
|
||||
* Linux (with knowledge of cgroups and cpusets, memory targets/initiators,
|
||||
etc.) on all supported hardware, including Intel Xeon Phi, ScaleMP vSMP,
|
||||
and NumaScale NumaConnect.
|
||||
* Solaris (with support for processor sets and logical domains)
|
||||
* AIX
|
||||
* Darwin / OS X
|
||||
* FreeBSD and its variants (such as kFreeBSD/GNU)
|
||||
* NetBSD
|
||||
* HP-UX
|
||||
* Microsoft Windows
|
||||
* IBM BlueGene/Q Compute Node Kernel (CNK)
|
||||
Netloc may be disabled, but the original hwloc cannot. Both hwloc and netloc
|
||||
APIs are documented after these sections.
|
||||
|
||||
Since it uses standard Operating System information, hwloc's support is mostly
|
||||
independant from the processor type (x86, powerpc, ...) and just relies on the
|
||||
Operating System support. The main exception is BSD operating systems (NetBSD,
|
||||
FreeBSD, etc.) because they do not provide support topology information, hence
|
||||
hwloc uses an x86-only CPUID-based backend (which can be used for other OSes
|
||||
too, see the Components and plugins section).
|
||||
Installation
|
||||
|
||||
To check whether hwloc works on a particular machine, just try to build it and
|
||||
run lstopo or lstopo-no-graphics. If some things do not look right (e.g. bogus
|
||||
or missing cache information), see Questions and Bugs.
|
||||
hwloc (https://www.open-mpi.org/projects/hwloc/) is available under the BSD
|
||||
license. It is hosted as a sub-project of the overall Open MPI project (https:/
|
||||
/www.open-mpi.org/). Note that hwloc does not require any functionality from
|
||||
Open MPI -- it is a wholly separate (and much smaller!) project and code base.
|
||||
It just happens to be hosted as part of the overall Open MPI project.
|
||||
|
||||
hwloc only reports the number of processors on unsupported operating systems;
|
||||
no topology information is available.
|
||||
Basic Installation
|
||||
|
||||
For development and debugging purposes, hwloc also offers the ability to work
|
||||
on "fake" topologies:
|
||||
Installation is the fairly common GNU-based process:
|
||||
|
||||
* Symmetrical tree of resources generated from a list of level arities, see
|
||||
Synthetic topologies.
|
||||
* Remote machine simulation through the gathering of topology as XML files,
|
||||
see Importing and exporting topologies from/to XML files.
|
||||
shell$ ./configure --prefix=...
|
||||
shell$ make
|
||||
shell$ make install
|
||||
|
||||
hwloc can display the topology in a human-readable format, either in graphical
|
||||
mode (X11), or by exporting in one of several different formats, including:
|
||||
plain text, LaTeX tikzpicture, PDF, PNG, and FIG (see Command-line Examples
|
||||
below). Note that some of the export formats require additional support
|
||||
libraries.
|
||||
hwloc- and netloc-specific configure options and requirements are documented in
|
||||
sections hwloc Installation and Netloc Installation respectively.
|
||||
|
||||
hwloc offers a programming interface for manipulating topologies and objects.
|
||||
It also brings a powerful CPU bitmap API that is used to describe topology
|
||||
objects location on physical/logical processors. See the Programming Interface
|
||||
below. It may also be used to binding applications onto certain cores or memory
|
||||
nodes. Several utility programs are also provided to ease command-line
|
||||
manipulation of topology objects, binding of processes, and so on.
|
||||
Also note that if you install supplemental libraries in non-standard locations,
|
||||
hwloc's configure script may not be able to find them without some help. You
|
||||
may need to specify additional CPPFLAGS, LDFLAGS, or PKG_CONFIG_PATH values on
|
||||
the configure command line.
|
||||
|
||||
Bindings for several other languages are available from the project website.
|
||||
For example, if libpciaccess was installed into /opt/pciaccess, hwloc's
|
||||
configure script may not find it be default. Try adding PKG_CONFIG_PATH to the
|
||||
./configure command line, like this:
|
||||
|
||||
Command-line Examples
|
||||
./configure PKG_CONFIG_PATH=/opt/pciaccess/lib/pkgconfig ...
|
||||
|
||||
On a 4-package 2-core machine with hyper-threading, the lstopo tool may show
|
||||
the following graphical output:
|
||||
Running the "lstopo" tool is a good way to check as a graphical output whether
|
||||
hwloc properly detected the architecture of your node. Netloc command-line
|
||||
tools can be used to display the network topology interconnecting your nodes.
|
||||
|
||||
[dudley]
|
||||
Installing from a Git clone
|
||||
|
||||
Here's the equivalent output in textual form:
|
||||
Additionally, the code can be directly cloned from Git:
|
||||
|
||||
Machine
|
||||
NUMANode L#0 (P#0)
|
||||
Package L#0 + L3 L#0 (4096KB)
|
||||
L2 L#0 (1024KB) + L1 L#0 (16KB) + Core L#0
|
||||
PU L#0 (P#0)
|
||||
PU L#1 (P#8)
|
||||
L2 L#1 (1024KB) + L1 L#1 (16KB) + Core L#1
|
||||
PU L#2 (P#4)
|
||||
PU L#3 (P#12)
|
||||
Package L#1 + L3 L#1 (4096KB)
|
||||
L2 L#2 (1024KB) + L1 L#2 (16KB) + Core L#2
|
||||
PU L#4 (P#1)
|
||||
PU L#5 (P#9)
|
||||
L2 L#3 (1024KB) + L1 L#3 (16KB) + Core L#3
|
||||
PU L#6 (P#5)
|
||||
PU L#7 (P#13)
|
||||
Package L#2 + L3 L#2 (4096KB)
|
||||
L2 L#4 (1024KB) + L1 L#4 (16KB) + Core L#4
|
||||
PU L#8 (P#2)
|
||||
PU L#9 (P#10)
|
||||
L2 L#5 (1024KB) + L1 L#5 (16KB) + Core L#5
|
||||
PU L#10 (P#6)
|
||||
PU L#11 (P#14)
|
||||
Package L#3 + L3 L#3 (4096KB)
|
||||
L2 L#6 (1024KB) + L1 L#6 (16KB) + Core L#6
|
||||
PU L#12 (P#3)
|
||||
PU L#13 (P#11)
|
||||
L2 L#7 (1024KB) + L1 L#7 (16KB) + Core L#7
|
||||
PU L#14 (P#7)
|
||||
PU L#15 (P#15)
|
||||
shell$ git clone https://github.com/open-mpi/hwloc.git
|
||||
shell$ cd hwloc
|
||||
shell$ ./autogen.sh
|
||||
|
||||
Note that there is also an equivalent output in XML that is meant for exporting
|
||||
/importing topologies but it is hardly readable to human-beings (see Importing
|
||||
and exporting topologies from/to XML files for details).
|
||||
Note that GNU Autoconf >=2.63, Automake >=1.11 and Libtool >=2.2.6 are required
|
||||
when building from a Git clone.
|
||||
|
||||
On a 4-package 2-core Opteron NUMA machine (with two core cores disallowed by
|
||||
the administrator), the lstopo tool may show the following graphical output
|
||||
(with --disallowed for displaying disallowed objects):
|
||||
|
||||
[hagrid]
|
||||
|
||||
Here's the equivalent output in textual form:
|
||||
|
||||
Machine (32GB total)
|
||||
Package L#0
|
||||
NUMANode L#0 (P#0 8190MB)
|
||||
L2 L#0 (1024KB) + L1 L#0 (64KB) + Core L#0 + PU L#0 (P#0)
|
||||
L2 L#1 (1024KB) + L1 L#1 (64KB) + Core L#1 + PU L#1 (P#1)
|
||||
Package L#1
|
||||
NUMANode L#1 (P#1 8192MB)
|
||||
L2 L#2 (1024KB) + L1 L#2 (64KB) + Core L#2 + PU L#2 (P#2)
|
||||
L2 L#3 (1024KB) + L1 L#3 (64KB) + Core L#3 + PU L#3 (P#3)
|
||||
Package L#2
|
||||
NUMANode L#2 (P#2 8192MB)
|
||||
L2 L#4 (1024KB) + L1 L#4 (64KB) + Core L#4 + PU L#4 (P#4)
|
||||
L2 L#5 (1024KB) + L1 L#5 (64KB) + Core L#5 + PU L#5 (P#5)
|
||||
Package L#3
|
||||
NUMANode L#3 (P#3 8192MB)
|
||||
L2 L#6 (1024KB) + L1 L#6 (64KB) + Core L#6 + PU L#6 (P#6)
|
||||
L2 L#7 (1024KB) + L1 L#7 (64KB) + Core L#7 + PU L#7 (P#7)
|
||||
|
||||
On a 2-package quad-core Xeon (pre-Nehalem, with 2 dual-core dies into each
|
||||
package):
|
||||
|
||||
[emmett]
|
||||
|
||||
Here's the same output in textual form:
|
||||
|
||||
Machine (total 16GB)
|
||||
NUMANode L#0 (P#0 16GB)
|
||||
Package L#0
|
||||
L2 L#0 (4096KB)
|
||||
L1 L#0 (32KB) + Core L#0 + PU L#0 (P#0)
|
||||
L1 L#1 (32KB) + Core L#1 + PU L#1 (P#4)
|
||||
L2 L#1 (4096KB)
|
||||
L1 L#2 (32KB) + Core L#2 + PU L#2 (P#2)
|
||||
L1 L#3 (32KB) + Core L#3 + PU L#3 (P#6)
|
||||
Package L#1
|
||||
L2 L#2 (4096KB)
|
||||
L1 L#4 (32KB) + Core L#4 + PU L#4 (P#1)
|
||||
L1 L#5 (32KB) + Core L#5 + PU L#5 (P#5)
|
||||
L2 L#3 (4096KB)
|
||||
L1 L#6 (32KB) + Core L#6 + PU L#6 (P#3)
|
||||
L1 L#7 (32KB) + Core L#7 + PU L#7 (P#7)
|
||||
|
||||
Programming Interface
|
||||
|
||||
The basic interface is available in hwloc.h. Some higher-level functions are
|
||||
available in hwloc/helper.h to reduce the need to manually manipulate objects
|
||||
and follow links between them. Documentation for all these is provided later in
|
||||
this document. Developers may also want to look at hwloc/inlines.h which
|
||||
contains the actual inline code of some hwloc.h routines, and at this document,
|
||||
which provides good higher-level topology traversal examples.
|
||||
|
||||
To precisely define the vocabulary used by hwloc, a Terms and Definitions
|
||||
section is available and should probably be read first.
|
||||
|
||||
Each hwloc object contains a cpuset describing the list of processing units
|
||||
that it contains. These bitmaps may be used for CPU binding and Memory binding.
|
||||
hwloc offers an extensive bitmap manipulation interface in hwloc/bitmap.h.
|
||||
|
||||
Moreover, hwloc also comes with additional helpers for interoperability with
|
||||
several commonly used environments. See the Interoperability With Other
|
||||
Software section for details.
|
||||
|
||||
The complete API documentation is available in a full set of HTML pages, man
|
||||
pages, and self-contained PDF files (formatted for both both US letter and A4
|
||||
formats) in the source tarball in doc/doxygen-doc/.
|
||||
|
||||
NOTE: If you are building the documentation from a Git clone, you will need to
|
||||
have Doxygen and pdflatex installed -- the documentation will be built during
|
||||
the normal "make" process. The documentation is installed during "make install"
|
||||
to $prefix/share/doc/hwloc/ and your systems default man page tree (under
|
||||
$prefix, of course).
|
||||
|
||||
Portability
|
||||
|
||||
Operating System have varying support for CPU and memory binding, e.g. while
|
||||
some Operating Systems provide interfaces for all kinds of CPU and memory
|
||||
bindings, some others provide only interfaces for a limited number of kinds of
|
||||
CPU and memory binding, and some do not provide any binding interface at all.
|
||||
Hwloc's binding functions would then simply return the ENOSYS error (Function
|
||||
not implemented), meaning that the underlying Operating System does not provide
|
||||
any interface for them. CPU binding and Memory binding provide more information
|
||||
on which hwloc binding functions should be preferred because interfaces for
|
||||
them are usually available on the supported Operating Systems.
|
||||
|
||||
Similarly, the ability of reporting topology information varies from one
|
||||
platform to another. As shown in Command-line Examples, hwloc can obtain
|
||||
information on a wide variety of hardware topologies. However, some platforms
|
||||
and/or operating system versions will only report a subset of this information.
|
||||
For example, on an PPC64-based system with 8 cores (each with 2 hardware
|
||||
threads) running a default 2.6.18-based kernel from RHEL 5.4, hwloc is only
|
||||
able to glean information about NUMA nodes and processor units (PUs). No
|
||||
information about caches, packages, or cores is available.
|
||||
|
||||
Here's the graphical output from lstopo on this platform when Simultaneous
|
||||
Multi-Threading (SMT) is enabled:
|
||||
|
||||
[ppc64-with]
|
||||
|
||||
And here's the graphical output from lstopo on this platform when SMT is
|
||||
disabled:
|
||||
|
||||
[ppc64-with]
|
||||
|
||||
Notice that hwloc only sees half the PUs when SMT is disabled. PU L#6, for
|
||||
example, seems to change location from NUMA node #0 to #1. In reality, no PUs
|
||||
"moved" -- they were simply re-numbered when hwloc only saw half as many (see
|
||||
also Logical index in Indexes and Sets). Hence, PU L#6 in the SMT-disabled
|
||||
picture probably corresponds to PU L#12 in the SMT-enabled picture.
|
||||
|
||||
This same "PUs have disappeared" effect can be seen on other platforms -- even
|
||||
platforms / OSs that provide much more information than the above PPC64 system.
|
||||
This is an unfortunate side-effect of how operating systems report information
|
||||
to hwloc.
|
||||
|
||||
Note that upgrading the Linux kernel on the same PPC64 system mentioned above
|
||||
to 2.6.34, hwloc is able to discover all the topology information. The
|
||||
following picture shows the entire topology layout when SMT is enabled:
|
||||
|
||||
[ppc64-full]
|
||||
|
||||
Developers using the hwloc API or XML output for portable applications should
|
||||
therefore be extremely careful to not make any assumptions about the structure
|
||||
of data that is returned. For example, per the above reported PPC topology, it
|
||||
is not safe to assume that PUs will always be descendants of cores.
|
||||
|
||||
Additionally, future hardware may insert new topology elements that are not
|
||||
available in this version of hwloc. Long-lived applications that are meant to
|
||||
span multiple different hardware platforms should also be careful about making
|
||||
structure assumptions. For example, a new element may someday exist between a
|
||||
core and a PU.
|
||||
|
||||
API Example
|
||||
|
||||
The following small C example (available in the source tree as ``doc/examples/
|
||||
hwloc-hello.c'') prints the topology of the machine and performs some thread
|
||||
and memory binding. More examples are available in the doc/examples/ directory
|
||||
of the source tree.
|
||||
|
||||
/* Example hwloc API program.
|
||||
*
|
||||
* See other examples under doc/examples/ in the source tree
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (c) 2009-2016 Inria. All rights reserved.
|
||||
* Copyright (c) 2009-2011 Universit?eacute; Bordeaux
|
||||
* Copyright (c) 2009-2010 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*
|
||||
* hwloc-hello.c
|
||||
*/
|
||||
#include "hwloc.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
static void print_children(hwloc_topology_t topology, hwloc_obj_t obj,
|
||||
int depth)
|
||||
{
|
||||
char type[32], attr[1024];
|
||||
unsigned i;
|
||||
hwloc_obj_type_snprintf(type, sizeof(type), obj, 0);
|
||||
printf("%*s%s", 2*depth, "", type);
|
||||
if (obj->os_index != (unsigned) -1)
|
||||
printf("#%u", obj->os_index);
|
||||
hwloc_obj_attr_snprintf(attr, sizeof(attr), obj, " ", 0);
|
||||
if (*attr)
|
||||
printf("(%s)", attr);
|
||||
printf("\n");
|
||||
for (i = 0; i < obj->arity; i++) {
|
||||
print_children(topology, obj->children[i], depth + 1);
|
||||
}
|
||||
}
|
||||
int main(void)
|
||||
{
|
||||
int depth;
|
||||
unsigned i, n;
|
||||
unsigned long size;
|
||||
int levels;
|
||||
char string[128];
|
||||
int topodepth;
|
||||
void *m;
|
||||
hwloc_topology_t topology;
|
||||
hwloc_cpuset_t cpuset;
|
||||
hwloc_obj_t obj;
|
||||
/* Allocate and initialize topology object. */
|
||||
hwloc_topology_init(&topology);
|
||||
/* ... Optionally, put detection configuration here to ignore
|
||||
some objects types, define a synthetic topology, etc....
|
||||
The default is to detect all the objects of the machine that
|
||||
the caller is allowed to access. See Configure Topology
|
||||
Detection. */
|
||||
/* Perform the topology detection. */
|
||||
hwloc_topology_load(topology);
|
||||
/* Optionally, get some additional topology information
|
||||
in case we need the topology depth later. */
|
||||
topodepth = hwloc_topology_get_depth(topology);
|
||||
/*****************************************************************
|
||||
* First example:
|
||||
* Walk the topology with an array style, from level 0 (always
|
||||
* the system level) to the lowest level (always the proc level).
|
||||
*****************************************************************/
|
||||
for (depth = 0; depth < topodepth; depth++) {
|
||||
printf("*** Objects at level %d\n", depth);
|
||||
for (i = 0; i < hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
i++) {
|
||||
hwloc_obj_type_snprintf(string, sizeof(string),
|
||||
hwloc_get_obj_by_depth(topology, depth, i), 0);
|
||||
printf("Index %u: %s\n", i, string);
|
||||
}
|
||||
}
|
||||
/*****************************************************************
|
||||
* Second example:
|
||||
* Walk the topology with a tree style.
|
||||
*****************************************************************/
|
||||
printf("*** Printing overall tree\n");
|
||||
print_children(topology, hwloc_get_root_obj(topology), 0);
|
||||
/*****************************************************************
|
||||
* Third example:
|
||||
* Print the number of packages.
|
||||
*****************************************************************/
|
||||
depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PACKAGE);
|
||||
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN) {
|
||||
printf("*** The number of packages is unknown\n");
|
||||
} else {
|
||||
printf("*** %u package(s)\n",
|
||||
hwloc_get_nbobjs_by_depth(topology, depth));
|
||||
}
|
||||
/*****************************************************************
|
||||
* Fourth example:
|
||||
* Compute the amount of cache that the first logical processor
|
||||
* has above it.
|
||||
*****************************************************************/
|
||||
levels = 0;
|
||||
size = 0;
|
||||
for (obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 0);
|
||||
obj;
|
||||
obj = obj->parent)
|
||||
if (hwloc_obj_type_is_cache(obj->type)) {
|
||||
levels++;
|
||||
size += obj->attr->cache.size;
|
||||
}
|
||||
printf("*** Logical processor 0 has %d caches totaling %luKB\n",
|
||||
levels, size / 1024);
|
||||
/*****************************************************************
|
||||
* Fifth example:
|
||||
* Bind to only one thread of the last core of the machine.
|
||||
*
|
||||
* First find out where cores are, or else smaller sets of CPUs if
|
||||
* the OS doesn't have the notion of a "core".
|
||||
*****************************************************************/
|
||||
depth = hwloc_get_type_or_below_depth(topology, HWLOC_OBJ_CORE);
|
||||
/* Get last core. */
|
||||
obj = hwloc_get_obj_by_depth(topology, depth,
|
||||
hwloc_get_nbobjs_by_depth(topology, depth) - 1);
|
||||
if (obj) {
|
||||
/* Get a copy of its cpuset that we may modify. */
|
||||
cpuset = hwloc_bitmap_dup(obj->cpuset);
|
||||
/* Get only one logical processor (in case the core is
|
||||
SMT/hyper-threaded). */
|
||||
hwloc_bitmap_singlify(cpuset);
|
||||
/* And try to bind ourself there. */
|
||||
if (hwloc_set_cpubind(topology, cpuset, 0)) {
|
||||
char *str;
|
||||
int error = errno;
|
||||
hwloc_bitmap_asprintf(&str, obj->cpuset);
|
||||
printf("Couldn't bind to cpuset %s: %s\n", str, strerror(error));
|
||||
free(str);
|
||||
}
|
||||
/* Free our cpuset copy */
|
||||
hwloc_bitmap_free(cpuset);
|
||||
}
|
||||
/*****************************************************************
|
||||
* Sixth example:
|
||||
* Allocate some memory on the last NUMA node, bind some existing
|
||||
* memory to the last NUMA node.
|
||||
*****************************************************************/
|
||||
/* Get last node. There's always at least one. */
|
||||
n = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_NUMANODE);
|
||||
obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, n - 1);
|
||||
size = 1024*1024;
|
||||
m = hwloc_alloc_membind(topology, size, obj->nodeset,
|
||||
HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_BYNODESET);
|
||||
hwloc_free(topology, m, size);
|
||||
m = malloc(size);
|
||||
hwloc_set_area_membind(topology, m, size, obj->nodeset,
|
||||
HWLOC_MEMBIND_BIND, HWLOC_MEMBIND_BYNODESET);
|
||||
free(m);
|
||||
/* Destroy topology object. */
|
||||
hwloc_topology_destroy(topology);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hwloc provides a pkg-config executable to obtain relevant compiler and linker
|
||||
flags. See Compiling software on top of hwloc's C API for details on building
|
||||
program on top of hwloc's API using GNU Make or CMake.
|
||||
|
||||
On a machine 2 processor packages -- each package of which has two processing
|
||||
cores -- the output from running hwloc-hello could be something like the
|
||||
following:
|
||||
|
||||
shell$ ./hwloc-hello
|
||||
*** Objects at level 0
|
||||
Index 0: Machine
|
||||
*** Objects at level 1
|
||||
Index 0: Package#0
|
||||
Index 1: Package#1
|
||||
*** Objects at level 2
|
||||
Index 0: Core#0
|
||||
Index 1: Core#1
|
||||
Index 2: Core#3
|
||||
Index 3: Core#2
|
||||
*** Objects at level 3
|
||||
Index 0: PU#0
|
||||
Index 1: PU#1
|
||||
Index 2: PU#2
|
||||
Index 3: PU#3
|
||||
*** Printing overall tree
|
||||
Machine
|
||||
Package#0
|
||||
Core#0
|
||||
PU#0
|
||||
Core#1
|
||||
PU#1
|
||||
Package#1
|
||||
Core#3
|
||||
PU#2
|
||||
Core#2
|
||||
PU#3
|
||||
*** 2 package(s)
|
||||
*** Logical processor 0 has 0 caches totaling 0KB
|
||||
shell$
|
||||
Nightly development snapshots are available on the web site, they can be
|
||||
configured and built without any need for Git or GNU Autotools.
|
||||
|
||||
Questions and Bugs
|
||||
|
||||
@@ -468,20 +80,6 @@ www.open-mpi.org/community/lists/hwloc.php).
|
||||
|
||||
There is also a #hwloc IRC channel on Libera Chat (irc.libera.chat).
|
||||
|
||||
History / Credits
|
||||
|
||||
hwloc is the evolution and merger of the libtopology project and the Portable
|
||||
Linux Processor Affinity (PLPA) (https://www.open-mpi.org/projects/plpa/)
|
||||
project. Because of functional and ideological overlap, these two code bases
|
||||
and ideas were merged and released under the name "hwloc" as an Open MPI
|
||||
sub-project.
|
||||
|
||||
libtopology was initially developed by the Inria Runtime Team-Project. PLPA was
|
||||
initially developed by the Open MPI development team as a sub-project. Both are
|
||||
now deprecated in favor of hwloc, which is distributed as an Open MPI
|
||||
sub-project.
|
||||
|
||||
|
||||
|
||||
See https://www.open-mpi.org/projects/hwloc/doc/ for more hwloc documentation,
|
||||
actual links to related pages, images, etc.
|
||||
See https://www.open-mpi.org/projects/hwloc/doc/ for more hwloc documentation.
|
||||
|
||||
9
src/3rdparty/hwloc/VERSION
vendored
9
src/3rdparty/hwloc/VERSION
vendored
@@ -8,8 +8,8 @@
|
||||
# Please update HWLOC_VERSION* in contrib/windows/hwloc_config.h too.
|
||||
|
||||
major=2
|
||||
minor=12
|
||||
release=1
|
||||
minor=9
|
||||
release=0
|
||||
|
||||
# greek is used for alpha or beta release tags. If it is non-empty,
|
||||
# it will be appended to the version number. It does not have to be
|
||||
@@ -22,7 +22,7 @@ greek=
|
||||
|
||||
# The date when this release was created
|
||||
|
||||
date="May 12, 2025"
|
||||
date="Dec 14, 2022"
|
||||
|
||||
# If snapshot=1, then use the value from snapshot_version as the
|
||||
# entire hwloc version (i.e., ignore major, minor, release, and
|
||||
@@ -41,6 +41,7 @@ snapshot_version=${major}.${minor}.${release}${greek}-git
|
||||
# 2. Version numbers are described in the Libtool current:revision:age
|
||||
# format.
|
||||
|
||||
libhwloc_so_version=25:0:10
|
||||
libhwloc_so_version=21:1:6
|
||||
libnetloc_so_version=0:0:0
|
||||
|
||||
# Please also update the <TargetName> lines in contrib/windows/libhwloc.vcxproj
|
||||
|
||||
486
src/3rdparty/hwloc/include/hwloc.h
vendored
486
src/3rdparty/hwloc/include/hwloc.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2025 Inria. All rights reserved.
|
||||
* Copyright © 2009-2022 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -11,10 +11,10 @@
|
||||
#ifndef HWLOC_CONFIG_H
|
||||
#define HWLOC_CONFIG_H
|
||||
|
||||
#define HWLOC_VERSION "2.12.1"
|
||||
#define HWLOC_VERSION "2.9.0"
|
||||
#define HWLOC_VERSION_MAJOR 2
|
||||
#define HWLOC_VERSION_MINOR 12
|
||||
#define HWLOC_VERSION_RELEASE 1
|
||||
#define HWLOC_VERSION_MINOR 9
|
||||
#define HWLOC_VERSION_RELEASE 0
|
||||
#define HWLOC_VERSION_GREEK ""
|
||||
|
||||
#define __hwloc_restrict
|
||||
|
||||
122
src/3rdparty/hwloc/include/hwloc/bitmap.h
vendored
122
src/3rdparty/hwloc/include/hwloc/bitmap.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2024 Inria. All rights reserved.
|
||||
* Copyright © 2009-2022 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -50,10 +50,9 @@ extern "C" {
|
||||
* hwloc_bitmap_free(set);
|
||||
* \endcode
|
||||
*
|
||||
* \note Most functions below return 0 on success and -1 on error.
|
||||
* The usual error case would be an internal failure to realloc/extend
|
||||
* \note Most functions below return an int that may be negative in case of
|
||||
* error. The usual error case would be an internal failure to realloc/extend
|
||||
* the storage of the bitmap (\p errno would be set to \c ENOMEM).
|
||||
* See also \ref hwlocality_api_error_reporting.
|
||||
*
|
||||
* \note Several examples of using the bitmap API are available under the
|
||||
* doc/examples/ directory in the source tree.
|
||||
@@ -84,13 +83,7 @@ typedef const struct hwloc_bitmap_s * hwloc_const_bitmap_t;
|
||||
*/
|
||||
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_alloc(void) __hwloc_attribute_malloc;
|
||||
|
||||
/** \brief Allocate a new full bitmap.
|
||||
*
|
||||
* \returns A valid bitmap or \c NULL.
|
||||
*
|
||||
* The bitmap should be freed by a corresponding call to
|
||||
* hwloc_bitmap_free().
|
||||
*/
|
||||
/** \brief Allocate a new full bitmap. */
|
||||
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_alloc_full(void) __hwloc_attribute_malloc;
|
||||
|
||||
/** \brief Free bitmap \p bitmap.
|
||||
@@ -113,134 +106,73 @@ HWLOC_DECLSPEC int hwloc_bitmap_copy(hwloc_bitmap_t dst, hwloc_const_bitmap_t sr
|
||||
* Bitmap/String Conversion
|
||||
*/
|
||||
|
||||
/** \brief Stringify a bitmap in the default hwloc format.
|
||||
*
|
||||
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
|
||||
*
|
||||
* Print the bits set inside a bitmap as a comma-separated list of hexadecimal 32-bit blocks.
|
||||
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"0xffffffff,0x00000006,0x00000002"</tt>.
|
||||
/** \brief Stringify a bitmap.
|
||||
*
|
||||
* Up to \p buflen characters may be written in buffer \p buf.
|
||||
*
|
||||
* If \p buflen is 0, \p buf may safely be \c NULL.
|
||||
*
|
||||
* \return the number of characters that were actually written if not truncating,
|
||||
* or that would have been written (not including the ending \c \0).
|
||||
* \return -1 on error.
|
||||
* or that would have been written (not including the ending \\0).
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Stringify a bitmap into a newly allocated string in the default hwloc format.
|
||||
/** \brief Stringify a bitmap into a newly allocated string.
|
||||
*
|
||||
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
|
||||
*
|
||||
* Print the bits set inside a bitmap as a comma-separated list of hexadecimal 32-bit blocks.
|
||||
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"0xffffffff,0x00000006,0x00000002"</tt>.
|
||||
*
|
||||
* \return the number of characters that were written (not including the ending \c \0).
|
||||
* \return -1 on error, for instance with \p errno set to \c ENOMEM on failure to allocate the output string.
|
||||
* \return -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Parse a bitmap string as the default hwloc format and stores it in bitmap \p bitmap.
|
||||
*
|
||||
* <b>Note that if the bitmap is a CPU or nodeset, the input string must contain physical indexes.</b>
|
||||
*
|
||||
* The input string should be a comma-separared list of hexadecimal 32-bit blocks.
|
||||
* String <tt>"0xffffffff,0x6,0x2"</tt> is parsed as a bitmap containing all bits between 64 and 95,
|
||||
* and bits 33, 34 and 1.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
/** \brief Parse a bitmap string and stores it in bitmap \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
|
||||
|
||||
/** \brief Stringify a bitmap in the list format.
|
||||
*
|
||||
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
|
||||
*
|
||||
* Lists are comma-separated indexes or ranges.
|
||||
* Ranges are dash separated indexes.
|
||||
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"1,33-34,64-95"</tt>.
|
||||
* The last range may not have an ending index if the bitmap is infinitely set.
|
||||
* The last range may not have an ending indexes if the bitmap is infinitely set.
|
||||
*
|
||||
* Up to \p buflen characters may be written in buffer \p buf.
|
||||
*
|
||||
* If \p buflen is 0, \p buf may safely be \c NULL.
|
||||
*
|
||||
* \return the number of characters that were actually written if not truncating,
|
||||
* or that would have been written (not including the ending \c \0).
|
||||
* \return -1 on error.
|
||||
* or that would have been written (not including the ending \\0).
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_list_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Stringify a bitmap into a newly allocated list string.
|
||||
*
|
||||
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
|
||||
*
|
||||
* Lists are comma-separated indexes or ranges.
|
||||
* Ranges are dash separated indexes.
|
||||
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"1,33-34,64-95"</tt>.
|
||||
* The last range may not have an ending index if the bitmap is infinitely set.
|
||||
*
|
||||
* \return the number of characters that were written (not including the ending \c \0).
|
||||
* \return -1 on error, for instance with \p errno set to \c ENOMEM on failure to allocate the output string.
|
||||
* \return -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_list_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Parse a list string and stores it in bitmap \p bitmap.
|
||||
*
|
||||
* <b>Note that if the bitmap is a CPU or nodeset, the input string must contain physical indexes.</b>
|
||||
*
|
||||
* Lists are comma-separated indexes or ranges.
|
||||
* Ranges are dash separated indexes.
|
||||
* String <tt>"1,33-34,64-95"</tt> is parsed as a bitmap containing bits 1, 33, 34, and all from 64 to 95.
|
||||
* The last range may not have an ending index if the bitmap is infinitely set.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_list_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
|
||||
|
||||
/** \brief Stringify a bitmap in the taskset-specific format.
|
||||
*
|
||||
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
|
||||
*
|
||||
* The taskset program manipulates bitmap strings that contain a single
|
||||
* The taskset command manipulates bitmap strings that contain a single
|
||||
* (possible very long) hexadecimal number starting with 0x.
|
||||
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as </tt>"0xffffffff0000000600000002"</tt>.
|
||||
*
|
||||
* Up to \p buflen characters may be written in buffer \p buf.
|
||||
*
|
||||
* If \p buflen is 0, \p buf may safely be \c NULL.
|
||||
*
|
||||
* \return the number of characters that were actually written if not truncating,
|
||||
* or that would have been written (not including the ending \c \0).
|
||||
* \return -1 on error.
|
||||
* or that would have been written (not including the ending \\0).
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Stringify a bitmap into a newly allocated taskset-specific string.
|
||||
*
|
||||
* <b>Note that if the bitmap is a CPU or nodeset, it contains physical indexes.</b>
|
||||
*
|
||||
* The taskset program manipulates bitmap strings that contain a single
|
||||
* (possible very long) hexadecimal number starting with 0x.
|
||||
* A bitmap containing bits 1, 33, 34, and all from 64 to 95 is printed as <tt>"0xffffffff0000000600000002"</tt>.
|
||||
*
|
||||
* \return the number of characters that were written (not including the ending \c \0).
|
||||
* \return -1 on error, for instance with \p errno set to \c ENOMEM on failure to allocate the output string.
|
||||
* \return -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_taskset_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Parse a taskset-specific bitmap string and stores it in bitmap \p bitmap.
|
||||
*
|
||||
* <b>Note that if the bitmap is a CPU or nodeset, the input string must contain physical indexes.</b>
|
||||
*
|
||||
* The taskset program manipulates bitmap strings that contain a single
|
||||
* (possible very long) hexadecimal number starting with 0x.
|
||||
* String <tt>"0xffffffff0000000600000002"</tt> is parsed as a bitmap containing all bits between 64 and 95,
|
||||
* and bits 33, 34 and 1.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_taskset_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
|
||||
|
||||
@@ -347,7 +279,6 @@ HWLOC_DECLSPEC int hwloc_bitmap_to_ulongs(hwloc_const_bitmap_t bitmap, unsigned
|
||||
* When called on the output of hwloc_topology_get_topology_cpuset(),
|
||||
* the returned number is large enough for all cpusets of the topology.
|
||||
*
|
||||
* \return the number of unsigned longs required.
|
||||
* \return -1 if \p bitmap is infinite.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_nr_ulongs(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
@@ -374,23 +305,21 @@ HWLOC_DECLSPEC int hwloc_bitmap_isfull(hwloc_const_bitmap_t bitmap) __hwloc_attr
|
||||
|
||||
/** \brief Compute the first index (least significant bit) in bitmap \p bitmap
|
||||
*
|
||||
* \return the first index set in \p bitmap.
|
||||
* \return -1 if \p bitmap is empty.
|
||||
* \return -1 if no index is set in \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_first(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compute the next index in bitmap \p bitmap which is after index \p prev
|
||||
*
|
||||
* \return the first index set in \p bitmap if \p prev is \c -1.
|
||||
* \return the next index set in \p bitmap if \p prev is not \c -1.
|
||||
* If \p prev is -1, the first index is returned.
|
||||
*
|
||||
* \return -1 if no index with higher index is set in \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_next(hwloc_const_bitmap_t bitmap, int prev) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compute the last index (most significant bit) in bitmap \p bitmap
|
||||
*
|
||||
* \return the last index set in \p bitmap.
|
||||
* \return -1 if \p bitmap is empty, or if \p bitmap is infinitely set.
|
||||
* \return -1 if no index is set in \p bitmap, or if \p bitmap is infinitely set.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_last(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
@@ -398,29 +327,28 @@ HWLOC_DECLSPEC int hwloc_bitmap_last(hwloc_const_bitmap_t bitmap) __hwloc_attrib
|
||||
* indexes that are in the bitmap).
|
||||
*
|
||||
* \return the number of indexes that are in the bitmap.
|
||||
*
|
||||
* \return -1 if \p bitmap is infinitely set.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_weight(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compute the first unset index (least significant bit) in bitmap \p bitmap
|
||||
*
|
||||
* \return the first unset index in \p bitmap.
|
||||
* \return -1 if \p bitmap is full.
|
||||
* \return -1 if no index is unset in \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_first_unset(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compute the next unset index in bitmap \p bitmap which is after index \p prev
|
||||
*
|
||||
* \return the first index unset in \p bitmap if \p prev is \c -1.
|
||||
* \return the next index unset in \p bitmap if \p prev is not \c -1.
|
||||
* If \p prev is -1, the first unset index is returned.
|
||||
*
|
||||
* \return -1 if no index with higher index is unset in \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_next_unset(hwloc_const_bitmap_t bitmap, int prev) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compute the last unset index (most significant bit) in bitmap \p bitmap
|
||||
*
|
||||
* \return the last index unset in \p bitmap.
|
||||
* \return -1 if \p bitmap is full, or if \p bitmap is not infinitely set.
|
||||
* \return -1 if no index is unset in \p bitmap, or if \p bitmap is infinitely set.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_last_unset(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
@@ -500,8 +428,6 @@ HWLOC_DECLSPEC int hwloc_bitmap_not (hwloc_bitmap_t res, hwloc_const_bitmap_t bi
|
||||
/** \brief Test whether bitmaps \p bitmap1 and \p bitmap2 intersects.
|
||||
*
|
||||
* \return 1 if bitmaps intersect, 0 otherwise.
|
||||
*
|
||||
* \note The empty bitmap does not intersect any other bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_intersects (hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
|
||||
|
||||
|
||||
8
src/3rdparty/hwloc/include/hwloc/cuda.h
vendored
8
src/3rdparty/hwloc/include/hwloc/cuda.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2010-2023 Inria. All rights reserved.
|
||||
* Copyright © 2010-2021 Inria. All rights reserved.
|
||||
* Copyright © 2010-2011 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -42,9 +42,6 @@ extern "C" {
|
||||
/** \brief Return the domain, bus and device IDs of the CUDA device \p cudevice.
|
||||
*
|
||||
* Device \p cudevice must match the local machine.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cuda_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
@@ -90,9 +87,6 @@ hwloc_cuda_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cuda_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
|
||||
8
src/3rdparty/hwloc/include/hwloc/cudart.h
vendored
8
src/3rdparty/hwloc/include/hwloc/cudart.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2010-2023 Inria. All rights reserved.
|
||||
* Copyright © 2010-2021 Inria. All rights reserved.
|
||||
* Copyright © 2010-2011 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -43,9 +43,6 @@ extern "C" {
|
||||
/** \brief Return the domain, bus and device IDs of the CUDA device whose index is \p idx.
|
||||
*
|
||||
* Device index \p idx must match the local machine.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cudart_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
@@ -87,9 +84,6 @@ hwloc_cudart_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unus
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cudart_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
|
||||
19
src/3rdparty/hwloc/include/hwloc/diff.h
vendored
19
src/3rdparty/hwloc/include/hwloc/diff.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2013-2024 Inria. All rights reserved.
|
||||
* Copyright © 2013-2020 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -222,8 +222,6 @@ enum hwloc_topology_diff_apply_flags_e {
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_apply(hwloc_topology_t topology, hwloc_topology_diff_t diff, unsigned long flags);
|
||||
|
||||
/** \brief Destroy a list of topology differences.
|
||||
*
|
||||
* \return 0.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff);
|
||||
|
||||
@@ -235,8 +233,6 @@ HWLOC_DECLSPEC int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff);
|
||||
* This identifier is usually the name of the other XML file
|
||||
* that contains the reference topology.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*
|
||||
* \note the pointer returned in refname should later be freed
|
||||
* by the caller.
|
||||
*/
|
||||
@@ -250,17 +246,10 @@ HWLOC_DECLSPEC int hwloc_topology_diff_load_xml(const char *xmlpath, hwloc_topol
|
||||
* This identifier is usually the name of the other XML file
|
||||
* that contains the reference topology.
|
||||
* This attribute is given back when reading the diff from XML.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_export_xml(hwloc_topology_diff_t diff, const char *refname, const char *xmlpath);
|
||||
|
||||
/** \brief Load a list of topology differences from a XML buffer.
|
||||
*
|
||||
* Build a list of differences from the XML memory buffer given
|
||||
* at \p xmlbuffer and of length \p buflen (including an ending \c \0).
|
||||
* This buffer may have been filled earlier with
|
||||
* hwloc_topology_diff_export_xmlbuffer().
|
||||
*
|
||||
* If not \c NULL, \p refname will be filled with the identifier
|
||||
* string of the reference topology for the difference file,
|
||||
@@ -268,8 +257,6 @@ HWLOC_DECLSPEC int hwloc_topology_diff_export_xml(hwloc_topology_diff_t diff, co
|
||||
* This identifier is usually the name of the other XML file
|
||||
* that contains the reference topology.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*
|
||||
* \note the pointer returned in refname should later be freed
|
||||
* by the caller.
|
||||
*/
|
||||
@@ -284,11 +271,9 @@ HWLOC_DECLSPEC int hwloc_topology_diff_load_xmlbuffer(const char *xmlbuffer, int
|
||||
* that contains the reference topology.
|
||||
* This attribute is given back when reading the diff from XML.
|
||||
*
|
||||
* The returned buffer ends with a \c \0 that is included in the returned
|
||||
* The returned buffer ends with a \0 that is included in the returned
|
||||
* length.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*
|
||||
* \note The XML buffer should later be freed with hwloc_free_xmlbuffer().
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_export_xmlbuffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen);
|
||||
|
||||
78
src/3rdparty/hwloc/include/hwloc/distances.h
vendored
78
src/3rdparty/hwloc/include/hwloc/distances.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2010-2025 Inria. All rights reserved.
|
||||
* Copyright © 2010-2022 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -28,18 +28,18 @@ extern "C" {
|
||||
|
||||
/** \brief Matrix of distances between a set of objects.
|
||||
*
|
||||
* The most common matrix contains latencies between NUMA nodes
|
||||
* This matrix often contains latencies between NUMA nodes
|
||||
* (as reported in the System Locality Distance Information Table (SLIT)
|
||||
* in the ACPI specification), which may or may not be physically accurate.
|
||||
* It corresponds to the latency for accessing the memory of one node
|
||||
* from a core in another node.
|
||||
* The corresponding kind is ::HWLOC_DISTANCES_KIND_MEANS_LATENCY | ::HWLOC_DISTANCES_KIND_FROM_USER.
|
||||
* The corresponding kind is ::HWLOC_DISTANCES_KIND_FROM_OS | ::HWLOC_DISTANCES_KIND_FROM_USER.
|
||||
* The name of this distances structure is "NUMALatency".
|
||||
* Others distance structures include and "XGMIBandwidth", "XGMIHops",
|
||||
* "XeLinkBandwidth" and "NVLinkBandwidth".
|
||||
*
|
||||
* The matrix may also contain bandwidths between random sets of objects,
|
||||
* possibly provided by the user, as specified in the \p kind attribute.
|
||||
* Others common distance structures include and "XGMIBandwidth", "XGMIHops",
|
||||
* "XeLinkBandwidth" and "NVLinkBandwidth".
|
||||
*
|
||||
* Pointers \p objs and \p values should not be replaced, reallocated, freed, etc.
|
||||
* However callers are allowed to modify \p kind as well as the contents
|
||||
@@ -70,10 +70,11 @@ struct hwloc_distances_s {
|
||||
* The \p kind attribute of struct hwloc_distances_s is a OR'ed set
|
||||
* of kinds.
|
||||
*
|
||||
* Each distance matrix may have only one kind among HWLOC_DISTANCES_KIND_FROM_*
|
||||
* specifying where distance information comes from,
|
||||
* and one kind among HWLOC_DISTANCES_KIND_MEANS_* specifying
|
||||
* whether values are latencies or bandwidths.
|
||||
* A kind of format HWLOC_DISTANCES_KIND_FROM_* specifies where the
|
||||
* distance information comes from, if known.
|
||||
*
|
||||
* A kind of format HWLOC_DISTANCES_KIND_MEANS_* specifies whether
|
||||
* values are latencies or bandwidths, if applicable.
|
||||
*/
|
||||
enum hwloc_distances_kind_e {
|
||||
/** \brief These distances were obtained from the operating system or hardware.
|
||||
@@ -130,8 +131,6 @@ enum hwloc_distances_kind_e {
|
||||
*
|
||||
* Each distance matrix returned in the \p distances array should be released
|
||||
* by the caller using hwloc_distances_release().
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_distances_get(hwloc_topology_t topology,
|
||||
@@ -141,8 +140,6 @@ hwloc_distances_get(hwloc_topology_t topology,
|
||||
/** \brief Retrieve distance matrices for object at a specific depth in the topology.
|
||||
*
|
||||
* Identical to hwloc_distances_get() with the additional \p depth filter.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_distances_get_by_depth(hwloc_topology_t topology, int depth,
|
||||
@@ -152,8 +149,6 @@ hwloc_distances_get_by_depth(hwloc_topology_t topology, int depth,
|
||||
/** \brief Retrieve distance matrices for object of a specific type.
|
||||
*
|
||||
* Identical to hwloc_distances_get() with the additional \p type filter.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_distances_get_by_type(hwloc_topology_t topology, hwloc_obj_type_t type,
|
||||
@@ -167,8 +162,6 @@ hwloc_distances_get_by_type(hwloc_topology_t topology, hwloc_obj_type_t type,
|
||||
* The name of the most common structure is "NUMALatency".
|
||||
* Others include "XGMIBandwidth", "XGMIHops", "XeLinkBandwidth",
|
||||
* and "NVLinkBandwidth".
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_distances_get_by_name(hwloc_topology_t topology, const char *name,
|
||||
@@ -178,12 +171,7 @@ hwloc_distances_get_by_name(hwloc_topology_t topology, const char *name,
|
||||
/** \brief Get a description of what a distances structure contains.
|
||||
*
|
||||
* For instance "NUMALatency" for hardware-provided NUMA distances (ACPI SLIT),
|
||||
* or \c NULL if unknown.
|
||||
*
|
||||
* \return the constant string with the name of the distance structure.
|
||||
*
|
||||
* \note The returned name should not be freed by the caller,
|
||||
* it belongs to the hwloc library.
|
||||
* or NULL if unknown.
|
||||
*/
|
||||
HWLOC_DECLSPEC const char *
|
||||
hwloc_distances_get_name(hwloc_topology_t topology, struct hwloc_distances_s *distances);
|
||||
@@ -227,24 +215,17 @@ enum hwloc_distances_transform_e {
|
||||
HWLOC_DISTANCES_TRANSFORM_LINKS = 1,
|
||||
|
||||
/** \brief Merge switches with multiple ports into a single object.
|
||||
*
|
||||
* This currently only applies to NVSwitches where GPUs seem connected
|
||||
* to different switch ports. Switch ports must be objects with subtype
|
||||
* "NVSwitch" as in the NVLinkBandwidth matrix.
|
||||
*
|
||||
* This transformation will replace all ports with only the first one,
|
||||
* now connected to all GPUs. Other ports are removed by applying
|
||||
* ::HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL internally.
|
||||
* This currently only applies to NVSwitches where GPUs seem connected to different
|
||||
* separate switch ports in the NVLinkBandwidth matrix. This transformation will
|
||||
* replace all of them with the same port connected to all GPUs.
|
||||
* Other ports are removed by applying ::HWLOC_DISTANCES_TRANSFORM_REMOVE_NULL internally.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS = 2,
|
||||
|
||||
/** \brief Apply a transitive closure to the matrix to connect objects across switches.
|
||||
*
|
||||
* All pairs of GPUs will be reported as directly connected instead GPUs being
|
||||
* only connected to switches.
|
||||
*
|
||||
* Switch ports must be objects with subtype "NVSwitch" as in the NVLinkBandwidth matrix.
|
||||
* This currently only applies to GPUs and NVSwitches in the NVLinkBandwidth matrix.
|
||||
* All pairs of GPUs will be reported as directly connected.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE = 3
|
||||
@@ -271,8 +252,6 @@ enum hwloc_distances_transform_e {
|
||||
*
|
||||
* \p flags must be \c 0 for now.
|
||||
*
|
||||
* \return 0 on success, -1 on error for instance if flags are invalid.
|
||||
*
|
||||
* \note Objects in distances array \p objs may be directly modified
|
||||
* in place without using hwloc_distances_transform().
|
||||
* One may use hwloc_get_obj_with_same_locality() to easily convert
|
||||
@@ -293,7 +272,6 @@ HWLOC_DECLSPEC int hwloc_distances_transform(hwloc_topology_t topology, struct h
|
||||
|
||||
/** \brief Find the index of an object in a distances structure.
|
||||
*
|
||||
* \return the index of the object in the distances structure if any.
|
||||
* \return -1 if object \p obj is not involved in structure \p distances.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
@@ -311,7 +289,6 @@ hwloc_distances_obj_index(struct hwloc_distances_s *distances, hwloc_obj_t obj)
|
||||
* The distance from \p obj1 to \p obj2 is stored in the value pointed by
|
||||
* \p value1to2 and reciprocally.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 if object \p obj1 or \p obj2 is not involved in structure \p distances.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
@@ -363,8 +340,6 @@ typedef void * hwloc_distances_add_handle_t;
|
||||
* Otherwise, it will be copied internally and may later be freed by the caller.
|
||||
*
|
||||
* \p kind specifies the kind of distance as a OR'ed set of ::hwloc_distances_kind_e.
|
||||
* Only one kind of meaning and one kind of provenance may be given if appropriate
|
||||
* (e.g. ::HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH and ::HWLOC_DISTANCES_KIND_FROM_USER).
|
||||
* Kind ::HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES will be automatically set
|
||||
* according to objects having different types in hwloc_distances_add_values().
|
||||
*
|
||||
@@ -399,8 +374,8 @@ hwloc_distances_add_create(hwloc_topology_t topology,
|
||||
*
|
||||
* \p flags must be \c 0 for now.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error.
|
||||
* \return \c 0 on success.
|
||||
* \return \c -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_add_values(hwloc_topology_t topology,
|
||||
hwloc_distances_add_handle_t handle,
|
||||
@@ -411,8 +386,7 @@ HWLOC_DECLSPEC int hwloc_distances_add_values(hwloc_topology_t topology,
|
||||
/** \brief Flags for adding a new distances to a topology. */
|
||||
enum hwloc_distances_add_flag_e {
|
||||
/** \brief Try to group objects based on the newly provided distance information.
|
||||
* Grouping is only performed when the distances structure contains latencies,
|
||||
* and when all objects are of the same type.
|
||||
* This is ignored for distances between objects of different types.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_ADD_FLAG_GROUP = (1UL<<0),
|
||||
@@ -437,8 +411,8 @@ enum hwloc_distances_add_flag_e {
|
||||
*
|
||||
* On error, the temporary distances structure and its content are destroyed.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error.
|
||||
* \return \c 0 on success.
|
||||
* \return \c -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_add_commit(hwloc_topology_t topology,
|
||||
hwloc_distances_add_handle_t handle,
|
||||
@@ -459,24 +433,18 @@ HWLOC_DECLSPEC int hwloc_distances_add_commit(hwloc_topology_t topology,
|
||||
*
|
||||
* If these distances were used to group objects, these additional
|
||||
* Group objects are not removed from the topology.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_remove(hwloc_topology_t topology);
|
||||
|
||||
/** \brief Remove distance matrices for objects at a specific depth in the topology.
|
||||
*
|
||||
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_remove_by_depth(hwloc_topology_t topology, int depth);
|
||||
|
||||
/** \brief Remove distance matrices for objects of a specific type in the topology.
|
||||
*
|
||||
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_distances_remove_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
|
||||
@@ -490,8 +458,6 @@ hwloc_distances_remove_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
|
||||
/** \brief Release and remove the given distance matrice from the topology.
|
||||
*
|
||||
* This function includes a call to hwloc_distances_release().
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_release_remove(hwloc_topology_t topology, struct hwloc_distances_s *distances);
|
||||
|
||||
|
||||
16
src/3rdparty/hwloc/include/hwloc/export.h
vendored
16
src/3rdparty/hwloc/include/hwloc/export.h
vendored
@@ -55,7 +55,7 @@ enum hwloc_topology_export_xml_flags_e {
|
||||
*
|
||||
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
|
||||
*
|
||||
* \return 0 on success, or -1 on error.
|
||||
* \return -1 if a failure occured.
|
||||
*
|
||||
* \note See also hwloc_topology_set_userdata_export_callback()
|
||||
* for exporting application-specific object userdata.
|
||||
@@ -91,7 +91,7 @@ HWLOC_DECLSPEC int hwloc_topology_export_xml(hwloc_topology_t topology, const ch
|
||||
*
|
||||
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
|
||||
*
|
||||
* \return 0 on success, or -1 on error.
|
||||
* \return -1 if a failure occured.
|
||||
*
|
||||
* \note See also hwloc_topology_set_userdata_export_callback()
|
||||
* for exporting application-specific object userdata.
|
||||
@@ -145,15 +145,13 @@ HWLOC_DECLSPEC void hwloc_topology_set_userdata_export_callback(hwloc_topology_t
|
||||
* that were given to the export callback.
|
||||
*
|
||||
* Only printable characters may be exported to XML string attributes.
|
||||
* If a non-printable character is passed in \p name or \p buffer,
|
||||
* the function returns -1 with errno set to EINVAL.
|
||||
*
|
||||
* If exporting binary data, the application should first encode into
|
||||
* printable characters only (or use hwloc_export_obj_userdata_base64()).
|
||||
* It should also take care of portability issues if the export may
|
||||
* be reimported on a different architecture.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c EINVAL if a non-printable character is
|
||||
* passed in \p name or \b buffer.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_export_obj_userdata(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
|
||||
|
||||
@@ -167,14 +165,8 @@ HWLOC_DECLSPEC int hwloc_export_obj_userdata(void *reserved, hwloc_topology_t to
|
||||
* This function may only be called from within the export() callback passed
|
||||
* to hwloc_topology_set_userdata_export_callback().
|
||||
*
|
||||
* The name must be made of printable characters for export to XML string attributes.
|
||||
*
|
||||
* The function does not take care of portability issues if the export
|
||||
* may be reimported on a different architecture.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c EINVAL if a non-printable character is
|
||||
* passed in \p name.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_export_obj_userdata_base64(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
|
||||
|
||||
|
||||
5
src/3rdparty/hwloc/include/hwloc/gl.h
vendored
5
src/3rdparty/hwloc/include/hwloc/gl.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2012 Blue Brain Project, EPFL. All rights reserved.
|
||||
* Copyright © 2012-2023 Inria. All rights reserved.
|
||||
* Copyright © 2012-2021 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -102,8 +102,7 @@ hwloc_gl_get_display_osdev_by_name(hwloc_topology_t topology,
|
||||
* Retrieves the OpenGL display port (server) in \p port and device (screen)
|
||||
* in \p screen that correspond to the given hwloc OS device object.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 if none could be found.
|
||||
* \return \c -1 if none could be found.
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
|
||||
13
src/3rdparty/hwloc/include/hwloc/glibc-sched.h
vendored
13
src/3rdparty/hwloc/include/hwloc/glibc-sched.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
||||
* Copyright © 2009-2020 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -52,8 +52,6 @@ extern "C" {
|
||||
* that takes a cpu_set_t as input parameter.
|
||||
*
|
||||
* \p schedsetsize should be sizeof(cpu_set_t) unless \p schedset was dynamically allocated with CPU_ALLOC
|
||||
*
|
||||
* \return 0.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cpuset_to_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_cpuset_t hwlocset,
|
||||
@@ -82,9 +80,6 @@ hwloc_cpuset_to_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribute
|
||||
* that takes a cpu_set_t as input parameter.
|
||||
*
|
||||
* \p schedsetsize should be sizeof(cpu_set_t) unless \p schedset was dynamically allocated with CPU_ALLOC
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cpuset_from_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_cpuset_t hwlocset,
|
||||
@@ -100,8 +95,7 @@ hwloc_cpuset_from_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribu
|
||||
cpu = 0;
|
||||
while (count) {
|
||||
if (CPU_ISSET_S(cpu, schedsetsize, schedset)) {
|
||||
if (hwloc_bitmap_set(hwlocset, cpu) < 0)
|
||||
return -1;
|
||||
hwloc_bitmap_set(hwlocset, cpu);
|
||||
count--;
|
||||
}
|
||||
cpu++;
|
||||
@@ -113,8 +107,7 @@ hwloc_cpuset_from_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribu
|
||||
assert(schedsetsize == sizeof(cpu_set_t));
|
||||
for(cpu=0; cpu<CPU_SETSIZE; cpu++)
|
||||
if (CPU_ISSET(cpu, schedset))
|
||||
if (hwloc_bitmap_set(hwlocset, cpu) < 0)
|
||||
return -1;
|
||||
hwloc_bitmap_set(hwlocset, cpu);
|
||||
#endif /* !CPU_ZERO_S */
|
||||
return 0;
|
||||
}
|
||||
|
||||
1049
src/3rdparty/hwloc/include/hwloc/helper.h
vendored
1049
src/3rdparty/hwloc/include/hwloc/helper.h
vendored
File diff suppressed because it is too large
Load Diff
161
src/3rdparty/hwloc/include/hwloc/levelzero.h
vendored
161
src/3rdparty/hwloc/include/hwloc/levelzero.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2021-2024 Inria. All rights reserved.
|
||||
* Copyright © 2021 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -32,8 +32,7 @@ extern "C" {
|
||||
/** \defgroup hwlocality_levelzero Interoperability with the oneAPI Level Zero interface.
|
||||
*
|
||||
* This interface offers ways to retrieve topology information about
|
||||
* devices managed by the Level Zero API, both for main Core devices (ZE API)
|
||||
* and the Sysman devices (ZES API).
|
||||
* devices managed by the Level Zero API.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
@@ -45,7 +44,8 @@ extern "C" {
|
||||
* the Level Zero device \p device.
|
||||
*
|
||||
* Topology \p topology and device \p device must match the local machine.
|
||||
* The Level Zero library must have been initialized with zeInit().
|
||||
* The Level Zero must have been initialized with Sysman enabled
|
||||
* (ZES_ENABLE_SYSMAN=1 in the environment).
|
||||
* I/O devices detection and the Level Zero component are not needed in the
|
||||
* topology.
|
||||
*
|
||||
@@ -55,80 +55,17 @@ extern "C" {
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*
|
||||
* \note zeDevicePciGetPropertiesExt() must be supported, or the entire machine
|
||||
* locality will be returned.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_levelzero_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
ze_device_handle_t device, hwloc_cpuset_t set)
|
||||
{
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
|
||||
#define HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX 128
|
||||
char path[HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX];
|
||||
ze_pci_ext_properties_t pci;
|
||||
ze_result_t res;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pci.stype = ZE_STRUCTURE_TYPE_PCI_EXT_PROPERTIES;
|
||||
pci.pNext = NULL;
|
||||
res = zeDevicePciGetPropertiesExt(device, &pci);
|
||||
if (res != ZE_RESULT_SUCCESS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/local_cpus",
|
||||
pci.address.domain, pci.address.bus, pci.address.device, pci.address.function);
|
||||
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|
||||
|| hwloc_bitmap_iszero(set))
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#else
|
||||
/* Non-Linux systems simply get a full cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the CPU set of logical processors that are physically
|
||||
* close to the Level Zero Sysman device \p device
|
||||
*
|
||||
* Store in \p set the CPU-set describing the locality of
|
||||
* the Level Zero device \p device.
|
||||
*
|
||||
* Topology \p topology and device \p device must match the local machine.
|
||||
* The Level Zero library must have been initialized with Sysman enabled
|
||||
* with zesInit().
|
||||
* I/O devices detection and the Level Zero component are not needed in the
|
||||
* topology.
|
||||
*
|
||||
* The function only returns the locality of the device.
|
||||
* If more information about the device is needed, OS objects should
|
||||
* be used instead, see hwloc_levelzero_get_device_osdev().
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_levelzero_get_sysman_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
zes_device_handle_t device, hwloc_cpuset_t set)
|
||||
{
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
|
||||
#define HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX 128
|
||||
char path[HWLOC_LEVELZERO_DEVICE_SYSFS_PATH_MAX];
|
||||
zes_pci_properties_t pci;
|
||||
zes_device_handle_t sdevice = device;
|
||||
ze_result_t res;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
@@ -136,7 +73,7 @@ hwloc_levelzero_get_sysman_device_cpuset(hwloc_topology_t topology __hwloc_attri
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = zesDevicePciGetProperties(device, &pci);
|
||||
res = zesDevicePciGetProperties(sdevice, &pci);
|
||||
if (res != ZE_RESULT_SUCCESS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
@@ -161,90 +98,17 @@ hwloc_levelzero_get_sysman_device_cpuset(hwloc_topology_t topology __hwloc_attri
|
||||
* \return \c NULL if none could be found.
|
||||
*
|
||||
* Topology \p topology and device \p dv_ind must match the local machine.
|
||||
* The Level Zero library must have been initialized with zeInit().
|
||||
* I/O devices detection and the Level Zero component must be enabled in the
|
||||
* topology. If not, the locality of the object may still be found using
|
||||
* hwloc_levelzero_get_device_cpuset().
|
||||
*
|
||||
* \note If the input ZE device is actually a subdevice, then its parent
|
||||
* (root device) is actually translated, i.e. the main hwloc OS device
|
||||
* is returned instead of one of its children.
|
||||
*
|
||||
* \note The corresponding hwloc PCI device may be found by looking
|
||||
* at the result parent pointer (unless PCI devices are filtered out).
|
||||
*
|
||||
* \note zeDevicePciGetPropertiesExt() must be supported.
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_levelzero_get_device_osdev(hwloc_topology_t topology, ze_device_handle_t device)
|
||||
{
|
||||
ze_pci_ext_properties_t pci;
|
||||
ze_result_t res;
|
||||
hwloc_obj_t osdev;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pci.stype = ZE_STRUCTURE_TYPE_PCI_EXT_PROPERTIES;
|
||||
pci.pNext = NULL;
|
||||
res = zeDevicePciGetPropertiesExt(device, &pci);
|
||||
if (res != ZE_RESULT_SUCCESS) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
hwloc_obj_t pcidev;
|
||||
|
||||
if (strncmp(osdev->name, "ze", 2))
|
||||
continue;
|
||||
|
||||
pcidev = osdev;
|
||||
while (pcidev && pcidev->type != HWLOC_OBJ_PCI_DEVICE)
|
||||
pcidev = pcidev->parent;
|
||||
if (!pcidev)
|
||||
continue;
|
||||
|
||||
if (pcidev
|
||||
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
|
||||
&& pcidev->attr->pcidev.domain == pci.address.domain
|
||||
&& pcidev->attr->pcidev.bus == pci.address.bus
|
||||
&& pcidev->attr->pcidev.dev == pci.address.device
|
||||
&& pcidev->attr->pcidev.func == pci.address.function)
|
||||
return osdev;
|
||||
|
||||
/* FIXME: when we'll have serialnumber, try it in case PCI is filtered-out */
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to Level Zero Sysman device
|
||||
* \p device.
|
||||
*
|
||||
* \return The hwloc OS device object that describes the given Level Zero device \p device.
|
||||
* \return \c NULL if none could be found.
|
||||
*
|
||||
* Topology \p topology and device \p dv_ind must match the local machine.
|
||||
* The Level Zero library must have been initialized with Sysman enabled
|
||||
* with zesInit().
|
||||
* I/O devices detection and the Level Zero component must be enabled in the
|
||||
* topology. If not, the locality of the object may still be found using
|
||||
* hwloc_levelzero_get_device_cpuset().
|
||||
*
|
||||
* \note If the input ZES device is actually a subdevice, then its parent
|
||||
* (root device) is actually translated, i.e. the main hwloc OS device
|
||||
* is returned instead of one of its children.
|
||||
*
|
||||
* \note The corresponding hwloc PCI device may be found by looking
|
||||
* at the result parent pointer (unless PCI devices are filtered out).
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_levelzero_get_sysman_device_osdev(hwloc_topology_t topology, zes_device_handle_t device)
|
||||
{
|
||||
zes_device_handle_t sdevice = device;
|
||||
zes_pci_properties_t pci;
|
||||
ze_result_t res;
|
||||
hwloc_obj_t osdev;
|
||||
@@ -254,25 +118,20 @@ hwloc_levelzero_get_sysman_device_osdev(hwloc_topology_t topology, zes_device_ha
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = zesDevicePciGetProperties(device, &pci);
|
||||
res = zesDevicePciGetProperties(sdevice, &pci);
|
||||
if (res != ZE_RESULT_SUCCESS) {
|
||||
/* L0 was likely initialized without sysman, don't bother */
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
hwloc_obj_t pcidev;
|
||||
hwloc_obj_t pcidev = osdev->parent;
|
||||
|
||||
if (strncmp(osdev->name, "ze", 2))
|
||||
continue;
|
||||
|
||||
pcidev = osdev;
|
||||
while (pcidev && pcidev->type != HWLOC_OBJ_PCI_DEVICE)
|
||||
pcidev = pcidev->parent;
|
||||
if (!pcidev)
|
||||
continue;
|
||||
|
||||
if (pcidev
|
||||
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
|
||||
&& pcidev->attr->pcidev.domain == pci.address.domain
|
||||
|
||||
34
src/3rdparty/hwloc/include/hwloc/linux-libnuma.h
vendored
34
src/3rdparty/hwloc/include/hwloc/linux-libnuma.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010, 2012 Université Bordeaux
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
@@ -50,8 +50,6 @@ extern "C" {
|
||||
* This function may be used before calling set_mempolicy, mbind, migrate_pages
|
||||
* or any other function that takes an array of unsigned long and a maximal
|
||||
* node number as input parameter.
|
||||
*
|
||||
* \return 0.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cpuset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset,
|
||||
@@ -86,8 +84,6 @@ hwloc_cpuset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_cpus
|
||||
* This function may be used before calling set_mempolicy, mbind, migrate_pages
|
||||
* or any other function that takes an array of unsigned long and a maximal
|
||||
* node number as input parameter.
|
||||
*
|
||||
* \return 0.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_nodeset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset,
|
||||
@@ -123,9 +119,6 @@ hwloc_nodeset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_nod
|
||||
* This function may be used after calling get_mempolicy or any other function
|
||||
* that takes an array of unsigned long as output parameter (and possibly
|
||||
* a maximal node number as input parameter).
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if failing an internal reallocation.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cpuset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
|
||||
@@ -137,8 +130,7 @@ hwloc_cpuset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_cpuset_t
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
||||
if (node->os_index < maxnode
|
||||
&& (mask[node->os_index/sizeof(*mask)/8] & (1UL << (node->os_index % (sizeof(*mask)*8)))))
|
||||
if (hwloc_bitmap_or(cpuset, cpuset, node->cpuset) < 0)
|
||||
return -1;
|
||||
hwloc_bitmap_or(cpuset, cpuset, node->cpuset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -150,9 +142,6 @@ hwloc_cpuset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_cpuset_t
|
||||
* This function may be used after calling get_mempolicy or any other function
|
||||
* that takes an array of unsigned long as output parameter (and possibly
|
||||
* a maximal node number as input parameter).
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_nodeset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
|
||||
@@ -164,8 +153,7 @@ hwloc_nodeset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_nodeset
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
||||
if (node->os_index < maxnode
|
||||
&& (mask[node->os_index/sizeof(*mask)/8] & (1UL << (node->os_index % (sizeof(*mask)*8)))))
|
||||
if (hwloc_bitmap_set(nodeset, node->os_index) < 0)
|
||||
return -1;
|
||||
hwloc_bitmap_set(nodeset, node->os_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -196,7 +184,7 @@ hwloc_nodeset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_nodeset
|
||||
* This function may be used before calling many numa_ functions
|
||||
* that use a struct bitmask as an input parameter.
|
||||
*
|
||||
* \return newly allocated struct bitmask, or \c NULL on error.
|
||||
* \return newly allocated struct bitmask.
|
||||
*/
|
||||
static __hwloc_inline struct bitmask *
|
||||
hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset) __hwloc_attribute_malloc;
|
||||
@@ -221,7 +209,7 @@ hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpu
|
||||
* This function may be used before calling many numa_ functions
|
||||
* that use a struct bitmask as an input parameter.
|
||||
*
|
||||
* \return newly allocated struct bitmask, or \c NULL on error.
|
||||
* \return newly allocated struct bitmask.
|
||||
*/
|
||||
static __hwloc_inline struct bitmask *
|
||||
hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset) __hwloc_attribute_malloc;
|
||||
@@ -243,9 +231,6 @@ hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_no
|
||||
*
|
||||
* This function may be used after calling many numa_ functions
|
||||
* that use a struct bitmask as an output parameter.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cpuset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
|
||||
@@ -256,8 +241,7 @@ hwloc_cpuset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_cpuset_
|
||||
hwloc_bitmap_zero(cpuset);
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
||||
if (numa_bitmask_isbitset(bitmask, node->os_index))
|
||||
if (hwloc_bitmap_or(cpuset, cpuset, node->cpuset) < 0)
|
||||
return -1;
|
||||
hwloc_bitmap_or(cpuset, cpuset, node->cpuset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -265,9 +249,6 @@ hwloc_cpuset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_cpuset_
|
||||
*
|
||||
* This function may be used after calling many numa_ functions
|
||||
* that use a struct bitmask as an output parameter.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_nodeset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
|
||||
@@ -278,8 +259,7 @@ hwloc_nodeset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_nodese
|
||||
hwloc_bitmap_zero(nodeset);
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
||||
if (numa_bitmask_isbitset(bitmask, node->os_index))
|
||||
if (hwloc_bitmap_set(nodeset, node->os_index) < 0)
|
||||
return -1;
|
||||
hwloc_bitmap_set(nodeset, node->os_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
10
src/3rdparty/hwloc/include/hwloc/linux.h
vendored
10
src/3rdparty/hwloc/include/hwloc/linux.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
||||
* Copyright © 2009-2021 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011 Université Bordeaux
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
@@ -38,8 +38,6 @@ extern "C" {
|
||||
* The behavior is exactly the same as the Linux sched_setaffinity system call,
|
||||
* but uses a hwloc cpuset.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*
|
||||
* \note This is equivalent to calling hwloc_set_proc_cpubind() with
|
||||
* HWLOC_CPUBIND_THREAD as flags.
|
||||
*/
|
||||
@@ -54,8 +52,6 @@ HWLOC_DECLSPEC int hwloc_linux_set_tid_cpubind(hwloc_topology_t topology, pid_t
|
||||
* The behavior is exactly the same as the Linux sched_getaffinity system call,
|
||||
* but uses a hwloc cpuset.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*
|
||||
* \note This is equivalent to calling hwloc_get_proc_cpubind() with
|
||||
* ::HWLOC_CPUBIND_THREAD as flags.
|
||||
*/
|
||||
@@ -66,8 +62,6 @@ HWLOC_DECLSPEC int hwloc_linux_get_tid_cpubind(hwloc_topology_t topology, pid_t
|
||||
* The CPU-set \p set (previously allocated by the caller)
|
||||
* is filled with the PU which the thread last ran on.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*
|
||||
* \note This is equivalent to calling hwloc_get_proc_last_cpu_location() with
|
||||
* ::HWLOC_CPUBIND_THREAD as flags.
|
||||
*/
|
||||
@@ -78,8 +72,6 @@ HWLOC_DECLSPEC int hwloc_linux_get_tid_last_cpu_location(hwloc_topology_t topolo
|
||||
* Might be used when reading CPU set from sysfs attributes such as topology
|
||||
* and caches for processors, or local_cpus for devices.
|
||||
*
|
||||
* \return 0 on success, -1 on error.
|
||||
*
|
||||
* \note This function ignores the HWLOC_FSROOT environment variable.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_linux_read_path_as_cpumask(const char *path, hwloc_bitmap_t set);
|
||||
|
||||
335
src/3rdparty/hwloc/include/hwloc/memattrs.h
vendored
335
src/3rdparty/hwloc/include/hwloc/memattrs.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2019-2025 Inria. All rights reserved.
|
||||
* Copyright © 2019-2022 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -54,15 +54,6 @@ extern "C" {
|
||||
* Attribute values for these nodes, if any, may then be obtained with
|
||||
* hwloc_memattr_get_value() and manually compared with the desired criteria.
|
||||
*
|
||||
* Memory attributes are also used internally to build Memory Tiers which provide
|
||||
* an easy way to distinguish NUMA nodes of different kinds, as explained
|
||||
* in \ref heteromem.
|
||||
*
|
||||
* Beside tiers, hwloc defines a set of "default" nodes where normal memory
|
||||
* allocations should be made from (see hwloc_topology_get_default_nodeset()).
|
||||
* This is also useful for dividing the machine into a set of non-overlapping
|
||||
* NUMA domains, for instance for binding tasks per domain.
|
||||
*
|
||||
* \sa An example is available in doc/examples/memory-attributes.c in the source tree.
|
||||
*
|
||||
* \note The API also supports specific objects as initiator,
|
||||
@@ -74,10 +65,7 @@ extern "C" {
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Predefined memory attribute IDs.
|
||||
* See ::hwloc_memattr_id_t for the generic definition of IDs
|
||||
* for predefined or custom attributes.
|
||||
*/
|
||||
/** \brief Memory node attributes. */
|
||||
enum hwloc_memattr_id_e {
|
||||
/** \brief
|
||||
* The \"Capacity\" is returned in bytes (local_memory attribute in objects).
|
||||
@@ -86,8 +74,6 @@ enum hwloc_memattr_id_e {
|
||||
*
|
||||
* No initiator is involved when looking at this attribute.
|
||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST.
|
||||
*
|
||||
* Capacity values may not be modified using hwloc_memattr_set_value().
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_MEMATTR_ID_CAPACITY = 0,
|
||||
@@ -103,8 +89,6 @@ enum hwloc_memattr_id_e {
|
||||
*
|
||||
* No initiator is involved when looking at this attribute.
|
||||
* The corresponding attribute flags are ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST.
|
||||
|
||||
* Locality values may not be modified using hwloc_memattr_set_value().
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_MEMATTR_ID_LOCALITY = 1,
|
||||
@@ -185,26 +169,15 @@ enum hwloc_memattr_id_e {
|
||||
|
||||
/* TODO persistence? */
|
||||
|
||||
HWLOC_MEMATTR_ID_MAX /**< \private
|
||||
* Sentinel value for predefined attributes.
|
||||
* Dynamically registered custom attributes start here.
|
||||
*/
|
||||
HWLOC_MEMATTR_ID_MAX /**< \private Sentinel value */
|
||||
};
|
||||
|
||||
/** \brief A memory attribute identifier.
|
||||
*
|
||||
* hwloc predefines some commonly-used attributes in ::hwloc_memattr_id_e.
|
||||
* One may then dynamically register custom ones with hwloc_memattr_register(),
|
||||
* they will be assigned IDs immediately after the predefined ones.
|
||||
* See \ref hwlocality_memattrs_manage for more information about
|
||||
* existing attribute IDs.
|
||||
* May be either one of ::hwloc_memattr_id_e or a new id returned by hwloc_memattr_register().
|
||||
*/
|
||||
typedef unsigned hwloc_memattr_id_t;
|
||||
|
||||
/** \brief Return the identifier of the memory attribute with the given name.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c EINVAL if no such attribute exists.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_get_by_name(hwloc_topology_t topology,
|
||||
@@ -250,16 +223,6 @@ enum hwloc_local_numanode_flag_e {
|
||||
*/
|
||||
HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY = (1UL<<1),
|
||||
|
||||
/** \breif Select NUMA nodes whose locality intersects the given cpuset.
|
||||
* This includes larger and smaller localities as well as localities
|
||||
* that are partially included.
|
||||
* For instance, if the locality is one core of both packages, a NUMA node
|
||||
* local to one package is neither larger nor smaller than this locality,
|
||||
* but it intersects it.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY = (1UL<<3),
|
||||
|
||||
/** \brief Select all NUMA nodes in the topology.
|
||||
* The initiator \p initiator is ignored.
|
||||
* \hideinitializer
|
||||
@@ -284,8 +247,6 @@ enum hwloc_local_numanode_flag_e {
|
||||
* or the number of nodes that would have been stored if there were
|
||||
* enough room.
|
||||
*
|
||||
* \return 0 on success or -1 on error.
|
||||
*
|
||||
* \note Some of these NUMA nodes may not have any memory attribute
|
||||
* values and hence not be reported as actual targets in other functions.
|
||||
*
|
||||
@@ -305,57 +266,7 @@ hwloc_get_local_numanode_objs(hwloc_topology_t topology,
|
||||
hwloc_obj_t *nodes,
|
||||
unsigned long flags);
|
||||
|
||||
/** \brief Return the set of default NUMA nodes
|
||||
*
|
||||
* In machines with heterogeneous memory, some NUMA nodes are considered
|
||||
* the default ones, i.e. where basic allocations should be made from.
|
||||
* These are usually DRAM nodes.
|
||||
*
|
||||
* Other nodes may be reserved for specific use (I/O device memory, e.g. GPU memory),
|
||||
* small but high performance (HBM), large but slow memory (NVM), etc.
|
||||
* Buffers should usually not be allocated from there unless explicitly required.
|
||||
*
|
||||
* This function fills \p nodeset with the bits of NUMA nodes considered default.
|
||||
*
|
||||
* It is guaranteed that these nodes have non-intersecting CPU sets,
|
||||
* i.e. cores may not have multiple local NUMA nodes anymore.
|
||||
* Hence this may be used to iterate over the platform divided into separate
|
||||
* NUMA localities, for instance for binding one task per NUMA domain.
|
||||
*
|
||||
* Any core that had some local NUMA node(s) in the initial topology should
|
||||
* still have one in the default nodeset. Corner cases where this would be
|
||||
* wrong consist in asymmetric platforms with missing DRAM nodes, or topologies
|
||||
* that were already restricted to less NUMA nodes.
|
||||
*
|
||||
* The returned nodeset may be passed to hwloc_topology_restrict() with
|
||||
* ::HWLOC_RESTRICT_FLAG_BYNODESET to remove all non-default nodes from
|
||||
* the topology. The resulting topology will be easier to use when iterating
|
||||
* over (now homogeneous) NUMA nodes.
|
||||
*
|
||||
* The heuristics for finding default nodes relies on memory tiers and subtypes
|
||||
* (see \ref heteromem) as well as the assumption that hardware vendors list
|
||||
* default nodes first in hardware tables.
|
||||
*
|
||||
* \p flags must be \c 0 for now.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error.
|
||||
*
|
||||
* \note The returned nodeset usually contains all nodes from a single memory
|
||||
* tier, likely the DRAM one.
|
||||
*
|
||||
* \note The returned nodeset is included in the list of available nodes
|
||||
* returned by hwloc_topology_get_topology_nodeset(). It is strictly smaller
|
||||
* if the machine has heterogeneous memory.
|
||||
*
|
||||
* \note The heuristics may return a suboptimal set of nodes if hwloc could
|
||||
* not guess memory types and/or if some default nodes were removed earlier
|
||||
* from the topology (e.g. with hwloc_topology_restrict()).
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_topology_get_default_nodeset(hwloc_topology_t topology,
|
||||
hwloc_nodeset_t nodeset,
|
||||
unsigned long flags);
|
||||
|
||||
|
||||
/** \brief Return an attribute value for a specific target NUMA node.
|
||||
*
|
||||
@@ -363,16 +274,8 @@ hwloc_topology_get_default_nodeset(hwloc_topology_t topology,
|
||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
|
||||
* location \p initiator is ignored and may be \c NULL.
|
||||
*
|
||||
* \p target_node cannot be \c NULL. If \p attribute is ::HWLOC_MEMATTR_ID_CAPACITY,
|
||||
* \p target_node must be a NUMA node. If it is ::HWLOC_MEMATTR_ID_LOCALITY,
|
||||
* \p target_node must have a CPU set.
|
||||
*
|
||||
* \p flags must be \c 0 for now.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance with errno set to \c EINVAL if flags
|
||||
* are invalid or no such attribute exists.
|
||||
*
|
||||
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
|
||||
* when refering to accesses performed by CPU cores.
|
||||
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
|
||||
@@ -404,10 +307,7 @@ hwloc_memattr_get_value(hwloc_topology_t topology,
|
||||
*
|
||||
* \p flags must be \c 0 for now.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c ENOENT if there are no matching targets.
|
||||
* \return -1 with errno set to \c EINVAL if flags are invalid,
|
||||
* or no such attribute exists.
|
||||
* If there are no matching targets, \c -1 is returned with \p errno set to \c ENOENT;
|
||||
*
|
||||
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
|
||||
* when refering to accesses performed by CPU cores.
|
||||
@@ -423,6 +323,10 @@ hwloc_memattr_get_best_target(hwloc_topology_t topology,
|
||||
hwloc_obj_t *best_target, hwloc_uint64_t *value);
|
||||
|
||||
/** \brief Return the best initiator for the given attribute and target NUMA node.
|
||||
*
|
||||
* If the attribute does not relate to a specific initiator
|
||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
|
||||
* \c -1 is returned and \p errno is set to \c EINVAL.
|
||||
*
|
||||
* If \p value is non \c NULL, the corresponding value is returned there.
|
||||
*
|
||||
@@ -436,22 +340,96 @@ hwloc_memattr_get_best_target(hwloc_topology_t topology,
|
||||
* The returned initiator should not be modified or freed,
|
||||
* it belongs to the topology.
|
||||
*
|
||||
* \p target_node cannot be \c NULL.
|
||||
*
|
||||
* \p flags must be \c 0 for now.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c ENOENT if there are no matching initiators.
|
||||
* \return -1 with errno set to \c EINVAL if the attribute does not relate to a specific initiator
|
||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR).
|
||||
* If there are no matching initiators, \c -1 is returned with \p errno set to \c ENOENT;
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_get_best_initiator(hwloc_topology_t topology,
|
||||
hwloc_memattr_id_t attribute,
|
||||
hwloc_obj_t target_node,
|
||||
hwloc_obj_t target,
|
||||
unsigned long flags,
|
||||
struct hwloc_location *best_initiator, hwloc_uint64_t *value);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/** \defgroup hwlocality_memattrs_manage Managing memory attributes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Return the name of a memory attribute.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_get_name(hwloc_topology_t topology,
|
||||
hwloc_memattr_id_t attribute,
|
||||
const char **name);
|
||||
|
||||
/** \brief Return the flags of the given attribute.
|
||||
*
|
||||
* Flags are a OR'ed set of ::hwloc_memattr_flag_e.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_get_flags(hwloc_topology_t topology,
|
||||
hwloc_memattr_id_t attribute,
|
||||
unsigned long *flags);
|
||||
|
||||
/** \brief Memory attribute flags.
|
||||
* Given to hwloc_memattr_register() and returned by hwloc_memattr_get_flags().
|
||||
*/
|
||||
enum hwloc_memattr_flag_e {
|
||||
/** \brief The best nodes for this memory attribute are those with the higher values.
|
||||
* For instance Bandwidth.
|
||||
*/
|
||||
HWLOC_MEMATTR_FLAG_HIGHER_FIRST = (1UL<<0),
|
||||
/** \brief The best nodes for this memory attribute are those with the lower values.
|
||||
* For instance Latency.
|
||||
*/
|
||||
HWLOC_MEMATTR_FLAG_LOWER_FIRST = (1UL<<1),
|
||||
/** \brief The value returned for this memory attribute depends on the given initiator.
|
||||
* For instance Bandwidth and Latency, but not Capacity.
|
||||
*/
|
||||
HWLOC_MEMATTR_FLAG_NEED_INITIATOR = (1UL<<2)
|
||||
};
|
||||
|
||||
/** \brief Register a new memory attribute.
|
||||
*
|
||||
* Add a specific memory attribute that is not defined in ::hwloc_memattr_id_e.
|
||||
* Flags are a OR'ed set of ::hwloc_memattr_flag_e. It must contain at least
|
||||
* one of ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST or ::HWLOC_MEMATTR_FLAG_LOWER_FIRST.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_register(hwloc_topology_t topology,
|
||||
const char *name,
|
||||
unsigned long flags,
|
||||
hwloc_memattr_id_t *id);
|
||||
|
||||
/** \brief Set an attribute value for a specific target NUMA node.
|
||||
*
|
||||
* If the attribute does not relate to a specific initiator
|
||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
|
||||
* location \p initiator is ignored and may be \c NULL.
|
||||
*
|
||||
* The initiator will be copied into the topology,
|
||||
* the caller should free anything allocated to store the initiator,
|
||||
* for instance the cpuset.
|
||||
*
|
||||
* \p flags must be \c 0 for now.
|
||||
*
|
||||
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
|
||||
* when referring to accesses performed by CPU cores.
|
||||
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
|
||||
* but users may for instance use it to provide custom information about
|
||||
* host memory accesses performed by GPUs.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_set_value(hwloc_topology_t topology,
|
||||
hwloc_memattr_id_t attribute,
|
||||
hwloc_obj_t target_node,
|
||||
struct hwloc_location *initiator,
|
||||
unsigned long flags,
|
||||
hwloc_uint64_t value);
|
||||
|
||||
/** \brief Return the target NUMA nodes that have some values for a given attribute.
|
||||
*
|
||||
* Return targets for the given attribute in the \p targets array
|
||||
@@ -482,8 +460,6 @@ hwloc_memattr_get_best_initiator(hwloc_topology_t topology,
|
||||
* NUMA nodes with hwloc_get_local_numanode_objs() and then look at their attribute
|
||||
* values.
|
||||
*
|
||||
* \return 0 on success or -1 on error.
|
||||
*
|
||||
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
|
||||
* when referring to accesses performed by CPU cores.
|
||||
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
|
||||
@@ -515,16 +491,12 @@ hwloc_memattr_get_targets(hwloc_topology_t topology,
|
||||
* The returned initiators should not be modified or freed,
|
||||
* they belong to the topology.
|
||||
*
|
||||
* \p target_node cannot be \c NULL.
|
||||
*
|
||||
* \p flags must be \c 0 for now.
|
||||
*
|
||||
* If the attribute does not relate to a specific initiator
|
||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
|
||||
* no initiator is returned.
|
||||
*
|
||||
* \return 0 on success or -1 on error.
|
||||
*
|
||||
* \note This function is meant for tools and debugging (listing internal information)
|
||||
* rather than for application queries. Applications should rather select useful
|
||||
* NUMA nodes with hwloc_get_local_numanode_objs() and then look at their attribute
|
||||
@@ -536,131 +508,6 @@ hwloc_memattr_get_initiators(hwloc_topology_t topology,
|
||||
hwloc_obj_t target_node,
|
||||
unsigned long flags,
|
||||
unsigned *nr, struct hwloc_location *initiators, hwloc_uint64_t *values);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/** \defgroup hwlocality_memattrs_manage Managing memory attributes
|
||||
*
|
||||
* Memory attribues are identified by an ID (::hwloc_memattr_id_t)
|
||||
* and a name. hwloc_memattr_get_name() and hwloc_memattr_get_by_name()
|
||||
* convert between them (or return error if the attribute does not exist).
|
||||
*
|
||||
* The set of valid ::hwloc_memattr_id_t is a contigous set starting at \c 0.
|
||||
* It first contains predefined attributes, as listed
|
||||
* in ::hwloc_memattr_id_e (from \c 0 to \c HWLOC_MEMATTR_ID_MAX-1).
|
||||
* Then custom attributes may be dynamically registered with
|
||||
* hwloc_memattr_register(). They will get the following IDs
|
||||
* (\c HWLOC_MEMATTR_ID_MAX for the first one, etc.).
|
||||
*
|
||||
* To iterate over all valid attributes
|
||||
* (either predefined or dynamically registered custom ones),
|
||||
* one may iterate over IDs starting from \c 0 until hwloc_memattr_get_name()
|
||||
* or hwloc_memattr_get_flags() returns an error.
|
||||
*
|
||||
* The values for an existing attribute or for custom dynamically registered ones
|
||||
* may be set or modified with hwloc_memattr_set_value().
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Return the name of a memory attribute.
|
||||
*
|
||||
* The output pointer \p name cannot be \c NULL.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c EINVAL if the attribute does not exist.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_get_name(hwloc_topology_t topology,
|
||||
hwloc_memattr_id_t attribute,
|
||||
const char **name);
|
||||
|
||||
/** \brief Return the flags of the given attribute.
|
||||
*
|
||||
* Flags are a OR'ed set of ::hwloc_memattr_flag_e.
|
||||
*
|
||||
* The output pointer \p flags cannot be \c NULL.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c EINVAL if the attribute does not exist.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_get_flags(hwloc_topology_t topology,
|
||||
hwloc_memattr_id_t attribute,
|
||||
unsigned long *flags);
|
||||
|
||||
/** \brief Memory attribute flags.
|
||||
* Given to hwloc_memattr_register() and returned by hwloc_memattr_get_flags().
|
||||
*/
|
||||
enum hwloc_memattr_flag_e {
|
||||
/** \brief The best nodes for this memory attribute are those with the higher values.
|
||||
* For instance Bandwidth.
|
||||
*/
|
||||
HWLOC_MEMATTR_FLAG_HIGHER_FIRST = (1UL<<0),
|
||||
/** \brief The best nodes for this memory attribute are those with the lower values.
|
||||
* For instance Latency.
|
||||
*/
|
||||
HWLOC_MEMATTR_FLAG_LOWER_FIRST = (1UL<<1),
|
||||
/** \brief The value returned for this memory attribute depends on the given initiator.
|
||||
* For instance Bandwidth and Latency, but not Capacity.
|
||||
*/
|
||||
HWLOC_MEMATTR_FLAG_NEED_INITIATOR = (1UL<<2)
|
||||
};
|
||||
|
||||
/** \brief Register a new memory attribute.
|
||||
*
|
||||
* Add a new custom memory attribute.
|
||||
* Flags are a OR'ed set of ::hwloc_memattr_flag_e. It must contain one of
|
||||
* ::HWLOC_MEMATTR_FLAG_HIGHER_FIRST or ::HWLOC_MEMATTR_FLAG_LOWER_FIRST but not both.
|
||||
*
|
||||
* The new attribute \p id is immediately after the last existing attribute ID
|
||||
* (which is either the ID of the last registered attribute if any,
|
||||
* or the ID of the last predefined attribute in ::hwloc_memattr_id_e).
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c EINVAL if an invalid set of flags is given.
|
||||
* \return -1 with errno set to \c EBUSY if another attribute already uses this name.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_register(hwloc_topology_t topology,
|
||||
const char *name,
|
||||
unsigned long flags,
|
||||
hwloc_memattr_id_t *id);
|
||||
|
||||
/** \brief Set an attribute value for a specific target NUMA node.
|
||||
*
|
||||
* If the attribute does not relate to a specific initiator
|
||||
* (it does not have the flag ::HWLOC_MEMATTR_FLAG_NEED_INITIATOR),
|
||||
* location \p initiator is ignored and may be \c NULL.
|
||||
*
|
||||
* The initiator will be copied into the topology,
|
||||
* the caller should free anything allocated to store the initiator,
|
||||
* for instance the cpuset.
|
||||
*
|
||||
* \p target_node cannot be \c NULL.
|
||||
*
|
||||
* \p attribute cannot be ::HWLOC_MEMATTR_FLAG_ID_CAPACITY or
|
||||
* ::HWLOC_MEMATTR_FLAG_ID_LOCALITY.
|
||||
*
|
||||
* \p flags must be \c 0 for now.
|
||||
*
|
||||
* \note The initiator \p initiator should be of type ::HWLOC_LOCATION_TYPE_CPUSET
|
||||
* when referring to accesses performed by CPU cores.
|
||||
* ::HWLOC_LOCATION_TYPE_OBJECT is currently unused internally by hwloc,
|
||||
* but users may for instance use it to provide custom information about
|
||||
* host memory accesses performed by GPUs.
|
||||
*
|
||||
* \return 0 on success or -1 on error.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_memattr_set_value(hwloc_topology_t topology,
|
||||
hwloc_memattr_id_t attribute,
|
||||
hwloc_obj_t target_node,
|
||||
struct hwloc_location *initiator,
|
||||
unsigned long flags,
|
||||
hwloc_uint64_t value);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
5
src/3rdparty/hwloc/include/hwloc/nvml.h
vendored
5
src/3rdparty/hwloc/include/hwloc/nvml.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2012-2023 Inria. All rights reserved.
|
||||
* Copyright © 2012-2021 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -51,9 +51,6 @@ extern "C" {
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_nvml_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
|
||||
27
src/3rdparty/hwloc/include/hwloc/opencl.h
vendored
27
src/3rdparty/hwloc/include/hwloc/opencl.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2012-2023 Inria. All rights reserved.
|
||||
* Copyright © 2012-2021 Inria. All rights reserved.
|
||||
* Copyright © 2013, 2018 Université Bordeaux. All right reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
@@ -41,15 +41,6 @@ extern "C" {
|
||||
*/
|
||||
/* Copyright (c) 2008-2018 The Khronos Group Inc. */
|
||||
|
||||
/* needs "cl_khr_pci_bus_info" device extension, but not strictly required for clGetDeviceInfo() */
|
||||
typedef struct {
|
||||
cl_uint pci_domain;
|
||||
cl_uint pci_bus;
|
||||
cl_uint pci_device;
|
||||
cl_uint pci_function;
|
||||
} hwloc_cl_device_pci_bus_info_khr;
|
||||
#define HWLOC_CL_DEVICE_PCI_BUS_INFO_KHR 0x410F
|
||||
|
||||
/* needs "cl_amd_device_attribute_query" device extension, but not strictly required for clGetDeviceInfo() */
|
||||
#define HWLOC_CL_DEVICE_TOPOLOGY_AMD 0x4037
|
||||
typedef union {
|
||||
@@ -78,28 +69,15 @@ typedef union {
|
||||
/** \brief Return the domain, bus and device IDs of the OpenCL device \p device.
|
||||
*
|
||||
* Device \p device must match the local machine.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_opencl_get_device_pci_busid(cl_device_id device,
|
||||
unsigned *domain, unsigned *bus, unsigned *dev, unsigned *func)
|
||||
{
|
||||
hwloc_cl_device_topology_amd amdtopo;
|
||||
hwloc_cl_device_pci_bus_info_khr khrbusinfo;
|
||||
cl_uint nvbus, nvslot, nvdomain;
|
||||
cl_int clret;
|
||||
|
||||
clret = clGetDeviceInfo(device, HWLOC_CL_DEVICE_PCI_BUS_INFO_KHR, sizeof(khrbusinfo), &khrbusinfo, NULL);
|
||||
if (CL_SUCCESS == clret) {
|
||||
*domain = (unsigned) khrbusinfo.pci_domain;
|
||||
*bus = (unsigned) khrbusinfo.pci_bus;
|
||||
*dev = (unsigned) khrbusinfo.pci_device;
|
||||
*func = (unsigned) khrbusinfo.pci_function;
|
||||
return 0;
|
||||
}
|
||||
|
||||
clret = clGetDeviceInfo(device, HWLOC_CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
|
||||
if (CL_SUCCESS == clret
|
||||
&& HWLOC_CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD == amdtopo.raw.type) {
|
||||
@@ -148,9 +126,6 @@ hwloc_opencl_get_device_pci_busid(cl_device_id device,
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux with the AMD or NVIDIA OpenCL implementation; other systems will simply
|
||||
* get a full cpuset.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if the device could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_opencl_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
||||
* Copyright © 2009-2021 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -57,9 +57,6 @@ extern "C" {
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_ibv_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
|
||||
147
src/3rdparty/hwloc/include/hwloc/plugins.h
vendored
147
src/3rdparty/hwloc/include/hwloc/plugins.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2013-2024 Inria. All rights reserved.
|
||||
* Copyright © 2013-2022 Inria. All rights reserved.
|
||||
* Copyright © 2016 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
@@ -26,7 +26,7 @@ struct hwloc_backend;
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_disc_components Components and Plugins: Discovery components and backends
|
||||
/** \defgroup hwlocality_disc_components Components and Plugins: Discovery components
|
||||
*
|
||||
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
|
||||
*
|
||||
@@ -90,6 +90,18 @@ struct hwloc_disc_component {
|
||||
struct hwloc_disc_component * next;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_disc_backends Components and Plugins: Discovery backends
|
||||
*
|
||||
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Discovery phase */
|
||||
typedef enum hwloc_disc_phase_e {
|
||||
/** \brief xml or synthetic, platform-specific components such as bgq.
|
||||
@@ -152,7 +164,7 @@ struct hwloc_disc_status {
|
||||
*/
|
||||
unsigned excluded_phases;
|
||||
|
||||
/** \brief OR'ed set of ::hwloc_disc_status_flag_e */
|
||||
/** \brief OR'ed set of hwloc_disc_status_flag_e */
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
@@ -301,64 +313,6 @@ struct hwloc_component {
|
||||
void * data;
|
||||
};
|
||||
|
||||
/** \brief Make sure that plugins can lookup core symbols.
|
||||
*
|
||||
* This is a sanity check to avoid lazy-lookup failures when libhwloc
|
||||
* is loaded within a plugin, and later tries to load its own plugins.
|
||||
* This may fail (and abort the program) if libhwloc symbols are in a
|
||||
* private namespace.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 if the plugin cannot be successfully loaded. The caller
|
||||
* plugin init() callback should return a negative error code as well.
|
||||
*
|
||||
* Plugins should call this function in their init() callback to avoid
|
||||
* later crashes if lazy symbol resolution is used by the upper layer that
|
||||
* loaded hwloc (e.g. OpenCL implementations using dlopen with RTLD_LAZY).
|
||||
*
|
||||
* \note The build system must define HWLOC_INSIDE_PLUGIN if and only if
|
||||
* building the caller as a plugin.
|
||||
*
|
||||
* \note This function should remain inline so plugins can call it even
|
||||
* when they cannot find libhwloc symbols.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_plugin_check_namespace(const char *pluginname __hwloc_attribute_unused, const char *symbol __hwloc_attribute_unused)
|
||||
{
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
void *sym;
|
||||
#ifdef HWLOC_HAVE_LTDL
|
||||
lt_dlhandle handle = lt_dlopen(NULL);
|
||||
#else
|
||||
void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
|
||||
#endif
|
||||
if (!handle)
|
||||
/* cannot check, assume things will work */
|
||||
return 0;
|
||||
#ifdef HWLOC_HAVE_LTDL
|
||||
sym = lt_dlsym(handle, symbol);
|
||||
lt_dlclose(handle);
|
||||
#else
|
||||
sym = dlsym(handle, symbol);
|
||||
dlclose(handle);
|
||||
#endif
|
||||
if (!sym) {
|
||||
static int verboseenv_checked = 0;
|
||||
static int verboseenv_value = 0;
|
||||
if (!verboseenv_checked) {
|
||||
const char *verboseenv = getenv("HWLOC_PLUGINS_VERBOSE");
|
||||
verboseenv_value = verboseenv ? atoi(verboseenv) : 0;
|
||||
verboseenv_checked = 1;
|
||||
}
|
||||
if (verboseenv_value)
|
||||
fprintf(stderr, "Plugin `%s' disabling itself because it cannot find the `%s' core symbol.\n",
|
||||
pluginname, symbol);
|
||||
return -1;
|
||||
}
|
||||
#endif /* HWLOC_INSIDE_PLUGIN */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -468,6 +422,64 @@ HWLOC_DECLSPEC int hwloc_obj_add_children_sets(hwloc_obj_t obj);
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_reconnect(hwloc_topology_t topology, unsigned long flags __hwloc_attribute_unused);
|
||||
|
||||
/** \brief Make sure that plugins can lookup core symbols.
|
||||
*
|
||||
* This is a sanity check to avoid lazy-lookup failures when libhwloc
|
||||
* is loaded within a plugin, and later tries to load its own plugins.
|
||||
* This may fail (and abort the program) if libhwloc symbols are in a
|
||||
* private namespace.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 if the plugin cannot be successfully loaded. The caller
|
||||
* plugin init() callback should return a negative error code as well.
|
||||
*
|
||||
* Plugins should call this function in their init() callback to avoid
|
||||
* later crashes if lazy symbol resolution is used by the upper layer that
|
||||
* loaded hwloc (e.g. OpenCL implementations using dlopen with RTLD_LAZY).
|
||||
*
|
||||
* \note The build system must define HWLOC_INSIDE_PLUGIN if and only if
|
||||
* building the caller as a plugin.
|
||||
*
|
||||
* \note This function should remain inline so plugins can call it even
|
||||
* when they cannot find libhwloc symbols.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_plugin_check_namespace(const char *pluginname __hwloc_attribute_unused, const char *symbol __hwloc_attribute_unused)
|
||||
{
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
void *sym;
|
||||
#ifdef HWLOC_HAVE_LTDL
|
||||
lt_dlhandle handle = lt_dlopen(NULL);
|
||||
#else
|
||||
void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
|
||||
#endif
|
||||
if (!handle)
|
||||
/* cannot check, assume things will work */
|
||||
return 0;
|
||||
#ifdef HWLOC_HAVE_LTDL
|
||||
sym = lt_dlsym(handle, symbol);
|
||||
lt_dlclose(handle);
|
||||
#else
|
||||
sym = dlsym(handle, symbol);
|
||||
dlclose(handle);
|
||||
#endif
|
||||
if (!sym) {
|
||||
static int verboseenv_checked = 0;
|
||||
static int verboseenv_value = 0;
|
||||
if (!verboseenv_checked) {
|
||||
const char *verboseenv = getenv("HWLOC_PLUGINS_VERBOSE");
|
||||
verboseenv_value = verboseenv ? atoi(verboseenv) : 0;
|
||||
verboseenv_checked = 1;
|
||||
}
|
||||
if (verboseenv_value)
|
||||
fprintf(stderr, "Plugin `%s' disabling itself because it cannot find the `%s' core symbol.\n",
|
||||
pluginname, symbol);
|
||||
return -1;
|
||||
}
|
||||
#endif /* HWLOC_INSIDE_PLUGIN */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -633,19 +645,6 @@ HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_parent_by_busid(struct hwloc_to
|
||||
*/
|
||||
HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func);
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_components_distances Components and Plugins: distances
|
||||
*
|
||||
* \note These structures and functions may change when ::HWLOC_COMPONENT_ABI is modified.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Handle to a new distances structure during its addition to the topology. */
|
||||
typedef void * hwloc_backend_distances_add_handle_t;
|
||||
|
||||
|
||||
14
src/3rdparty/hwloc/include/hwloc/rename.h
vendored
14
src/3rdparty/hwloc/include/hwloc/rename.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright © 2010-2025 Inria. All rights reserved.
|
||||
* Copyright © 2010-2022 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -176,7 +176,6 @@ extern "C" {
|
||||
|
||||
#define hwloc_topology_insert_misc_object HWLOC_NAME(topology_insert_misc_object)
|
||||
#define hwloc_topology_alloc_group_object HWLOC_NAME(topology_alloc_group_object)
|
||||
#define hwloc_topology_free_group_object HWLOC_NAME(topology_free_group_object)
|
||||
#define hwloc_topology_insert_group_object HWLOC_NAME(topology_insert_group_object)
|
||||
#define hwloc_obj_add_other_obj_sets HWLOC_NAME(obj_add_other_obj_sets)
|
||||
#define hwloc_topology_refresh HWLOC_NAME(topology_refresh)
|
||||
@@ -210,7 +209,6 @@ extern "C" {
|
||||
|
||||
#define hwloc_obj_get_info_by_name HWLOC_NAME(obj_get_info_by_name)
|
||||
#define hwloc_obj_add_info HWLOC_NAME(obj_add_info)
|
||||
#define hwloc_obj_set_subtype HWLOC_NAME(obj_set_subtype)
|
||||
|
||||
#define HWLOC_CPUBIND_PROCESS HWLOC_NAME_CAPS(CPUBIND_PROCESS)
|
||||
#define HWLOC_CPUBIND_THREAD HWLOC_NAME_CAPS(CPUBIND_THREAD)
|
||||
@@ -233,7 +231,6 @@ extern "C" {
|
||||
#define HWLOC_MEMBIND_FIRSTTOUCH HWLOC_NAME_CAPS(MEMBIND_FIRSTTOUCH)
|
||||
#define HWLOC_MEMBIND_BIND HWLOC_NAME_CAPS(MEMBIND_BIND)
|
||||
#define HWLOC_MEMBIND_INTERLEAVE HWLOC_NAME_CAPS(MEMBIND_INTERLEAVE)
|
||||
#define HWLOC_MEMBIND_WEIGHTED_INTERLEAVE HWLOC_NAME_CAPS(MEMBIND_WEIGHTED_INTERLEAVE)
|
||||
#define HWLOC_MEMBIND_NEXTTOUCH HWLOC_NAME_CAPS(MEMBIND_NEXTTOUCH)
|
||||
#define HWLOC_MEMBIND_MIXED HWLOC_NAME_CAPS(MEMBIND_MIXED)
|
||||
|
||||
@@ -409,10 +406,8 @@ extern "C" {
|
||||
#define hwloc_local_numanode_flag_e HWLOC_NAME(local_numanode_flag_e)
|
||||
#define HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY HWLOC_NAME_CAPS(LOCAL_NUMANODE_FLAG_LARGER_LOCALITY)
|
||||
#define HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY HWLOC_NAME_CAPS(LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY)
|
||||
#define HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY HWLOC_NAME_CAPS(LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY)
|
||||
#define HWLOC_LOCAL_NUMANODE_FLAG_ALL HWLOC_NAME_CAPS(LOCAL_NUMANODE_FLAG_ALL)
|
||||
#define hwloc_get_local_numanode_objs HWLOC_NAME(get_local_numanode_objs)
|
||||
#define hwloc_topology_get_default_nodeset HWLOC_NAME(topology_get_default_nodeset)
|
||||
|
||||
#define hwloc_memattr_get_name HWLOC_NAME(memattr_get_name)
|
||||
#define hwloc_memattr_get_flags HWLOC_NAME(memattr_get_flags)
|
||||
@@ -564,7 +559,6 @@ extern "C" {
|
||||
|
||||
/* opencl.h */
|
||||
|
||||
#define hwloc_cl_device_pci_bus_info_khr HWLOC_NAME(cl_device_pci_bus_info_khr)
|
||||
#define hwloc_cl_device_topology_amd HWLOC_NAME(cl_device_topology_amd)
|
||||
#define hwloc_opencl_get_device_pci_busid HWLOC_NAME(opencl_get_device_pci_ids)
|
||||
#define hwloc_opencl_get_device_cpuset HWLOC_NAME(opencl_get_device_cpuset)
|
||||
@@ -601,9 +595,7 @@ extern "C" {
|
||||
/* levelzero.h */
|
||||
|
||||
#define hwloc_levelzero_get_device_cpuset HWLOC_NAME(levelzero_get_device_cpuset)
|
||||
#define hwloc_levelzero_get_sysman_device_cpuset HWLOC_NAME(levelzero_get_sysman_device_cpuset)
|
||||
#define hwloc_levelzero_get_device_osdev HWLOC_NAME(levelzero_get_device_osdev)
|
||||
#define hwloc_levelzero_get_sysman_device_osdev HWLOC_NAME(levelzero_get_sysman_device_osdev)
|
||||
|
||||
/* gl.h */
|
||||
|
||||
@@ -722,8 +714,6 @@ extern "C" {
|
||||
#define hwloc__obj_type_is_dcache HWLOC_NAME(_obj_type_is_dcache)
|
||||
#define hwloc__obj_type_is_icache HWLOC_NAME(_obj_type_is_icache)
|
||||
|
||||
#define hwloc__pci_link_speed HWLOC_NAME(_pci_link_speed)
|
||||
|
||||
/* private/cpuid-x86.h */
|
||||
|
||||
#define hwloc_have_x86_cpuid HWLOC_NAME(have_x86_cpuid)
|
||||
@@ -817,8 +807,6 @@ extern "C" {
|
||||
#define hwloc_topology_setup_defaults HWLOC_NAME(topology_setup_defaults)
|
||||
#define hwloc_topology_clear HWLOC_NAME(topology_clear)
|
||||
|
||||
#define hwloc__reconnect HWLOC_NAME(_reconnect)
|
||||
|
||||
#define hwloc__attach_memory_object HWLOC_NAME(insert_memory_object)
|
||||
|
||||
#define hwloc_get_obj_by_type_and_gp_index HWLOC_NAME(get_obj_by_type_and_gp_index)
|
||||
|
||||
5
src/3rdparty/hwloc/include/hwloc/rsmi.h
vendored
5
src/3rdparty/hwloc/include/hwloc/rsmi.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2012-2023 Inria. All rights reserved.
|
||||
* Copyright © 2012-2021 Inria. All rights reserved.
|
||||
* Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.
|
||||
* Written by Advanced Micro Devices,
|
||||
* See COPYING in top-level directory.
|
||||
@@ -55,9 +55,6 @@ extern "C" {
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 on error, for instance if device information could not be found.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_rsmi_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
|
||||
17
src/3rdparty/hwloc/include/hwloc/shmem.h
vendored
17
src/3rdparty/hwloc/include/hwloc/shmem.h
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2013-2023 Inria. All rights reserved.
|
||||
* Copyright © 2013-2018 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -48,8 +48,6 @@ extern "C" {
|
||||
* This length (in bytes) must be used in hwloc_shmem_topology_write()
|
||||
* and hwloc_shmem_topology_adopt() later.
|
||||
*
|
||||
* \return the length, or -1 on error, for instance if flags are invalid.
|
||||
*
|
||||
* \note Flags \p flags are currently unused, must be 0.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_shmem_topology_get_length(hwloc_topology_t topology,
|
||||
@@ -76,10 +74,9 @@ HWLOC_DECLSPEC int hwloc_shmem_topology_get_length(hwloc_topology_t topology,
|
||||
* is not. However the caller may also allocate it manually in shared memory
|
||||
* to share it as well.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 with errno set to \c EBUSY if the virtual memory mapping defined
|
||||
* \return -1 with errno set to EBUSY if the virtual memory mapping defined
|
||||
* by \p mmap_address and \p length isn't available in the process.
|
||||
* \return -1 with errno set to \c EINVAL if \p fileoffset, \p mmap_address
|
||||
* \return -1 with errno set to EINVAL if \p fileoffset, \p mmap_address
|
||||
* or \p length aren't page-aligned.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_shmem_topology_write(hwloc_topology_t topology,
|
||||
@@ -115,16 +112,14 @@ HWLOC_DECLSPEC int hwloc_shmem_topology_write(hwloc_topology_t topology,
|
||||
*
|
||||
* \note This function takes care of calling hwloc_topology_abi_check().
|
||||
*
|
||||
* \return 0 on success.
|
||||
*
|
||||
* \return -1 with errno set to \c EBUSY if the virtual memory mapping defined
|
||||
* \return -1 with errno set to EBUSY if the virtual memory mapping defined
|
||||
* by \p mmap_address and \p length isn't available in the process.
|
||||
*
|
||||
* \return -1 with errno set to \c EINVAL if \p fileoffset, \p mmap_address
|
||||
* \return -1 with errno set to EINVAL if \p fileoffset, \p mmap_address
|
||||
* or \p length aren't page-aligned, or do not match what was given to
|
||||
* hwloc_shmem_topology_write() earlier.
|
||||
*
|
||||
* \return -1 with errno set to \c EINVAL if the layout of the topology structure
|
||||
* \return -1 with errno set to EINVAL if the layout of the topology structure
|
||||
* is different between the writer process and the adopter process.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_shmem_topology_adopt(hwloc_topology_t *topologyp,
|
||||
|
||||
22
src/3rdparty/hwloc/include/private/cpuid-x86.h
vendored
22
src/3rdparty/hwloc/include/private/cpuid-x86.h
vendored
@@ -11,22 +11,6 @@
|
||||
#ifndef HWLOC_PRIVATE_CPUID_X86_H
|
||||
#define HWLOC_PRIVATE_CPUID_X86_H
|
||||
|
||||
/* A macro for annotating memory as uninitialized when building with MSAN
|
||||
* (and otherwise having no effect). See below for why this is used with
|
||||
* our custom assembly.
|
||||
*/
|
||||
#ifdef __has_feature
|
||||
#define HWLOC_HAS_FEATURE(name) __has_feature(name)
|
||||
#else
|
||||
#define HWLOC_HAS_FEATURE(name) 0
|
||||
#endif
|
||||
#if HWLOC_HAS_FEATURE(memory_sanitizer) || defined(MEMORY_SANITIZER)
|
||||
#include <sanitizer/msan_interface.h>
|
||||
#define HWLOC_ANNOTATE_MEMORY_IS_INITIALIZED(ptr, len) __msan_unpoison(ptr, len)
|
||||
#else
|
||||
#define HWLOC_ANNOTATE_MEMORY_IS_INITIALIZED(ptr, len)
|
||||
#endif
|
||||
|
||||
#if (defined HWLOC_X86_32_ARCH) && (!defined HWLOC_HAVE_MSVC_CPUIDEX)
|
||||
static __hwloc_inline int hwloc_have_x86_cpuid(void)
|
||||
{
|
||||
@@ -87,18 +71,12 @@ static __hwloc_inline void hwloc_x86_cpuid(unsigned *eax, unsigned *ebx, unsigne
|
||||
"movl %k2,%1\n\t"
|
||||
: "+a" (*eax), "=m" (*ebx), "=&r"(sav_rbx),
|
||||
"+c" (*ecx), "=&d" (*edx));
|
||||
/* MSAN does not recognize the effect of the above assembly on the memory operand
|
||||
* (`"=m"(*ebx)`). This may get improved in MSAN at some point in the future, e.g.
|
||||
* see https://github.com/llvm/llvm-project/pull/77393. */
|
||||
HWLOC_ANNOTATE_MEMORY_IS_INITIALIZED(ebx, sizeof *ebx);
|
||||
#elif defined(HWLOC_X86_32_ARCH)
|
||||
__asm__(
|
||||
"mov %%ebx,%1\n\t"
|
||||
"cpuid\n\t"
|
||||
"xchg %%ebx,%1\n\t"
|
||||
: "+a" (*eax), "=&SD" (*ebx), "+c" (*ecx), "=&d" (*edx));
|
||||
/* See above. */
|
||||
HWLOC_ANNOTATE_MEMORY_IS_INITIALIZED(ebx, sizeof *ebx);
|
||||
#else
|
||||
#error unknown architecture
|
||||
#endif
|
||||
|
||||
35
src/3rdparty/hwloc/include/private/misc.h
vendored
35
src/3rdparty/hwloc/include/private/misc.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2024 Inria. All rights reserved.
|
||||
* Copyright © 2009-2019 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -186,7 +186,7 @@ hwloc_ffsl_from_ffs32(unsigned long x)
|
||||
/**
|
||||
* flsl helpers.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#ifdef __GNUC_____
|
||||
|
||||
# if (__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))
|
||||
# define hwloc_flsl(x) ((x) ? (8*sizeof(long) - __builtin_clzl(x)) : 0)
|
||||
@@ -573,35 +573,4 @@ typedef SSIZE_T ssize_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static __inline float
|
||||
hwloc__pci_link_speed(unsigned generation, unsigned lanes)
|
||||
{
|
||||
float lanespeed;
|
||||
/*
|
||||
* These are single-direction bandwidths only.
|
||||
*
|
||||
* Gen1 used NRZ with 8/10 encoding.
|
||||
* PCIe Gen1 = 2.5GT/s signal-rate per lane x 8/10 = 0.25GB/s data-rate per lane
|
||||
* PCIe Gen2 = 5 GT/s signal-rate per lane x 8/10 = 0.5 GB/s data-rate per lane
|
||||
* Gen3 switched to NRZ with 128/130 encoding.
|
||||
* PCIe Gen3 = 8 GT/s signal-rate per lane x 128/130 = 1 GB/s data-rate per lane
|
||||
* PCIe Gen4 = 16 GT/s signal-rate per lane x 128/130 = 2 GB/s data-rate per lane
|
||||
* PCIe Gen5 = 32 GT/s signal-rate per lane x 128/130 = 4 GB/s data-rate per lane
|
||||
* Gen6 switched to PAM with with 242/256 FLIT (242B payload protected by 8B CRC + 6B FEC).
|
||||
* PCIe Gen6 = 64 GT/s signal-rate per lane x 242/256 = 8 GB/s data-rate per lane
|
||||
* PCIe Gen7 = 128GT/s signal-rate per lane x 242/256 = 16 GB/s data-rate per lane
|
||||
*/
|
||||
|
||||
/* lanespeed in Gbit/s */
|
||||
if (generation <= 2)
|
||||
lanespeed = 2.5f * generation * 0.8f;
|
||||
else if (generation <= 5)
|
||||
lanespeed = 8.0f * (1<<(generation-3)) * 128/130;
|
||||
else
|
||||
lanespeed = 8.0f * (1<<(generation-3)) * 242/256; /* assume Gen8 will be 256 GT/s and so on */
|
||||
|
||||
/* linkspeed in GB/s */
|
||||
return lanespeed * lanes / 8;
|
||||
}
|
||||
|
||||
#endif /* HWLOC_PRIVATE_MISC_H */
|
||||
|
||||
578
src/3rdparty/hwloc/include/private/netloc.h
vendored
Normal file
578
src/3rdparty/hwloc/include/private/netloc.h
vendored
Normal file
@@ -0,0 +1,578 @@
|
||||
/*
|
||||
* Copyright © 2014 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright © 2013-2014 University of Wisconsin-La Crosse.
|
||||
* All rights reserved.
|
||||
* Copyright © 2015-2017 Inria. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
* See COPYING in top-level directory.
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef _NETLOC_PRIVATE_H_
|
||||
#define _NETLOC_PRIVATE_H_
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <netloc.h>
|
||||
#include <netloc/uthash.h>
|
||||
#include <netloc/utarray.h>
|
||||
#include <private/autogen/config.h>
|
||||
|
||||
#define NETLOCFILE_VERSION 1
|
||||
|
||||
#ifdef NETLOC_SCOTCH
|
||||
#include <stdint.h>
|
||||
#include <scotch.h>
|
||||
#define NETLOC_int SCOTCH_Num
|
||||
#else
|
||||
#define NETLOC_int int
|
||||
#endif
|
||||
|
||||
/*
|
||||
* "Import" a few things from hwloc
|
||||
*/
|
||||
#define __netloc_attribute_unused __hwloc_attribute_unused
|
||||
#define __netloc_attribute_malloc __hwloc_attribute_malloc
|
||||
#define __netloc_attribute_const __hwloc_attribute_const
|
||||
#define __netloc_attribute_pure __hwloc_attribute_pure
|
||||
#define __netloc_attribute_deprecated __hwloc_attribute_deprecated
|
||||
#define __netloc_attribute_may_alias __hwloc_attribute_may_alias
|
||||
#define NETLOC_DECLSPEC HWLOC_DECLSPEC
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Types
|
||||
**********************************************************************/
|
||||
|
||||
/**
|
||||
* Definitions for Comparators
|
||||
* \sa These are the return values from the following functions:
|
||||
* netloc_network_compare, netloc_dt_edge_t_compare, netloc_dt_node_t_compare
|
||||
*/
|
||||
typedef enum {
|
||||
NETLOC_CMP_SAME = 0, /**< Compared as the Same */
|
||||
NETLOC_CMP_SIMILAR = -1, /**< Compared as Similar, but not the Same */
|
||||
NETLOC_CMP_DIFF = -2 /**< Compared as Different */
|
||||
} netloc_compare_type_t;
|
||||
|
||||
/**
|
||||
* Enumerated type for the various types of supported networks
|
||||
*/
|
||||
typedef enum {
|
||||
NETLOC_NETWORK_TYPE_ETHERNET = 1, /**< Ethernet network */
|
||||
NETLOC_NETWORK_TYPE_INFINIBAND = 2, /**< InfiniBand network */
|
||||
NETLOC_NETWORK_TYPE_INVALID = 3 /**< Invalid network */
|
||||
} netloc_network_type_t;
|
||||
|
||||
/**
|
||||
* Enumerated type for the various types of supported topologies
|
||||
*/
|
||||
typedef enum {
|
||||
NETLOC_TOPOLOGY_TYPE_INVALID = -1, /**< Invalid */
|
||||
NETLOC_TOPOLOGY_TYPE_TREE = 1, /**< Tree */
|
||||
} netloc_topology_type_t;
|
||||
|
||||
/**
|
||||
* Enumerated type for the various types of nodes
|
||||
*/
|
||||
typedef enum {
|
||||
NETLOC_NODE_TYPE_HOST = 0, /**< Host (a.k.a., network addressable endpoint - e.g., MAC Address) node */
|
||||
NETLOC_NODE_TYPE_SWITCH = 1, /**< Switch node */
|
||||
NETLOC_NODE_TYPE_INVALID = 2 /**< Invalid node */
|
||||
} netloc_node_type_t;
|
||||
|
||||
typedef enum {
|
||||
NETLOC_ARCH_TREE = 0, /* Fat tree */
|
||||
} netloc_arch_type_t;
|
||||
|
||||
|
||||
/* Pre declarations to avoid inter dependency problems */
|
||||
/** \cond IGNORE */
|
||||
struct netloc_topology_t;
|
||||
typedef struct netloc_topology_t netloc_topology_t;
|
||||
struct netloc_node_t;
|
||||
typedef struct netloc_node_t netloc_node_t;
|
||||
struct netloc_edge_t;
|
||||
typedef struct netloc_edge_t netloc_edge_t;
|
||||
struct netloc_physical_link_t;
|
||||
typedef struct netloc_physical_link_t netloc_physical_link_t;
|
||||
struct netloc_path_t;
|
||||
typedef struct netloc_path_t netloc_path_t;
|
||||
|
||||
struct netloc_arch_tree_t;
|
||||
typedef struct netloc_arch_tree_t netloc_arch_tree_t;
|
||||
struct netloc_arch_node_t;
|
||||
typedef struct netloc_arch_node_t netloc_arch_node_t;
|
||||
struct netloc_arch_node_slot_t;
|
||||
typedef struct netloc_arch_node_slot_t netloc_arch_node_slot_t;
|
||||
struct netloc_arch_t;
|
||||
typedef struct netloc_arch_t netloc_arch_t;
|
||||
/** \endcond */
|
||||
|
||||
/**
|
||||
* \struct netloc_topology_t
|
||||
* \brief Netloc Topology Context
|
||||
*
|
||||
* An opaque data structure used to reference a network topology.
|
||||
*
|
||||
* \note Must be initialized with \ref netloc_topology_construct()
|
||||
*/
|
||||
struct netloc_topology_t {
|
||||
/** Topology path */
|
||||
char *topopath;
|
||||
/** Subnet ID */
|
||||
char *subnet_id;
|
||||
|
||||
/** Node List */
|
||||
netloc_node_t *nodes; /* Hash table of nodes by physical_id */
|
||||
netloc_node_t *nodesByHostname; /* Hash table of nodes by hostname */
|
||||
|
||||
netloc_physical_link_t *physical_links; /* Hash table with physcial links */
|
||||
|
||||
/** Partition List */
|
||||
UT_array *partitions;
|
||||
|
||||
/** Hwloc topology List */
|
||||
char *hwlocpath;
|
||||
UT_array *topos;
|
||||
hwloc_topology_t *hwloc_topos;
|
||||
|
||||
/** Type of the graph */
|
||||
netloc_topology_type_t type;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Netloc Node Type
|
||||
*
|
||||
* Represents the concept of a node (a.k.a., vertex, endpoint) within a network
|
||||
* graph. This could be a server or a network switch. The \ref node_type parameter
|
||||
* will distinguish the exact type of node this represents in the graph.
|
||||
*/
|
||||
struct netloc_node_t {
|
||||
UT_hash_handle hh; /* makes this structure hashable with physical_id */
|
||||
UT_hash_handle hh2; /* makes this structure hashable with hostname */
|
||||
|
||||
/** Physical ID of the node */
|
||||
char physical_id[20];
|
||||
|
||||
/** Logical ID of the node (if any) */
|
||||
int logical_id;
|
||||
|
||||
/** Type of the node */
|
||||
netloc_node_type_t type;
|
||||
|
||||
/* Pointer to physical_links */
|
||||
UT_array *physical_links;
|
||||
|
||||
/** Description information from discovery (if any) */
|
||||
char *description;
|
||||
|
||||
/**
|
||||
* Application-given private data pointer.
|
||||
* Initialized to NULL, and not used by the netloc library.
|
||||
*/
|
||||
void * userdata;
|
||||
|
||||
/** Outgoing edges from this node */
|
||||
netloc_edge_t *edges;
|
||||
|
||||
UT_array *subnodes; /* the group of nodes for the virtual nodes */
|
||||
|
||||
netloc_path_t *paths;
|
||||
|
||||
char *hostname;
|
||||
|
||||
UT_array *partitions; /* index in the list from the topology */
|
||||
|
||||
hwloc_topology_t hwlocTopo;
|
||||
int hwlocTopoIdx;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Netloc Edge Type
|
||||
*
|
||||
* Represents the concept of a directed edge within a network graph.
|
||||
*
|
||||
* \note We do not point to the netloc_node_t structure directly to
|
||||
* simplify the representation, and allow the information to more easily
|
||||
* be entered into the data store without circular references.
|
||||
* \todo JJH Is the note above still true?
|
||||
*/
|
||||
struct netloc_edge_t {
|
||||
UT_hash_handle hh; /* makes this structure hashable */
|
||||
|
||||
netloc_node_t *dest;
|
||||
|
||||
int id;
|
||||
|
||||
/** Pointers to the parent node */
|
||||
netloc_node_t *node;
|
||||
|
||||
/* Pointer to physical_links */
|
||||
UT_array *physical_links;
|
||||
|
||||
/** total gbits of the links */
|
||||
float total_gbits;
|
||||
|
||||
UT_array *partitions; /* index in the list from the topology */
|
||||
|
||||
UT_array *subnode_edges; /* for edges going to virtual nodes */
|
||||
|
||||
struct netloc_edge_t *other_way;
|
||||
|
||||
/**
|
||||
* Application-given private data pointer.
|
||||
* Initialized to NULL, and not used by the netloc library.
|
||||
*/
|
||||
void * userdata;
|
||||
};
|
||||
|
||||
|
||||
struct netloc_physical_link_t {
|
||||
UT_hash_handle hh; /* makes this structure hashable */
|
||||
|
||||
int id; // TODO long long
|
||||
netloc_node_t *src;
|
||||
netloc_node_t *dest;
|
||||
int ports[2];
|
||||
char *width;
|
||||
char *speed;
|
||||
|
||||
netloc_edge_t *edge;
|
||||
|
||||
int other_way_id;
|
||||
struct netloc_physical_link_t *other_way;
|
||||
|
||||
UT_array *partitions; /* index in the list from the topology */
|
||||
|
||||
/** gbits of the link from speed and width */
|
||||
float gbits;
|
||||
|
||||
/** Description information from discovery (if any) */
|
||||
char *description;
|
||||
};
|
||||
|
||||
struct netloc_path_t {
|
||||
UT_hash_handle hh; /* makes this structure hashable */
|
||||
char dest_id[20];
|
||||
UT_array *links;
|
||||
};
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Architecture structures
|
||||
**********************************************************************/
|
||||
struct netloc_arch_tree_t {
|
||||
NETLOC_int num_levels;
|
||||
NETLOC_int *degrees;
|
||||
NETLOC_int *cost;
|
||||
};
|
||||
|
||||
struct netloc_arch_node_t {
|
||||
UT_hash_handle hh; /* makes this structure hashable */
|
||||
char *name; /* Hash key */
|
||||
netloc_node_t *node; /* Corresponding node */
|
||||
int idx_in_topo; /* idx with ghost hosts to have complete topo */
|
||||
int num_slots; /* it is not the real number of slots but the maximum slot idx */
|
||||
int *slot_idx; /* corresponding idx in slot_tree */
|
||||
int *slot_os_idx; /* corresponding os index for each leaf in tree */
|
||||
netloc_arch_tree_t *slot_tree; /* Tree built from hwloc */
|
||||
int num_current_slots; /* Number of PUs */
|
||||
NETLOC_int *current_slots; /* indices in the complete tree */
|
||||
int *slot_ranks; /* corresponding MPI rank for each leaf in tree */
|
||||
};
|
||||
|
||||
struct netloc_arch_node_slot_t {
|
||||
netloc_arch_node_t *node;
|
||||
int slot;
|
||||
};
|
||||
|
||||
struct netloc_arch_t {
|
||||
netloc_topology_t *topology;
|
||||
int has_slots; /* if slots are included in the architecture */
|
||||
netloc_arch_type_t type;
|
||||
union {
|
||||
netloc_arch_tree_t *node_tree;
|
||||
netloc_arch_tree_t *global_tree;
|
||||
} arch;
|
||||
netloc_arch_node_t *nodes_by_name;
|
||||
netloc_arch_node_slot_t *node_slot_by_idx; /* node_slot by index in complete topo */
|
||||
NETLOC_int num_current_hosts; /* if has_slots, host is a slot, else host is a node */
|
||||
NETLOC_int *current_hosts; /* indices in the complete topology */
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
* Topology Functions
|
||||
**********************************************************************/
|
||||
/**
|
||||
* Allocate a topology handle.
|
||||
*
|
||||
* User is responsible for calling \ref netloc_detach on the topology handle.
|
||||
* The network parameter information is deep copied into the topology handle, so the
|
||||
* user may destruct the network handle after calling this function and/or reuse
|
||||
* the network handle.
|
||||
*
|
||||
* \returns NETLOC_SUCCESS on success
|
||||
* \returns NETLOC_ERROR upon an error.
|
||||
*/
|
||||
netloc_topology_t *netloc_topology_construct(char *path);
|
||||
|
||||
/**
|
||||
* Destruct a topology handle
|
||||
*
|
||||
* \param topology A valid pointer to a \ref netloc_topology_t handle created
|
||||
* from a prior call to \ref netloc_topology_construct.
|
||||
*
|
||||
* \returns NETLOC_SUCCESS on success
|
||||
* \returns NETLOC_ERROR upon an error.
|
||||
*/
|
||||
int netloc_topology_destruct(netloc_topology_t *topology);
|
||||
|
||||
int netloc_topology_find_partition_idx(netloc_topology_t *topology, char *partition_name);
|
||||
|
||||
int netloc_topology_read_hwloc(netloc_topology_t *topology, int num_nodes,
|
||||
netloc_node_t **node_list);
|
||||
|
||||
#define netloc_topology_iter_partitions(topology,partition) \
|
||||
for ((partition) = (char **)utarray_front(topology->partitions); \
|
||||
(partition) != NULL; \
|
||||
(partition) = (char **)utarray_next(topology->partitions, partition))
|
||||
|
||||
#define netloc_topology_iter_hwloctopos(topology,hwloctopo) \
|
||||
for ((hwloctopo) = (char **)utarray_front(topology->topos); \
|
||||
(hwloctopo) != NULL; \
|
||||
(hwloctopo) = (char **)utarray_next(topology->topos, hwloctopo))
|
||||
|
||||
#define netloc_topology_find_node(topology,node_id,node) \
|
||||
HASH_FIND_STR(topology->nodes, node_id, node)
|
||||
|
||||
#define netloc_topology_iter_nodes(topology,node,_tmp) \
|
||||
HASH_ITER(hh, topology->nodes, node, _tmp)
|
||||
|
||||
#define netloc_topology_num_nodes(topology) \
|
||||
HASH_COUNT(topology->nodes)
|
||||
|
||||
/*************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for netloc_node_t
|
||||
*
|
||||
* User is responsible for calling the destructor on the handle.
|
||||
*
|
||||
* Returns
|
||||
* A newly allocated pointer to the network information.
|
||||
*/
|
||||
netloc_node_t *netloc_node_construct(void);
|
||||
|
||||
/**
|
||||
* Destructor for netloc_node_t
|
||||
*
|
||||
* \param node A valid node handle
|
||||
*
|
||||
* Returns
|
||||
* NETLOC_SUCCESS on success
|
||||
* NETLOC_ERROR on error
|
||||
*/
|
||||
int netloc_node_destruct(netloc_node_t *node);
|
||||
|
||||
char *netloc_node_pretty_print(netloc_node_t* node);
|
||||
|
||||
#define netloc_node_get_num_subnodes(node) \
|
||||
utarray_len((node)->subnodes)
|
||||
|
||||
#define netloc_node_get_subnode(node,i) \
|
||||
(*(netloc_node_t **)utarray_eltptr((node)->subnodes, (i)))
|
||||
|
||||
#define netloc_node_get_num_edges(node) \
|
||||
utarray_len((node)->edges)
|
||||
|
||||
#define netloc_node_get_edge(node,i) \
|
||||
(*(netloc_edge_t **)utarray_eltptr((node)->edges, (i)))
|
||||
|
||||
#define netloc_node_iter_edges(node,edge,_tmp) \
|
||||
HASH_ITER(hh, node->edges, edge, _tmp)
|
||||
|
||||
#define netloc_node_iter_paths(node,path,_tmp) \
|
||||
HASH_ITER(hh, node->paths, path, _tmp)
|
||||
|
||||
#define netloc_node_is_host(node) \
|
||||
(node->type == NETLOC_NODE_TYPE_HOST)
|
||||
|
||||
#define netloc_node_is_switch(node) \
|
||||
(node->type == NETLOC_NODE_TYPE_SWITCH)
|
||||
|
||||
#define netloc_node_iter_paths(node, path,_tmp) \
|
||||
HASH_ITER(hh, node->paths, path, _tmp)
|
||||
|
||||
int netloc_node_is_in_partition(netloc_node_t *node, int partition);
|
||||
|
||||
/*************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for netloc_edge_t
|
||||
*
|
||||
* User is responsible for calling the destructor on the handle.
|
||||
*
|
||||
* Returns
|
||||
* A newly allocated pointer to the edge information.
|
||||
*/
|
||||
netloc_edge_t *netloc_edge_construct(void);
|
||||
|
||||
/**
|
||||
* Destructor for netloc_edge_t
|
||||
*
|
||||
* \param edge A valid edge handle
|
||||
*
|
||||
* Returns
|
||||
* NETLOC_SUCCESS on success
|
||||
* NETLOC_ERROR on error
|
||||
*/
|
||||
int netloc_edge_destruct(netloc_edge_t *edge);
|
||||
|
||||
char * netloc_edge_pretty_print(netloc_edge_t* edge);
|
||||
|
||||
void netloc_edge_reset_uid(void);
|
||||
|
||||
int netloc_edge_is_in_partition(netloc_edge_t *edge, int partition);
|
||||
|
||||
#define netloc_edge_get_num_links(edge) \
|
||||
utarray_len((edge)->physical_links)
|
||||
|
||||
#define netloc_edge_get_link(edge,i) \
|
||||
(*(netloc_physical_link_t **)utarray_eltptr((edge)->physical_links, (i)))
|
||||
|
||||
#define netloc_edge_get_num_subedges(edge) \
|
||||
utarray_len((edge)->subnode_edges)
|
||||
|
||||
#define netloc_edge_get_subedge(edge,i) \
|
||||
(*(netloc_edge_t **)utarray_eltptr((edge)->subnode_edges, (i)))
|
||||
|
||||
/*************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for netloc_physical_link_t
|
||||
*
|
||||
* User is responsible for calling the destructor on the handle.
|
||||
*
|
||||
* Returns
|
||||
* A newly allocated pointer to the physical link information.
|
||||
*/
|
||||
netloc_physical_link_t * netloc_physical_link_construct(void);
|
||||
|
||||
/**
|
||||
* Destructor for netloc_physical_link_t
|
||||
*
|
||||
* Returns
|
||||
* NETLOC_SUCCESS on success
|
||||
* NETLOC_ERROR on error
|
||||
*/
|
||||
int netloc_physical_link_destruct(netloc_physical_link_t *link);
|
||||
|
||||
char * netloc_link_pretty_print(netloc_physical_link_t* link);
|
||||
|
||||
/*************************************************/
|
||||
|
||||
|
||||
netloc_path_t *netloc_path_construct(void);
|
||||
int netloc_path_destruct(netloc_path_t *path);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Architecture functions
|
||||
**********************************************************************/
|
||||
|
||||
netloc_arch_t * netloc_arch_construct(void);
|
||||
|
||||
int netloc_arch_destruct(netloc_arch_t *arch);
|
||||
|
||||
int netloc_arch_build(netloc_arch_t *arch, int add_slots);
|
||||
|
||||
int netloc_arch_set_current_resources(netloc_arch_t *arch);
|
||||
|
||||
int netloc_arch_set_global_resources(netloc_arch_t *arch);
|
||||
|
||||
int netloc_arch_node_get_hwloc_info(netloc_arch_node_t *arch);
|
||||
|
||||
void netloc_arch_tree_complete(netloc_arch_tree_t *tree, UT_array **down_degrees_by_level,
|
||||
int num_hosts, int **parch_idx);
|
||||
|
||||
NETLOC_int netloc_arch_tree_num_leaves(netloc_arch_tree_t *tree);
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Access functions of various elements of the topology
|
||||
**********************************************************************/
|
||||
|
||||
#define netloc_get_num_partitions(object) \
|
||||
utarray_len((object)->partitions)
|
||||
|
||||
#define netloc_get_partition(object,i) \
|
||||
(*(int *)utarray_eltptr((object)->partitions, (i)))
|
||||
|
||||
|
||||
#define netloc_path_iter_links(path,link) \
|
||||
for ((link) = (netloc_physical_link_t **)utarray_front(path->links); \
|
||||
(link) != NULL; \
|
||||
(link) = (netloc_physical_link_t **)utarray_next(path->links, link))
|
||||
|
||||
/**********************************************************************
|
||||
* Misc functions
|
||||
**********************************************************************/
|
||||
|
||||
/**
|
||||
* Decode the network type
|
||||
*
|
||||
* \param net_type A valid member of the \ref netloc_network_type_t type
|
||||
*
|
||||
* \returns NULL if the type is invalid
|
||||
* \returns A string for that \ref netloc_network_type_t type
|
||||
*/
|
||||
static inline const char * netloc_network_type_decode(netloc_network_type_t net_type) {
|
||||
if( NETLOC_NETWORK_TYPE_ETHERNET == net_type ) {
|
||||
return "ETH";
|
||||
}
|
||||
else if( NETLOC_NETWORK_TYPE_INFINIBAND == net_type ) {
|
||||
return "IB";
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the node type
|
||||
*
|
||||
* \param node_type A valid member of the \ref netloc_node_type_t type
|
||||
*
|
||||
* \returns NULL if the type is invalid
|
||||
* \returns A string for that \ref netloc_node_type_t type
|
||||
*/
|
||||
static inline const char * netloc_node_type_decode(netloc_node_type_t node_type) {
|
||||
if( NETLOC_NODE_TYPE_SWITCH == node_type ) {
|
||||
return "SW";
|
||||
}
|
||||
else if( NETLOC_NODE_TYPE_HOST == node_type ) {
|
||||
return "CA";
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t netloc_line_get(char **lineptr, size_t *n, FILE *stream);
|
||||
|
||||
char *netloc_line_get_next_token(char **string, char c);
|
||||
|
||||
int netloc_build_comm_mat(char *filename, int *pn, double ***pmat);
|
||||
|
||||
#define STRDUP_IF_NOT_NULL(str) (NULL == str ? NULL : strdup(str))
|
||||
#define STR_EMPTY_IF_NULL(str) (NULL == str ? "" : str)
|
||||
|
||||
|
||||
#endif // _NETLOC_PRIVATE_H_
|
||||
14
src/3rdparty/hwloc/include/private/private.h
vendored
14
src/3rdparty/hwloc/include/private/private.h
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2025 Inria. All rights reserved.
|
||||
* Copyright © 2009-2022 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012, 2020 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
*
|
||||
@@ -245,12 +245,6 @@ struct hwloc_topology {
|
||||
* temporary variables during discovery
|
||||
*/
|
||||
|
||||
/* set to 1 at the beginning of load() if the filter of any cpu cache type (L1 to L3i) is not NONE,
|
||||
* may be checked by backends before querying caches
|
||||
* (when they don't know the level of caches they are querying).
|
||||
*/
|
||||
int want_some_cpu_caches;
|
||||
|
||||
/* machine-wide memory.
|
||||
* temporarily stored there by OSes that only provide this without NUMA information,
|
||||
* and actually used later by the core.
|
||||
@@ -302,9 +296,6 @@ extern void hwloc__reorder_children(hwloc_obj_t parent);
|
||||
extern void hwloc_topology_setup_defaults(struct hwloc_topology *topology);
|
||||
extern void hwloc_topology_clear(struct hwloc_topology *topology);
|
||||
|
||||
#define _HWLOC_RECONNECT_FLAG_KEEPSTRUCTURE (1UL<<0)
|
||||
extern int hwloc__reconnect(struct hwloc_topology *topology, unsigned long flags);
|
||||
|
||||
/* insert memory object as memory child of normal parent */
|
||||
extern struct hwloc_obj * hwloc__attach_memory_object(struct hwloc_topology *topology, hwloc_obj_t parent,
|
||||
hwloc_obj_t obj, const char *reason);
|
||||
@@ -429,7 +420,7 @@ extern void hwloc_internal_memattrs_need_refresh(hwloc_topology_t topology);
|
||||
extern void hwloc_internal_memattrs_refresh(hwloc_topology_t topology);
|
||||
extern int hwloc_internal_memattrs_dup(hwloc_topology_t new, hwloc_topology_t old);
|
||||
extern int hwloc_internal_memattr_set_value(hwloc_topology_t topology, hwloc_memattr_id_t id, hwloc_obj_type_t target_type, hwloc_uint64_t target_gp_index, unsigned target_os_index, struct hwloc_internal_location_s *initiator, hwloc_uint64_t value);
|
||||
extern int hwloc_internal_memattrs_guess_memory_tiers(hwloc_topology_t topology, int force_subtype);
|
||||
extern int hwloc_internal_memattrs_guess_memory_tiers(hwloc_topology_t topology);
|
||||
|
||||
extern void hwloc_internal_cpukinds_init(hwloc_topology_t topology);
|
||||
extern int hwloc_internal_cpukinds_rank(hwloc_topology_t topology);
|
||||
@@ -486,7 +477,6 @@ extern char * hwloc_progname(struct hwloc_topology *topology);
|
||||
#define HWLOC_GROUP_KIND_INTEL_DIE 104 /* no subkind */
|
||||
#define HWLOC_GROUP_KIND_S390_BOOK 110 /* subkind 0 is book, subkind 1 is drawer (group of books) */
|
||||
#define HWLOC_GROUP_KIND_AMD_COMPUTE_UNIT 120 /* no subkind */
|
||||
#define HWLOC_GROUP_KIND_AMD_COMPLEX 121 /* no subkind */
|
||||
/* then, OS-specific groups */
|
||||
#define HWLOC_GROUP_KIND_SOLARIS_PG_HW_PERF 200 /* subkind is group width */
|
||||
#define HWLOC_GROUP_KIND_AIX_SDL_UNKNOWN 210 /* subkind is SDL level */
|
||||
|
||||
8
src/3rdparty/hwloc/include/private/xml.h
vendored
8
src/3rdparty/hwloc/include/private/xml.h
vendored
@@ -19,14 +19,13 @@ HWLOC_DECLSPEC int hwloc__xml_verbose(void);
|
||||
typedef struct hwloc__xml_import_state_s {
|
||||
struct hwloc__xml_import_state_s *parent;
|
||||
|
||||
/* globals shared between the entire stack of states during import */
|
||||
/* globals shared because the entire stack of states during import */
|
||||
struct hwloc_xml_backend_data_s *global;
|
||||
|
||||
/* opaque data used to store backend-specific data.
|
||||
* statically allocated to allow stack-allocation by the common code without knowing actual backend needs.
|
||||
* libxml is 3 ptrs. nolibxml is 3 ptr + one int.
|
||||
*/
|
||||
char data[4 * SIZEOF_VOID_P];
|
||||
char data[32];
|
||||
} * hwloc__xml_import_state_t;
|
||||
|
||||
struct hwloc__xml_imported_v1distances_s {
|
||||
@@ -75,9 +74,8 @@ typedef struct hwloc__xml_export_state_s {
|
||||
|
||||
/* opaque data used to store backend-specific data.
|
||||
* statically allocated to allow stack-allocation by the common code without knowing actual backend needs.
|
||||
* libxml is 1 ptr. nolibxml is 1 ptr + 2 size_t + 3 ints.
|
||||
*/
|
||||
char data[6 * SIZEOF_VOID_P];
|
||||
char data[40];
|
||||
} * hwloc__xml_export_state_t;
|
||||
|
||||
HWLOC_DECLSPEC void hwloc__xml_export_topology(hwloc__xml_export_state_t parentstate, hwloc_topology_t topology, unsigned long flags);
|
||||
|
||||
3
src/3rdparty/hwloc/src/bind.c
vendored
3
src/3rdparty/hwloc/src/bind.c
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2024 Inria. All rights reserved.
|
||||
* Copyright © 2009-2020 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010, 2012 Université Bordeaux
|
||||
* Copyright © 2011-2015 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -287,7 +287,6 @@ static __hwloc_inline int hwloc__check_membind_policy(hwloc_membind_policy_t pol
|
||||
|| policy == HWLOC_MEMBIND_FIRSTTOUCH
|
||||
|| policy == HWLOC_MEMBIND_BIND
|
||||
|| policy == HWLOC_MEMBIND_INTERLEAVE
|
||||
|| policy == HWLOC_MEMBIND_WEIGHTED_INTERLEAVE
|
||||
|| policy == HWLOC_MEMBIND_NEXTTOUCH)
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
59
src/3rdparty/hwloc/src/bitmap.c
vendored
59
src/3rdparty/hwloc/src/bitmap.c
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2024 Inria. All rights reserved.
|
||||
* Copyright © 2009-2020 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -245,7 +245,6 @@ int hwloc_bitmap_copy(struct hwloc_bitmap_s * dst, const struct hwloc_bitmap_s *
|
||||
/* Strings always use 32bit groups */
|
||||
#define HWLOC_PRIxSUBBITMAP "%08lx"
|
||||
#define HWLOC_BITMAP_SUBSTRING_SIZE 32
|
||||
#define HWLOC_BITMAP_SUBSTRING_FULL_VALUE 0xFFFFFFFFUL
|
||||
#define HWLOC_BITMAP_SUBSTRING_LENGTH (HWLOC_BITMAP_SUBSTRING_SIZE/4)
|
||||
#define HWLOC_BITMAP_STRING_PER_LONG (HWLOC_BITS_PER_LONG/HWLOC_BITMAP_SUBSTRING_SIZE)
|
||||
|
||||
@@ -262,7 +261,6 @@ int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const stru
|
||||
const unsigned long accum_mask = ~0UL;
|
||||
#else /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */
|
||||
const unsigned long accum_mask = ((1UL << HWLOC_BITMAP_SUBSTRING_SIZE) - 1) << (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE);
|
||||
int merge_with_infinite_prefix = 0;
|
||||
#endif /* HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE */
|
||||
|
||||
HWLOC__BITMAP_CHECK(set);
|
||||
@@ -281,9 +279,6 @@ int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const stru
|
||||
res = size>0 ? (int)size - 1 : 0;
|
||||
tmp += res;
|
||||
size -= res;
|
||||
#if HWLOC_BITS_PER_LONG > HWLOC_BITMAP_SUBSTRING_SIZE
|
||||
merge_with_infinite_prefix = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
i=(int) set->ulongs_count-1;
|
||||
@@ -299,24 +294,16 @@ int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const stru
|
||||
}
|
||||
|
||||
while (i>=0 || accumed) {
|
||||
unsigned long value;
|
||||
|
||||
/* Refill accumulator */
|
||||
if (!accumed) {
|
||||
accum = set->ulongs[i--];
|
||||
accumed = HWLOC_BITS_PER_LONG;
|
||||
}
|
||||
value = (accum & accum_mask) >> (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE);
|
||||
|
||||
#if HWLOC_BITS_PER_LONG > HWLOC_BITMAP_SUBSTRING_SIZE
|
||||
if (merge_with_infinite_prefix && value == HWLOC_BITMAP_SUBSTRING_FULL_VALUE) {
|
||||
/* first full subbitmap merged with infinite prefix */
|
||||
res = 0;
|
||||
} else
|
||||
#endif
|
||||
if (value) {
|
||||
if (accum & accum_mask) {
|
||||
/* print the whole subset if not empty */
|
||||
res = hwloc_snprintf(tmp, size, needcomma ? ",0x" HWLOC_PRIxSUBBITMAP : "0x" HWLOC_PRIxSUBBITMAP, value);
|
||||
res = hwloc_snprintf(tmp, size, needcomma ? ",0x" HWLOC_PRIxSUBBITMAP : "0x" HWLOC_PRIxSUBBITMAP,
|
||||
(accum & accum_mask) >> (HWLOC_BITS_PER_LONG - HWLOC_BITMAP_SUBSTRING_SIZE));
|
||||
needcomma = 1;
|
||||
} else if (i == -1 && accumed == HWLOC_BITMAP_SUBSTRING_SIZE) {
|
||||
/* print a single 0 to mark the last subset */
|
||||
@@ -336,7 +323,6 @@ int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, const stru
|
||||
#else
|
||||
accum <<= HWLOC_BITMAP_SUBSTRING_SIZE;
|
||||
accumed -= HWLOC_BITMAP_SUBSTRING_SIZE;
|
||||
merge_with_infinite_prefix = 0;
|
||||
#endif
|
||||
|
||||
if (res >= size)
|
||||
@@ -376,8 +362,7 @@ int hwloc_bitmap_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restric
|
||||
{
|
||||
const char * current = string;
|
||||
unsigned long accum = 0;
|
||||
int count = 0;
|
||||
int ulongcount;
|
||||
int count=0;
|
||||
int infinite = 0;
|
||||
|
||||
/* count how many substrings there are */
|
||||
@@ -398,20 +383,9 @@ int hwloc_bitmap_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc_restric
|
||||
count--;
|
||||
}
|
||||
|
||||
ulongcount = (count + HWLOC_BITMAP_STRING_PER_LONG - 1) / HWLOC_BITMAP_STRING_PER_LONG;
|
||||
if (hwloc_bitmap_reset_by_ulongs(set, ulongcount) < 0)
|
||||
if (hwloc_bitmap_reset_by_ulongs(set, (count + HWLOC_BITMAP_STRING_PER_LONG - 1) / HWLOC_BITMAP_STRING_PER_LONG) < 0)
|
||||
return -1;
|
||||
|
||||
set->infinite = 0; /* will be updated later */
|
||||
|
||||
#if HWLOC_BITS_PER_LONG != HWLOC_BITMAP_SUBSTRING_SIZE
|
||||
if (infinite && (count % HWLOC_BITMAP_STRING_PER_LONG) != 0) {
|
||||
/* accumulate substrings of the first ulong that are hidden in the infinite prefix */
|
||||
int i;
|
||||
for(i = (count % HWLOC_BITMAP_STRING_PER_LONG); i < HWLOC_BITMAP_STRING_PER_LONG; i++)
|
||||
accum |= (HWLOC_BITMAP_SUBSTRING_FULL_VALUE << (i*HWLOC_BITMAP_SUBSTRING_SIZE));
|
||||
}
|
||||
#endif
|
||||
set->infinite = 0;
|
||||
|
||||
while (*current != '\0') {
|
||||
unsigned long val;
|
||||
@@ -570,9 +544,6 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co
|
||||
ssize_t size = buflen;
|
||||
char *tmp = buf;
|
||||
int res, ret = 0;
|
||||
#if HWLOC_BITS_PER_LONG == 64
|
||||
int merge_with_infinite_prefix = 0;
|
||||
#endif
|
||||
int started = 0;
|
||||
int i;
|
||||
|
||||
@@ -592,9 +563,6 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co
|
||||
res = size>0 ? (int)size - 1 : 0;
|
||||
tmp += res;
|
||||
size -= res;
|
||||
#if HWLOC_BITS_PER_LONG == 64
|
||||
merge_with_infinite_prefix = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
i=set->ulongs_count-1;
|
||||
@@ -614,11 +582,7 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co
|
||||
if (started) {
|
||||
/* print the whole subset */
|
||||
#if HWLOC_BITS_PER_LONG == 64
|
||||
if (merge_with_infinite_prefix && (val & 0xffffffff00000000UL) == 0xffffffff00000000UL) {
|
||||
res = hwloc_snprintf(tmp, size, "%08lx", val & 0xffffffffUL);
|
||||
} else {
|
||||
res = hwloc_snprintf(tmp, size, "%016lx", val);
|
||||
}
|
||||
res = hwloc_snprintf(tmp, size, "%016lx", val);
|
||||
#else
|
||||
res = hwloc_snprintf(tmp, size, "%08lx", val);
|
||||
#endif
|
||||
@@ -635,9 +599,6 @@ int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, co
|
||||
res = size>0 ? (int)size - 1 : 0;
|
||||
tmp += res;
|
||||
size -= res;
|
||||
#if HWLOC_BITS_PER_LONG == 64
|
||||
merge_with_infinite_prefix = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* if didn't display anything, display 0x0 */
|
||||
@@ -718,10 +679,6 @@ int hwloc_bitmap_taskset_sscanf(struct hwloc_bitmap_s *set, const char * __hwloc
|
||||
goto failed;
|
||||
|
||||
set->ulongs[count-1] = val;
|
||||
if (infinite && tmpchars != HWLOC_BITS_PER_LONG/4) {
|
||||
/* infinite prefix with partial substring, fill remaining bits */
|
||||
set->ulongs[count-1] |= (~0ULL)<<(4*tmpchars);
|
||||
}
|
||||
|
||||
current += tmpchars;
|
||||
chars -= tmpchars;
|
||||
|
||||
3
src/3rdparty/hwloc/src/components.c
vendored
3
src/3rdparty/hwloc/src/components.c
vendored
@@ -94,7 +94,8 @@ static hwloc_dlhandle hwloc_dlopenext(const char *_filename)
|
||||
{
|
||||
hwloc_dlhandle handle;
|
||||
char *filename = NULL;
|
||||
if (asprintf(&filename, "%s.so", _filename) < 0)
|
||||
(void) asprintf(&filename, "%s.so", _filename);
|
||||
if (!filename)
|
||||
return NULL;
|
||||
handle = dlopen(filename, RTLD_NOW|RTLD_LOCAL);
|
||||
free(filename);
|
||||
|
||||
3
src/3rdparty/hwloc/src/cpukinds.c
vendored
3
src/3rdparty/hwloc/src/cpukinds.c
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020-2024 Inria. All rights reserved.
|
||||
* Copyright © 2020-2022 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -50,7 +50,6 @@ hwloc_internal_cpukinds_dup(hwloc_topology_t new, hwloc_topology_t old)
|
||||
return -1;
|
||||
new->cpukinds = kinds;
|
||||
new->nr_cpukinds = old->nr_cpukinds;
|
||||
new->nr_cpukinds_allocated = old->nr_cpukinds;
|
||||
memcpy(kinds, old->cpukinds, old->nr_cpukinds * sizeof(*kinds));
|
||||
|
||||
for(i=0;i<old->nr_cpukinds; i++) {
|
||||
|
||||
26
src/3rdparty/hwloc/src/diff.c
vendored
26
src/3rdparty/hwloc/src/diff.c
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2013-2023 Inria. All rights reserved.
|
||||
* Copyright © 2013-2022 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -411,30 +411,6 @@ int hwloc_topology_diff_build(hwloc_topology_t topo1,
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
/* cpukinds */
|
||||
if (topo1->nr_cpukinds != topo2->nr_cpukinds)
|
||||
goto roottoocomplex;
|
||||
for(i=0; i<topo1->nr_cpukinds; i++) {
|
||||
struct hwloc_internal_cpukind_s *ic1 = &topo1->cpukinds[i];
|
||||
struct hwloc_internal_cpukind_s *ic2 = &topo2->cpukinds[i];
|
||||
unsigned j;
|
||||
if (!hwloc_bitmap_isequal(ic1->cpuset, ic2->cpuset)
|
||||
|| ic1->efficiency != ic2->efficiency
|
||||
|| ic1->forced_efficiency != ic2->forced_efficiency
|
||||
|| ic1->ranking_value != ic2->ranking_value
|
||||
|| ic1->nr_infos != ic2->nr_infos)
|
||||
goto roottoocomplex;
|
||||
for(j=0; j<ic1->nr_infos; j++) {
|
||||
struct hwloc_info_s *info1 = &ic1->infos[j], *info2 = &ic2->infos[j];
|
||||
if (strcmp(info1->name, info2->name)
|
||||
|| strcmp(info1->value, info2->value)) {
|
||||
goto roottoocomplex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
roottoocomplex:
|
||||
|
||||
36
src/3rdparty/hwloc/src/distances.c
vendored
36
src/3rdparty/hwloc/src/distances.c
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2010-2025 Inria. All rights reserved.
|
||||
* Copyright © 2010-2022 Inria. All rights reserved.
|
||||
* Copyright © 2011-2012 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -624,8 +624,8 @@ void * hwloc_distances_add_create(hwloc_topology_t topology,
|
||||
return NULL;
|
||||
}
|
||||
if ((kind & ~HWLOC_DISTANCES_KIND_ALL)
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_FROM_ALL) > 1
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_MEANS_ALL) > 1) {
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_FROM_ALL) != 1
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_MEANS_ALL) != 1) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
@@ -699,7 +699,7 @@ hwloc_distances_add_commit(hwloc_topology_t topology,
|
||||
}
|
||||
|
||||
/* in case we added some groups, see if we need to reconnect */
|
||||
hwloc__reconnect(topology, 0);
|
||||
hwloc_topology_reconnect(topology, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1387,12 +1387,19 @@ static __hwloc_inline int is_nvswitch(hwloc_obj_t obj)
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__distances_transform_merge_switch_ports(struct hwloc_distances_s *distances)
|
||||
hwloc__distances_transform_merge_switch_ports(hwloc_topology_t topology,
|
||||
struct hwloc_distances_s *distances)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist = hwloc__internal_distances_from_public(topology, distances);
|
||||
hwloc_obj_t *objs = distances->objs;
|
||||
hwloc_uint64_t *values = distances->values;
|
||||
unsigned first, i, j, nbobjs = distances->nbobjs;
|
||||
|
||||
if (strcmp(dist->name, "NVLinkBandwidth")) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* find the first port */
|
||||
first = (unsigned) -1;
|
||||
for(i=0; i<nbobjs; i++)
|
||||
@@ -1428,13 +1435,20 @@ hwloc__distances_transform_merge_switch_ports(struct hwloc_distances_s *distance
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__distances_transform_transitive_closure(struct hwloc_distances_s *distances)
|
||||
hwloc__distances_transform_transitive_closure(hwloc_topology_t topology,
|
||||
struct hwloc_distances_s *distances)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist = hwloc__internal_distances_from_public(topology, distances);
|
||||
hwloc_obj_t *objs = distances->objs;
|
||||
hwloc_uint64_t *values = distances->values;
|
||||
unsigned nbobjs = distances->nbobjs;
|
||||
unsigned i, j, k;
|
||||
|
||||
if (strcmp(dist->name, "NVLinkBandwidth")) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i=0; i<nbobjs; i++) {
|
||||
hwloc_uint64_t bw_i2sw = 0;
|
||||
if (is_nvswitch(objs[i]))
|
||||
@@ -1453,8 +1467,8 @@ hwloc__distances_transform_transitive_closure(struct hwloc_distances_s *distance
|
||||
if (is_nvswitch(objs[k]))
|
||||
bw_sw2j += values[k*nbobjs+j];
|
||||
|
||||
/* bandwidth from i to j now gets indirect bandwidth too, min(i2sw,sw2j) */
|
||||
values[i*nbobjs+j] += bw_i2sw > bw_sw2j ? bw_sw2j : bw_i2sw;
|
||||
/* bandwidth from i to j is now min(i2sw,sw2j) */
|
||||
values[i*nbobjs+j] = bw_i2sw > bw_sw2j ? bw_sw2j : bw_i2sw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1462,7 +1476,7 @@ hwloc__distances_transform_transitive_closure(struct hwloc_distances_s *distance
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_distances_transform(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
hwloc_distances_transform(hwloc_topology_t topology,
|
||||
struct hwloc_distances_s *distances,
|
||||
enum hwloc_distances_transform_e transform,
|
||||
void *transform_attr,
|
||||
@@ -1481,13 +1495,13 @@ hwloc_distances_transform(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
case HWLOC_DISTANCES_TRANSFORM_MERGE_SWITCH_PORTS:
|
||||
{
|
||||
int err;
|
||||
err = hwloc__distances_transform_merge_switch_ports(distances);
|
||||
err = hwloc__distances_transform_merge_switch_ports(topology, distances);
|
||||
if (!err)
|
||||
err = hwloc__distances_transform_remove_null(distances);
|
||||
return err;
|
||||
}
|
||||
case HWLOC_DISTANCES_TRANSFORM_TRANSITIVE_CLOSURE:
|
||||
return hwloc__distances_transform_transitive_closure(distances);
|
||||
return hwloc__distances_transform_transitive_closure(topology, distances);
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
||||
863
src/3rdparty/hwloc/src/memattrs.c
vendored
863
src/3rdparty/hwloc/src/memattrs.c
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2020-2025 Inria. All rights reserved.
|
||||
* Copyright © 2020-2022 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -14,26 +14,13 @@
|
||||
*/
|
||||
|
||||
static __hwloc_inline
|
||||
int hwloc__memattr_get_convenience_value(hwloc_memattr_id_t id,
|
||||
hwloc_obj_t node,
|
||||
hwloc_uint64_t *valuep)
|
||||
hwloc_uint64_t hwloc__memattr_get_convenience_value(hwloc_memattr_id_t id,
|
||||
hwloc_obj_t node)
|
||||
{
|
||||
if (id == HWLOC_MEMATTR_ID_CAPACITY) {
|
||||
if (node->type != HWLOC_OBJ_NUMANODE) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
*valuep = node->attr->numanode.local_memory;
|
||||
return 0;
|
||||
}
|
||||
else if (id == HWLOC_MEMATTR_ID_LOCALITY) {
|
||||
if (!node->cpuset) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
*valuep = hwloc_bitmap_weight(node->cpuset);
|
||||
return 0;
|
||||
}
|
||||
if (id == HWLOC_MEMATTR_ID_CAPACITY)
|
||||
return node->attr->numanode.local_memory;
|
||||
else if (id == HWLOC_MEMATTR_ID_LOCALITY)
|
||||
return hwloc_bitmap_weight(node->cpuset);
|
||||
else
|
||||
assert(0);
|
||||
return 0; /* shut up the compiler */
|
||||
@@ -635,7 +622,7 @@ hwloc_memattr_get_targets(hwloc_topology_t topology,
|
||||
if (found<max) {
|
||||
targets[found] = node;
|
||||
if (values)
|
||||
hwloc__memattr_get_convenience_value(id, node, &values[found]);
|
||||
values[found] = hwloc__memattr_get_convenience_value(id, node);
|
||||
}
|
||||
found++;
|
||||
}
|
||||
@@ -761,7 +748,7 @@ hwloc_memattr_get_initiators(hwloc_topology_t topology,
|
||||
struct hwloc_internal_memattr_target_s *imtg;
|
||||
unsigned i, max;
|
||||
|
||||
if (flags || !target_node) {
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -823,7 +810,7 @@ hwloc_memattr_get_value(hwloc_topology_t topology,
|
||||
struct hwloc_internal_memattr_s *imattr;
|
||||
struct hwloc_internal_memattr_target_s *imtg;
|
||||
|
||||
if (flags || !target_node) {
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -836,7 +823,8 @@ hwloc_memattr_get_value(hwloc_topology_t topology,
|
||||
|
||||
if (imattr->iflags & HWLOC_IMATTR_FLAG_CONVENIENCE) {
|
||||
/* convenience attributes */
|
||||
return hwloc__memattr_get_convenience_value(id, target_node, valuep);
|
||||
*valuep = hwloc__memattr_get_convenience_value(id, target_node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* normal attributes */
|
||||
@@ -948,7 +936,7 @@ hwloc_memattr_set_value(hwloc_topology_t topology,
|
||||
{
|
||||
struct hwloc_internal_location_s iloc, *ilocp;
|
||||
|
||||
if (flags || !target_node) {
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -1019,10 +1007,10 @@ hwloc_memattr_get_best_target(hwloc_topology_t topology,
|
||||
/* convenience attributes */
|
||||
for(j=0; ; j++) {
|
||||
hwloc_obj_t node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, j);
|
||||
hwloc_uint64_t value = 0;
|
||||
hwloc_uint64_t value;
|
||||
if (!node)
|
||||
break;
|
||||
hwloc__memattr_get_convenience_value(id, node, &value);
|
||||
value = hwloc__memattr_get_convenience_value(id, node);
|
||||
hwloc__update_best_target(&best, &best_value, &found,
|
||||
node, value,
|
||||
imattr->flags & HWLOC_MEMATTR_FLAG_HIGHER_FIRST);
|
||||
@@ -1105,7 +1093,7 @@ hwloc_memattr_get_best_initiator(hwloc_topology_t topology,
|
||||
int found;
|
||||
unsigned i;
|
||||
|
||||
if (flags || !target_node) {
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@@ -1158,8 +1146,6 @@ match_local_obj_cpuset(hwloc_obj_t node, hwloc_cpuset_t cpuset, unsigned long fl
|
||||
{
|
||||
if (flags & HWLOC_LOCAL_NUMANODE_FLAG_ALL)
|
||||
return 1;
|
||||
if (flags & HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY)
|
||||
return hwloc_bitmap_intersects(node->cpuset, cpuset);
|
||||
if ((flags & HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY)
|
||||
&& hwloc_bitmap_isincluded(cpuset, node->cpuset))
|
||||
return 1;
|
||||
@@ -1182,7 +1168,6 @@ hwloc_get_local_numanode_objs(hwloc_topology_t topology,
|
||||
|
||||
if (flags & ~(HWLOC_LOCAL_NUMANODE_FLAG_SMALLER_LOCALITY
|
||||
|HWLOC_LOCAL_NUMANODE_FLAG_LARGER_LOCALITY
|
||||
|HWLOC_LOCAL_NUMANODE_FLAG_INTERSECT_LOCALITY
|
||||
| HWLOC_LOCAL_NUMANODE_FLAG_ALL)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
@@ -1229,174 +1214,29 @@ hwloc_get_local_numanode_objs(hwloc_topology_t topology,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_nodes_by_os_index(const void *_a, const void *_b)
|
||||
{
|
||||
const hwloc_obj_t * a = _a, * b = _b;
|
||||
return (*a)->os_index - (*b)->os_index;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_topology_get_default_nodeset(hwloc_topology_t topology,
|
||||
hwloc_nodeset_t nodeset,
|
||||
unsigned long flags)
|
||||
{
|
||||
hwloc_obj_t *nodes;
|
||||
hwloc_bitmap_t remainingcpuset;
|
||||
unsigned nrnodes, i;
|
||||
const char *first_subtype;
|
||||
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
remainingcpuset = hwloc_bitmap_dup(topology->levels[0][0]->cpuset);
|
||||
if (!remainingcpuset)
|
||||
goto out;
|
||||
|
||||
nrnodes = topology->slevels[HWLOC_SLEVEL_NUMANODE].nbobjs;
|
||||
nodes = malloc(nrnodes * sizeof(*nodes));
|
||||
if (!nodes)
|
||||
goto out_with_remainingcpuset;
|
||||
|
||||
memcpy(nodes, topology->slevels[HWLOC_SLEVEL_NUMANODE].objs, nrnodes * sizeof(*nodes));
|
||||
qsort(nodes, nrnodes, sizeof(*nodes), compare_nodes_by_os_index);
|
||||
|
||||
hwloc_bitmap_zero(nodeset);
|
||||
|
||||
/* always take the first node (FIXME: except if unexpected subtype?) */
|
||||
first_subtype = nodes[0]->subtype;
|
||||
hwloc_bitmap_set(nodeset, nodes[0]->os_index);
|
||||
hwloc_bitmap_andnot(remainingcpuset, remainingcpuset, nodes[0]->cpuset);
|
||||
|
||||
/* use all non-intersecting nodes with same subtype */
|
||||
for(i=1; i<nrnodes; i++) {
|
||||
/* check same or no subtype */
|
||||
if (first_subtype) {
|
||||
if (!nodes[i]->subtype || strcmp(first_subtype, nodes[i]->subtype))
|
||||
continue;
|
||||
} else if (nodes[i]->subtype) {
|
||||
continue;
|
||||
}
|
||||
/* take non-overlapping nodes */
|
||||
if (hwloc_bitmap_isincluded(nodes[i]->cpuset, remainingcpuset) /* can be empty */) {
|
||||
hwloc_bitmap_set(nodeset, nodes[i]->os_index);
|
||||
hwloc_bitmap_andnot(remainingcpuset, remainingcpuset, nodes[i]->cpuset);
|
||||
}
|
||||
/* more needed? */
|
||||
if (hwloc_bitmap_iszero(remainingcpuset))
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* find more nodes to cover the entire topology cpuset.
|
||||
* only take what's necessary: first nodes, non-empty */
|
||||
for(i=1; i<nrnodes; i++) {
|
||||
/* already taken? */
|
||||
if (hwloc_bitmap_isset(nodeset, i))
|
||||
continue;
|
||||
/* take non-overlapping nodes, except empty */
|
||||
if (hwloc_bitmap_isincluded(nodes[i]->cpuset, remainingcpuset)
|
||||
&& !hwloc_bitmap_iszero(nodes[i]->cpuset)) {
|
||||
hwloc_bitmap_set(nodeset, nodes[i]->os_index);
|
||||
hwloc_bitmap_andnot(remainingcpuset, remainingcpuset, nodes[i]->cpuset);
|
||||
}
|
||||
/* more needed? */
|
||||
if (hwloc_bitmap_iszero(remainingcpuset))
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
free(nodes);
|
||||
hwloc_bitmap_free(remainingcpuset);
|
||||
return 0;
|
||||
|
||||
out_with_remainingcpuset:
|
||||
hwloc_bitmap_free(remainingcpuset);
|
||||
out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
* Using memattrs to identify HBM/DRAM
|
||||
*/
|
||||
|
||||
enum hwloc_memory_tier_type_e {
|
||||
/* WARNING: keep higher BW types first for compare_tiers_by_bw_and_type() when BW info is missing */
|
||||
HWLOC_MEMORY_TIER_HBM = 1UL<<0,
|
||||
HWLOC_MEMORY_TIER_DRAM = 1UL<<1,
|
||||
HWLOC_MEMORY_TIER_GPU = 1UL<<2,
|
||||
HWLOC_MEMORY_TIER_SPM = 1UL<<3, /* Specific-Purpose Memory is usually HBM, we'll use BW to confirm or force*/
|
||||
HWLOC_MEMORY_TIER_NVM = 1UL<<4,
|
||||
HWLOC_MEMORY_TIER_CXL = 1UL<<5
|
||||
};
|
||||
typedef unsigned long hwloc_memory_tier_type_t;
|
||||
#define HWLOC_MEMORY_TIER_UNKNOWN 0UL
|
||||
|
||||
static const char * hwloc_memory_tier_type_snprintf(hwloc_memory_tier_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case HWLOC_MEMORY_TIER_DRAM: return "DRAM";
|
||||
case HWLOC_MEMORY_TIER_HBM: return "HBM";
|
||||
case HWLOC_MEMORY_TIER_GPU: return "GPUMemory";
|
||||
case HWLOC_MEMORY_TIER_SPM: return "SPM";
|
||||
case HWLOC_MEMORY_TIER_NVM: return "NVM";
|
||||
case HWLOC_MEMORY_TIER_CXL:
|
||||
case HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_DRAM: return "CXL-DRAM";
|
||||
case HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_HBM: return "CXL-HBM";
|
||||
case HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_GPU: return "CXL-GPUMemory";
|
||||
case HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_SPM: return "CXL-SPM";
|
||||
case HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_NVM: return "CXL-NVM";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static hwloc_memory_tier_type_t hwloc_memory_tier_type_sscanf(const char *name)
|
||||
{
|
||||
if (!strcasecmp(name, "DRAM"))
|
||||
return HWLOC_MEMORY_TIER_DRAM;
|
||||
if (!strcasecmp(name, "HBM"))
|
||||
return HWLOC_MEMORY_TIER_HBM;
|
||||
if (!strcasecmp(name, "GPUMemory"))
|
||||
return HWLOC_MEMORY_TIER_GPU;
|
||||
if (!strcasecmp(name, "SPM"))
|
||||
return HWLOC_MEMORY_TIER_SPM;
|
||||
if (!strcasecmp(name, "NVM"))
|
||||
return HWLOC_MEMORY_TIER_NVM;
|
||||
if (!strcasecmp(name, "CXL-DRAM"))
|
||||
return HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_DRAM;
|
||||
if (!strcasecmp(name, "CXL-HBM"))
|
||||
return HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_HBM;
|
||||
if (!strcasecmp(name, "CXL-GPUMemory"))
|
||||
return HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_GPU;
|
||||
if (!strcasecmp(name, "CXL-SPM"))
|
||||
return HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_SPM;
|
||||
if (!strcasecmp(name, "CXL-NVM"))
|
||||
return HWLOC_MEMORY_TIER_CXL|HWLOC_MEMORY_TIER_NVM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* factorized tier, grouping multiple nodes */
|
||||
struct hwloc_memory_tier_s {
|
||||
hwloc_nodeset_t nodeset;
|
||||
uint64_t local_bw_min, local_bw_max;
|
||||
uint64_t local_lat_min, local_lat_max;
|
||||
hwloc_memory_tier_type_t type;
|
||||
};
|
||||
|
||||
/* early tier discovery, one entry per node */
|
||||
struct hwloc_memory_node_info_s {
|
||||
hwloc_obj_t node;
|
||||
uint64_t local_bw;
|
||||
uint64_t local_lat;
|
||||
hwloc_memory_tier_type_t type;
|
||||
unsigned rank;
|
||||
enum hwloc_memory_tier_type_e {
|
||||
/* warning the order is important for guess_memory_tiers() after qsort() */
|
||||
HWLOC_MEMORY_TIER_UNKNOWN,
|
||||
HWLOC_MEMORY_TIER_DRAM,
|
||||
HWLOC_MEMORY_TIER_HBM,
|
||||
HWLOC_MEMORY_TIER_SPM, /* Specific-Purpose Memory is usually HBM, we'll use BW to confirm */
|
||||
HWLOC_MEMORY_TIER_NVM,
|
||||
HWLOC_MEMORY_TIER_GPU,
|
||||
} type;
|
||||
};
|
||||
|
||||
static int compare_node_infos_by_type_and_bw(const void *_a, const void *_b)
|
||||
static int compare_tiers(const void *_a, const void *_b)
|
||||
{
|
||||
const struct hwloc_memory_node_info_s *a = _a, *b = _b;
|
||||
/* sort by type of node first */
|
||||
const struct hwloc_memory_tier_s *a = _a, *b = _b;
|
||||
/* sort by type of tier first */
|
||||
if (a->type != b->type)
|
||||
return a->type - b->type;
|
||||
/* then by bandwidth */
|
||||
@@ -1407,571 +1247,180 @@ static int compare_node_infos_by_type_and_bw(const void *_a, const void *_b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_tiers_by_bw_and_type(const void *_a, const void *_b)
|
||||
int
|
||||
hwloc_internal_memattrs_guess_memory_tiers(hwloc_topology_t topology)
|
||||
{
|
||||
const struct hwloc_memory_tier_s *a = _a, *b = _b;
|
||||
/* sort by (average) BW first */
|
||||
if (a->local_bw_min && b->local_bw_min) {
|
||||
if (a->local_bw_min + a->local_bw_max > b->local_bw_min + b->local_bw_max)
|
||||
return -1;
|
||||
else if (a->local_bw_min + a->local_bw_max < b->local_bw_min + b->local_bw_max)
|
||||
return 1;
|
||||
}
|
||||
/* then by tier type */
|
||||
if (a->type != b->type)
|
||||
return a->type - b->type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_memory_tier_s *
|
||||
hwloc__group_memory_tiers(hwloc_topology_t topology,
|
||||
unsigned *nr_tiers_p)
|
||||
{
|
||||
struct hwloc_internal_memattr_s *imattr_bw, *imattr_lat;
|
||||
struct hwloc_memory_node_info_s *nodeinfos;
|
||||
struct hwloc_internal_memattr_s *imattr;
|
||||
struct hwloc_memory_tier_s *tiers;
|
||||
unsigned nr_tiers;
|
||||
float bw_threshold = 0.1;
|
||||
float lat_threshold = 0.1;
|
||||
const char *env;
|
||||
unsigned i, j, n;
|
||||
const char *env;
|
||||
int spm_is_hbm = -1; /* -1 will guess from BW, 0 no, 1 forced */
|
||||
int mark_dram = 1;
|
||||
unsigned first_spm, first_nvm;
|
||||
hwloc_uint64_t max_unknown_bw, min_spm_bw;
|
||||
|
||||
env = getenv("HWLOC_MEMTIERS_GUESS");
|
||||
if (env) {
|
||||
if (!strcmp(env, "none")) {
|
||||
return 0;
|
||||
} else if (!strcmp(env, "default")) {
|
||||
/* nothing */
|
||||
} else if (!strcmp(env, "spm_is_hbm")) {
|
||||
hwloc_debug("Assuming SPM-tier is HBM, ignore bandwidth\n");
|
||||
spm_is_hbm = 1;
|
||||
} else if (HWLOC_SHOW_CRITICAL_ERRORS()) {
|
||||
fprintf(stderr, "hwloc: Failed to recognize HWLOC_MEMTIERS_GUESS value %s\n", env);
|
||||
}
|
||||
}
|
||||
|
||||
imattr = &topology->memattrs[HWLOC_MEMATTR_ID_BANDWIDTH];
|
||||
|
||||
if (!(imattr->iflags & HWLOC_IMATTR_FLAG_CACHE_VALID))
|
||||
hwloc__imattr_refresh(topology, imattr);
|
||||
|
||||
n = hwloc_get_nbobjs_by_depth(topology, HWLOC_TYPE_DEPTH_NUMANODE);
|
||||
assert(n);
|
||||
|
||||
env = getenv("HWLOC_MEMTIERS_BANDWIDTH_THRESHOLD");
|
||||
if (env)
|
||||
bw_threshold = atof(env);
|
||||
|
||||
env = getenv("HWLOC_MEMTIERS_LATENCY_THRESHOLD");
|
||||
if (env)
|
||||
lat_threshold = atof(env);
|
||||
|
||||
imattr_bw = &topology->memattrs[HWLOC_MEMATTR_ID_BANDWIDTH];
|
||||
imattr_lat = &topology->memattrs[HWLOC_MEMATTR_ID_LATENCY];
|
||||
|
||||
if (!(imattr_bw->iflags & HWLOC_IMATTR_FLAG_CACHE_VALID))
|
||||
hwloc__imattr_refresh(topology, imattr_bw);
|
||||
if (!(imattr_lat->iflags & HWLOC_IMATTR_FLAG_CACHE_VALID))
|
||||
hwloc__imattr_refresh(topology, imattr_lat);
|
||||
|
||||
nodeinfos = malloc(n * sizeof(*nodeinfos));
|
||||
if (!nodeinfos)
|
||||
return NULL;
|
||||
tiers = malloc(n * sizeof(*tiers));
|
||||
if (!tiers)
|
||||
return -1;
|
||||
|
||||
for(i=0; i<n; i++) {
|
||||
hwloc_obj_t node;
|
||||
const char *daxtype;
|
||||
struct hwloc_internal_location_s iloc;
|
||||
struct hwloc_internal_memattr_target_s *imtg;
|
||||
struct hwloc_internal_memattr_target_s *imtg = NULL;
|
||||
struct hwloc_internal_memattr_initiator_s *imi;
|
||||
|
||||
node = hwloc_get_obj_by_depth(topology, HWLOC_TYPE_DEPTH_NUMANODE, i);
|
||||
assert(node);
|
||||
nodeinfos[i].node = node;
|
||||
tiers[i].node = node;
|
||||
|
||||
/* defaults to unknown */
|
||||
nodeinfos[i].type = HWLOC_MEMORY_TIER_UNKNOWN;
|
||||
nodeinfos[i].local_bw = 0;
|
||||
nodeinfos[i].local_lat = 0;
|
||||
/* defaults */
|
||||
tiers[i].type = HWLOC_MEMORY_TIER_UNKNOWN;
|
||||
tiers[i].local_bw = 0; /* unknown */
|
||||
|
||||
daxtype = hwloc_obj_get_info_by_name(node, "DAXType");
|
||||
/* mark NVM, SPM and GPU nodes */
|
||||
if (daxtype && !strcmp(daxtype, "NVM"))
|
||||
tiers[i].type = HWLOC_MEMORY_TIER_NVM;
|
||||
if (daxtype && !strcmp(daxtype, "SPM"))
|
||||
tiers[i].type = HWLOC_MEMORY_TIER_SPM;
|
||||
if (node->subtype && !strcmp(node->subtype, "GPUMemory"))
|
||||
nodeinfos[i].type = HWLOC_MEMORY_TIER_GPU;
|
||||
else if (daxtype && !strcmp(daxtype, "NVM"))
|
||||
nodeinfos[i].type = HWLOC_MEMORY_TIER_NVM;
|
||||
else if (daxtype && !strcmp(daxtype, "SPM"))
|
||||
nodeinfos[i].type = HWLOC_MEMORY_TIER_SPM;
|
||||
/* add CXL flag */
|
||||
if (hwloc_obj_get_info_by_name(node, "CXLDevice") != NULL) {
|
||||
/* CXL is always SPM for now. HBM and DRAM not possible here yet.
|
||||
* Hence remove all but NVM first.
|
||||
*/
|
||||
nodeinfos[i].type &= HWLOC_MEMORY_TIER_NVM;
|
||||
nodeinfos[i].type |= HWLOC_MEMORY_TIER_CXL;
|
||||
}
|
||||
tiers[i].type = HWLOC_MEMORY_TIER_GPU;
|
||||
|
||||
/* get local bandwidth */
|
||||
imtg = NULL;
|
||||
for(j=0; j<imattr_bw->nr_targets; j++)
|
||||
if (imattr_bw->targets[j].obj == node) {
|
||||
imtg = &imattr_bw->targets[j];
|
||||
break;
|
||||
if (spm_is_hbm == -1) {
|
||||
for(j=0; j<imattr->nr_targets; j++)
|
||||
if (imattr->targets[j].obj == node) {
|
||||
imtg = &imattr->targets[j];
|
||||
break;
|
||||
}
|
||||
if (imtg && !hwloc_bitmap_iszero(node->cpuset)) {
|
||||
iloc.type = HWLOC_LOCATION_TYPE_CPUSET;
|
||||
iloc.location.cpuset = node->cpuset;
|
||||
imi = hwloc__memattr_target_get_initiator(imtg, &iloc, 0);
|
||||
if (imi)
|
||||
tiers[i].local_bw = imi->value;
|
||||
}
|
||||
if (imtg && !hwloc_bitmap_iszero(node->cpuset)) {
|
||||
struct hwloc_internal_memattr_initiator_s *imi;
|
||||
iloc.type = HWLOC_LOCATION_TYPE_CPUSET;
|
||||
iloc.location.cpuset = node->cpuset;
|
||||
imi = hwloc__memattr_target_get_initiator(imtg, &iloc, 0);
|
||||
if (imi)
|
||||
nodeinfos[i].local_bw = imi->value;
|
||||
}
|
||||
/* get local latency */
|
||||
imtg = NULL;
|
||||
for(j=0; j<imattr_lat->nr_targets; j++)
|
||||
if (imattr_lat->targets[j].obj == node) {
|
||||
imtg = &imattr_lat->targets[j];
|
||||
break;
|
||||
}
|
||||
if (imtg && !hwloc_bitmap_iszero(node->cpuset)) {
|
||||
struct hwloc_internal_memattr_initiator_s *imi;
|
||||
iloc.type = HWLOC_LOCATION_TYPE_CPUSET;
|
||||
iloc.location.cpuset = node->cpuset;
|
||||
imi = hwloc__memattr_target_get_initiator(imtg, &iloc, 0);
|
||||
if (imi)
|
||||
nodeinfos[i].local_lat = imi->value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort nodes by tier type and bandwidth.
|
||||
*
|
||||
* We could also use the existing subtype but it's not clear it'd be better.
|
||||
* For NVIDIA GPU, "GPUMemory" is set in the Linux backend, and used above to set tier type anyway.
|
||||
* For KNL, the Linux backend sets subtypes and memattrs, sorting by memattrs already works fine.
|
||||
* Existing subtypes could have been imported from XML, usually mostly OK except maybe SPM (fallback for I don't know)?
|
||||
* An envvar (or HWLOC_MEMTIERS_REFRESH special value?) could be passed to ignore existing subtypes,
|
||||
* but "GPUMemory" wouldn't be available anymore, we'd have to use something else like "PCIBusId",
|
||||
* but that one might not always be specific to GPU-backed NUMA nodes?
|
||||
*/
|
||||
hwloc_debug("Sorting memory node infos...\n");
|
||||
qsort(nodeinfos, n, sizeof(*nodeinfos), compare_node_infos_by_type_and_bw);
|
||||
#ifdef HWLOC_DEBUG
|
||||
/* sort tiers */
|
||||
qsort(tiers, n, sizeof(*tiers), compare_tiers);
|
||||
hwloc_debug("Sorting memory tiers...\n");
|
||||
for(i=0; i<n; i++)
|
||||
hwloc_debug(" node info %u = node L#%u P#%u with info type %lx and local BW %llu lat %llu\n",
|
||||
hwloc_debug(" tier %u = node L#%u P#%u with tier type %d and local BW #%llu\n",
|
||||
i,
|
||||
nodeinfos[i].node->logical_index, nodeinfos[i].node->os_index,
|
||||
nodeinfos[i].type,
|
||||
(unsigned long long) nodeinfos[i].local_bw,
|
||||
(unsigned long long) nodeinfos[i].local_lat);
|
||||
#endif
|
||||
/* now we have UNKNOWN nodes (sorted by BW only), then known ones */
|
||||
tiers[i].node->logical_index, tiers[i].node->os_index,
|
||||
tiers[i].type, (unsigned long long) tiers[i].local_bw);
|
||||
|
||||
/* iterate among them and add a rank value.
|
||||
* start from rank 0 and switch to next rank when the type changes or when the BW or latendy difference is > threshold */
|
||||
hwloc_debug("Starting memory tier #0 and iterating over nodes...\n");
|
||||
nodeinfos[0].rank = 0;
|
||||
for(i=1; i<n; i++) {
|
||||
/* reuse the same rank by default */
|
||||
nodeinfos[i].rank = nodeinfos[i-1].rank;
|
||||
/* comparing type */
|
||||
if (nodeinfos[i].type != nodeinfos[i-1].type) {
|
||||
hwloc_debug(" Switching to memory tier #%u starting with node L#%u P#%u because of type\n",
|
||||
nodeinfos[i].rank, nodeinfos[i].node->logical_index, nodeinfos[i].node->os_index);
|
||||
nodeinfos[i].rank++;
|
||||
continue;
|
||||
}
|
||||
/* comparing bandwidth */
|
||||
if (nodeinfos[i].local_bw && nodeinfos[i-1].local_bw) {
|
||||
float bw_ratio = (float)nodeinfos[i].local_bw/(float)nodeinfos[i-1].local_bw;
|
||||
if (bw_ratio < 1.)
|
||||
bw_ratio = 1./bw_ratio;
|
||||
if (bw_ratio > 1.0 + bw_threshold) {
|
||||
nodeinfos[i].rank++;
|
||||
hwloc_debug(" Switching to memory tier #%u starting with node L#%u P#%u because of bandwidth\n",
|
||||
nodeinfos[i].rank, nodeinfos[i].node->logical_index, nodeinfos[i].node->os_index);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* comparing latency */
|
||||
if (nodeinfos[i].local_lat && nodeinfos[i-1].local_lat) {
|
||||
float lat_ratio = (float)nodeinfos[i].local_lat/(float)nodeinfos[i-1].local_lat;
|
||||
if (lat_ratio < 1.)
|
||||
lat_ratio = 1./lat_ratio;
|
||||
if (lat_ratio > 1.0 + lat_threshold) {
|
||||
hwloc_debug(" Switching to memory tier #%u starting with node L#%u P#%u because of latency\n",
|
||||
nodeinfos[i].rank, nodeinfos[i].node->logical_index, nodeinfos[i].node->os_index);
|
||||
nodeinfos[i].rank++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* FIXME: if there are cpuset-intersecting nodes in same tier, split again? */
|
||||
hwloc_debug(" Found %u tiers total\n", nodeinfos[n-1].rank + 1);
|
||||
/* now we have UNKNOWN tiers (sorted by BW), then SPM tiers (sorted by BW), then NVM, then GPU */
|
||||
|
||||
/* now group nodeinfos into factorized tiers */
|
||||
nr_tiers = nodeinfos[n-1].rank + 1;
|
||||
tiers = calloc(nr_tiers, sizeof(*tiers));
|
||||
if (!tiers)
|
||||
goto out_with_nodeinfos;
|
||||
for(i=0; i<nr_tiers; i++) {
|
||||
tiers[i].nodeset = hwloc_bitmap_alloc();
|
||||
if (!tiers[i].nodeset)
|
||||
goto out_with_tiers;
|
||||
tiers[i].local_bw_min = tiers[i].local_bw_max = 0;
|
||||
tiers[i].local_lat_min = tiers[i].local_lat_max = 0;
|
||||
tiers[i].type = HWLOC_MEMORY_TIER_UNKNOWN;
|
||||
}
|
||||
/* iterate over UNKNOWN tiers, and find their BW */
|
||||
for(i=0; i<n; i++) {
|
||||
unsigned rank = nodeinfos[i].rank;
|
||||
assert(rank < nr_tiers);
|
||||
hwloc_bitmap_set(tiers[rank].nodeset, nodeinfos[i].node->os_index);
|
||||
assert(tiers[rank].type == HWLOC_MEMORY_TIER_UNKNOWN
|
||||
|| tiers[rank].type == nodeinfos[i].type);
|
||||
tiers[rank].type = nodeinfos[i].type;
|
||||
/* nodeinfos are sorted in BW order, no need to compare */
|
||||
if (!tiers[rank].local_bw_min)
|
||||
tiers[rank].local_bw_min = nodeinfos[i].local_bw;
|
||||
tiers[rank].local_bw_max = nodeinfos[i].local_bw;
|
||||
/* compare latencies to update min/max */
|
||||
if (!tiers[rank].local_lat_min || nodeinfos[i].local_lat < tiers[rank].local_lat_min)
|
||||
tiers[rank].local_lat_min = nodeinfos[i].local_lat;
|
||||
if (!tiers[rank].local_lat_max || nodeinfos[i].local_lat > tiers[rank].local_lat_max)
|
||||
tiers[rank].local_lat_max = nodeinfos[i].local_lat;
|
||||
if (tiers[i].type > HWLOC_MEMORY_TIER_UNKNOWN)
|
||||
break;
|
||||
}
|
||||
first_spm = i;
|
||||
/* get max BW from first */
|
||||
if (first_spm > 0)
|
||||
max_unknown_bw = tiers[0].local_bw;
|
||||
else
|
||||
max_unknown_bw = 0;
|
||||
|
||||
free(nodeinfos);
|
||||
*nr_tiers_p = nr_tiers;
|
||||
return tiers;
|
||||
/* there are no DRAM or HBM tiers yet */
|
||||
|
||||
out_with_tiers:
|
||||
for(i=0; i<nr_tiers; i++)
|
||||
hwloc_bitmap_free(tiers[i].nodeset);
|
||||
free(tiers);
|
||||
out_with_nodeinfos:
|
||||
free(nodeinfos);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum hwloc_guess_memtiers_flag {
|
||||
HWLOC_GUESS_MEMTIERS_FLAG_NODE0_IS_DRAM = 1<<0,
|
||||
HWLOC_GUESS_MEMTIERS_FLAG_SPM_IS_HBM = 1<<1
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc__guess_dram_hbm_tiers(struct hwloc_memory_tier_s *tier1,
|
||||
struct hwloc_memory_tier_s *tier2,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct hwloc_memory_tier_s *tmp;
|
||||
|
||||
if (!tier1->local_bw_min || !tier2->local_bw_min) {
|
||||
hwloc_debug(" Missing BW info\n");
|
||||
return -1;
|
||||
/* iterate over SPM tiers, and find their BW */
|
||||
for(i=first_spm; i<n; i++) {
|
||||
if (tiers[i].type > HWLOC_MEMORY_TIER_SPM)
|
||||
break;
|
||||
}
|
||||
first_nvm = i;
|
||||
/* get min BW from last */
|
||||
if (first_nvm > first_spm)
|
||||
min_spm_bw = tiers[first_nvm-1].local_bw;
|
||||
else
|
||||
min_spm_bw = 0;
|
||||
|
||||
/* reorder tiers by BW */
|
||||
if (tier1->local_bw_min > tier2->local_bw_min) {
|
||||
tmp = tier1; tier1 = tier2; tier2 = tmp;
|
||||
}
|
||||
/* tier1 < tier2 */
|
||||
/* FIXME: if there's more than 10% between some sets of nodes inside a tier, split it? */
|
||||
/* FIXME: if there are cpuset-intersecting nodes in same tier, abort? */
|
||||
|
||||
hwloc_debug(" tier1 BW %llu-%llu vs tier2 BW %llu-%llu\n",
|
||||
(unsigned long long) tier1->local_bw_min,
|
||||
(unsigned long long) tier1->local_bw_max,
|
||||
(unsigned long long) tier2->local_bw_min,
|
||||
(unsigned long long) tier2->local_bw_max);
|
||||
if (tier2->local_bw_min <= tier1->local_bw_max * 2) {
|
||||
/* tier2 BW isn't 2x tier1, we cannot guess HBM */
|
||||
hwloc_debug(" BW difference isn't >2x\n");
|
||||
return -1;
|
||||
}
|
||||
/* tier2 BW is >2x tier1 */
|
||||
|
||||
if ((flags & HWLOC_GUESS_MEMTIERS_FLAG_NODE0_IS_DRAM)
|
||||
&& hwloc_bitmap_isset(tier2->nodeset, 0)) {
|
||||
/* node0 is not DRAM, and we assume that's not possible */
|
||||
hwloc_debug(" node0 shouldn't have HBM BW\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* assume tier1 == DRAM and tier2 == HBM */
|
||||
tier1->type = HWLOC_MEMORY_TIER_DRAM;
|
||||
tier2->type = HWLOC_MEMORY_TIER_HBM;
|
||||
hwloc_debug(" Success\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__guess_memory_tiers_types(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
unsigned nr_tiers,
|
||||
struct hwloc_memory_tier_s *tiers)
|
||||
{
|
||||
unsigned long flags;
|
||||
const char *env;
|
||||
unsigned nr_unknown, nr_spm;
|
||||
struct hwloc_memory_tier_s *unknown_tier[2], *spm_tier;
|
||||
unsigned i;
|
||||
|
||||
flags = 0;
|
||||
env = getenv("HWLOC_MEMTIERS_GUESS");
|
||||
if (env) {
|
||||
if (!strcmp(env, "none"))
|
||||
return 0;
|
||||
/* by default, we don't guess anything unsure */
|
||||
if (!strcmp(env, "all"))
|
||||
/* enable all typical cases */
|
||||
flags = ~0UL;
|
||||
if (strstr(env, "spm_is_hbm")) {
|
||||
hwloc_debug("Assuming SPM-tier is HBM, ignore bandwidth\n");
|
||||
flags |= HWLOC_GUESS_MEMTIERS_FLAG_SPM_IS_HBM;
|
||||
}
|
||||
if (strstr(env, "node0_is_dram")) {
|
||||
hwloc_debug("Assuming node0 is DRAM\n");
|
||||
flags |= HWLOC_GUESS_MEMTIERS_FLAG_NODE0_IS_DRAM;
|
||||
}
|
||||
}
|
||||
|
||||
if (nr_tiers == 1)
|
||||
/* Likely DRAM only, but could also be HBM-only in non-SPM mode.
|
||||
* We cannot be sure, but it doesn't matter since there's a single tier.
|
||||
if (spm_is_hbm == -1) {
|
||||
/* if we have BW for all SPM and UNKNOWN
|
||||
* and all SPM BW are 2x superior to all UNKNOWN BW
|
||||
*/
|
||||
return 0;
|
||||
hwloc_debug("UNKNOWN-memory-tier max bandwidth %llu\n", (unsigned long long) max_unknown_bw);
|
||||
hwloc_debug("SPM-memory-tier min bandwidth %llu\n", (unsigned long long) min_spm_bw);
|
||||
if (max_unknown_bw > 0 && min_spm_bw > 0 && max_unknown_bw*2 < min_spm_bw) {
|
||||
hwloc_debug("assuming SPM means HBM and !SPM means DRAM since bandwidths are very different\n");
|
||||
spm_is_hbm = 1;
|
||||
} else {
|
||||
hwloc_debug("cannot assume SPM means HBM\n");
|
||||
spm_is_hbm = 0;
|
||||
}
|
||||
}
|
||||
|
||||
nr_unknown = nr_spm = 0;
|
||||
unknown_tier[0] = unknown_tier[1] = spm_tier = NULL;
|
||||
for(i=0; i<nr_tiers; i++) {
|
||||
if (spm_is_hbm) {
|
||||
for(i=0; i<first_spm; i++)
|
||||
tiers[i].type = HWLOC_MEMORY_TIER_DRAM;
|
||||
for(i=first_spm; i<first_nvm; i++)
|
||||
tiers[i].type = HWLOC_MEMORY_TIER_HBM;
|
||||
}
|
||||
|
||||
if (first_spm == n)
|
||||
mark_dram = 0;
|
||||
|
||||
/* now apply subtypes */
|
||||
for(i=0; i<n; i++) {
|
||||
const char *type = NULL;
|
||||
if (tiers[i].node->subtype) /* don't overwrite the existing subtype */
|
||||
continue;
|
||||
switch (tiers[i].type) {
|
||||
case HWLOC_MEMORY_TIER_UNKNOWN:
|
||||
if (nr_unknown < 2)
|
||||
unknown_tier[nr_unknown] = &tiers[i];
|
||||
nr_unknown++;
|
||||
case HWLOC_MEMORY_TIER_DRAM:
|
||||
if (mark_dram)
|
||||
type = "DRAM";
|
||||
break;
|
||||
case HWLOC_MEMORY_TIER_HBM:
|
||||
type = "HBM";
|
||||
break;
|
||||
case HWLOC_MEMORY_TIER_SPM:
|
||||
spm_tier = &tiers[i];
|
||||
nr_spm++;
|
||||
type = "SPM";
|
||||
break;
|
||||
case HWLOC_MEMORY_TIER_NVM:
|
||||
type = "NVM";
|
||||
break;
|
||||
case HWLOC_MEMORY_TIER_DRAM:
|
||||
case HWLOC_MEMORY_TIER_HBM:
|
||||
/* not possible */
|
||||
abort();
|
||||
default:
|
||||
/* ignore HBM, NVM, ... */
|
||||
/* GPU memory is already marked with subtype="GPUMemory",
|
||||
* UNKNOWN doesn't deserve any subtype
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
hwloc_debug("Found %u unknown memory tiers and %u SPM\n",
|
||||
nr_unknown, nr_spm);
|
||||
|
||||
/* Try to guess DRAM + HBM common cases.
|
||||
* Other things we'd like to detect:
|
||||
* single unknown => DRAM or HBM? HBM won't be SPM on HBM-only CPUs
|
||||
* unknown + CXL DRAM => DRAM or HBM?
|
||||
*/
|
||||
if (nr_unknown == 2 && !nr_spm) {
|
||||
/* 2 unknown, could be DRAM + non-SPM HBM */
|
||||
hwloc_debug(" Trying to guess 2 unknown tiers using BW\n");
|
||||
hwloc__guess_dram_hbm_tiers(unknown_tier[0], unknown_tier[1], flags);
|
||||
} else if (nr_unknown == 1 && nr_spm == 1) {
|
||||
/* 1 unknown + 1 SPM, could be DRAM + SPM HBM */
|
||||
hwloc_debug(" Trying to guess 1 unknown + 1 SPM tiers using BW\n");
|
||||
hwloc__guess_dram_hbm_tiers(unknown_tier[0], spm_tier, flags);
|
||||
}
|
||||
|
||||
if (flags & HWLOC_GUESS_MEMTIERS_FLAG_SPM_IS_HBM) {
|
||||
/* force mark SPM as HBM */
|
||||
for(i=0; i<nr_tiers; i++)
|
||||
if (tiers[i].type == HWLOC_MEMORY_TIER_SPM) {
|
||||
hwloc_debug("Forcing SPM tier to HBM");
|
||||
tiers[i].type = HWLOC_MEMORY_TIER_HBM;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & HWLOC_GUESS_MEMTIERS_FLAG_NODE0_IS_DRAM) {
|
||||
/* force mark node0's tier as DRAM if we couldn't guess it */
|
||||
for(i=0; i<nr_tiers; i++)
|
||||
if (hwloc_bitmap_isset(tiers[i].nodeset, 0)
|
||||
&& tiers[i].type == HWLOC_MEMORY_TIER_UNKNOWN) {
|
||||
hwloc_debug("Forcing node0 tier to DRAM");
|
||||
tiers[i].type = HWLOC_MEMORY_TIER_DRAM;
|
||||
break;
|
||||
}
|
||||
if (type) {
|
||||
hwloc_debug("Marking node L#%u P#%u as %s\n", tiers[i].node->logical_index, tiers[i].node->os_index, type);
|
||||
tiers[i].node->subtype = strdup(type);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* parses something like 0xf=HBM;0x0f=DRAM;0x00f=CXL-DRAM */
|
||||
static struct hwloc_memory_tier_s *
|
||||
hwloc__force_memory_tiers(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
unsigned *nr_tiers_p,
|
||||
const char *_env)
|
||||
{
|
||||
struct hwloc_memory_tier_s *tiers = NULL;
|
||||
unsigned nr_tiers, i;
|
||||
hwloc_bitmap_t nodeset = NULL;
|
||||
char *env;
|
||||
const char *tmp;
|
||||
|
||||
env = strdup(_env);
|
||||
if (!env) {
|
||||
fprintf(stderr, "[hwloc/memtiers] failed to duplicate HWLOC_MEMTIERS envvar\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp = env;
|
||||
nr_tiers = 1;
|
||||
while (1) {
|
||||
tmp = strchr(tmp, ';');
|
||||
if (!tmp)
|
||||
break;
|
||||
tmp++;
|
||||
nr_tiers++;
|
||||
}
|
||||
|
||||
nodeset = hwloc_bitmap_alloc();
|
||||
if (!nodeset) {
|
||||
fprintf(stderr, "[hwloc/memtiers] failed to allocated forced tiers' nodeset\n");
|
||||
goto out_with_envvar;
|
||||
}
|
||||
|
||||
tiers = calloc(nr_tiers, sizeof(*tiers));
|
||||
if (!tiers) {
|
||||
fprintf(stderr, "[hwloc/memtiers] failed to allocated forced tiers\n");
|
||||
goto out_with_nodeset;
|
||||
}
|
||||
nr_tiers = 0;
|
||||
|
||||
tmp = env;
|
||||
while (1) {
|
||||
char *end;
|
||||
char *equal;
|
||||
hwloc_memory_tier_type_t type;
|
||||
|
||||
end = strchr(tmp, ';');
|
||||
if (end)
|
||||
*end = '\0';
|
||||
|
||||
equal = strchr(tmp, '=');
|
||||
if (!equal) {
|
||||
fprintf(stderr, "[hwloc/memtiers] missing `=' before end of forced tier description at `%s'\n", tmp);
|
||||
goto out_with_tiers;
|
||||
}
|
||||
*equal = '\0';
|
||||
|
||||
hwloc_bitmap_sscanf(nodeset, tmp);
|
||||
if (hwloc_bitmap_iszero(nodeset)) {
|
||||
fprintf(stderr, "[hwloc/memtiers] empty forced tier nodeset `%s', aborting\n", tmp);
|
||||
goto out_with_tiers;
|
||||
}
|
||||
type = hwloc_memory_tier_type_sscanf(equal+1);
|
||||
if (!type)
|
||||
hwloc_debug("failed to recognize forced tier type `%s'\n", equal+1);
|
||||
tiers[nr_tiers].nodeset = hwloc_bitmap_dup(nodeset);
|
||||
tiers[nr_tiers].type = type;
|
||||
tiers[nr_tiers].local_bw_min = tiers[nr_tiers].local_bw_max = 0;
|
||||
tiers[nr_tiers].local_lat_min = tiers[nr_tiers].local_lat_max = 0;
|
||||
nr_tiers++;
|
||||
if (!end)
|
||||
break;
|
||||
tmp = end+1;
|
||||
}
|
||||
|
||||
free(env);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
hwloc_debug("Forcing %u memory tiers\n", nr_tiers);
|
||||
#ifdef HWLOC_DEBUG
|
||||
for(i=0; i<nr_tiers; i++) {
|
||||
char *s;
|
||||
hwloc_bitmap_asprintf(&s, tiers[i].nodeset);
|
||||
hwloc_debug(" tier #%u type %lx nodeset %s\n", i, tiers[i].type, s);
|
||||
free(s);
|
||||
}
|
||||
#endif
|
||||
*nr_tiers_p = nr_tiers;
|
||||
return tiers;
|
||||
|
||||
out_with_tiers:
|
||||
for(i=0; i<nr_tiers; i++)
|
||||
hwloc_bitmap_free(tiers[i].nodeset);
|
||||
free(tiers);
|
||||
out_with_nodeset:
|
||||
hwloc_bitmap_free(nodeset);
|
||||
out_with_envvar:
|
||||
free(env);
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__apply_memory_tiers_subtypes(hwloc_topology_t topology,
|
||||
unsigned nr_tiers,
|
||||
struct hwloc_memory_tier_s *tiers,
|
||||
int force)
|
||||
{
|
||||
hwloc_obj_t node = NULL;
|
||||
hwloc_debug("Marking node tiers\n");
|
||||
while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NUMANODE, node)) != NULL) {
|
||||
unsigned j;
|
||||
for(j=0; j<nr_tiers; j++) {
|
||||
if (hwloc_bitmap_isset(tiers[j].nodeset, node->os_index)) {
|
||||
const char *subtype = hwloc_memory_tier_type_snprintf(tiers[j].type);
|
||||
if (!node->subtype || force) { /* don't overwrite the existing subtype unless forced */
|
||||
if (subtype) { /* don't set a subtype for unknown tiers */
|
||||
hwloc_debug(" marking node L#%u P#%u as %s (was %s)\n", node->logical_index, node->os_index, subtype, node->subtype);
|
||||
free(node->subtype);
|
||||
node->subtype = strdup(subtype);
|
||||
}
|
||||
} else
|
||||
hwloc_debug(" node L#%u P#%u already marked as %s, not setting %s\n",
|
||||
node->logical_index, node->os_index, node->subtype, subtype);
|
||||
if (nr_tiers > 1) {
|
||||
char tmp[20];
|
||||
snprintf(tmp, sizeof(tmp), "%u", j);
|
||||
hwloc__add_info_nodup(&node->infos, &node->infos_count, "MemoryTier", tmp, 1);
|
||||
}
|
||||
break; /* each node is in a single tier */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nr_tiers > 1) {
|
||||
hwloc_obj_t root = hwloc_get_root_obj(topology);
|
||||
char tmp[20];
|
||||
snprintf(tmp, sizeof(tmp), "%u", nr_tiers);
|
||||
hwloc__add_info_nodup(&root->infos, &root->infos_count, "MemoryTiersNr", tmp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_internal_memattrs_guess_memory_tiers(hwloc_topology_t topology, int force_subtype)
|
||||
{
|
||||
struct hwloc_memory_tier_s *tiers;
|
||||
unsigned nr_tiers;
|
||||
unsigned i;
|
||||
const char *env;
|
||||
|
||||
env = getenv("HWLOC_MEMTIERS");
|
||||
if (env) {
|
||||
if (!strcmp(env, "none"))
|
||||
goto out;
|
||||
tiers = hwloc__force_memory_tiers(topology, &nr_tiers, env);
|
||||
if (tiers) {
|
||||
assert(nr_tiers > 0);
|
||||
force_subtype = 1;
|
||||
goto ready;
|
||||
}
|
||||
}
|
||||
|
||||
tiers = hwloc__group_memory_tiers(topology, &nr_tiers);
|
||||
if (!tiers)
|
||||
goto out;
|
||||
|
||||
hwloc__guess_memory_tiers_types(topology, nr_tiers, tiers);
|
||||
|
||||
/* sort tiers by BW first, then by type */
|
||||
hwloc_debug("Sorting memory tiers...\n");
|
||||
qsort(tiers, nr_tiers, sizeof(*tiers), compare_tiers_by_bw_and_type);
|
||||
|
||||
ready:
|
||||
#ifdef HWLOC_DEBUG
|
||||
for(i=0; i<nr_tiers; i++) {
|
||||
char *s;
|
||||
hwloc_bitmap_asprintf(&s, tiers[i].nodeset);
|
||||
hwloc_debug(" tier %u = nodes %s with type %lx and local BW %llu-%llu lat %llu-%llu\n",
|
||||
i,
|
||||
s, tiers[i].type,
|
||||
(unsigned long long) tiers[i].local_bw_min,
|
||||
(unsigned long long) tiers[i].local_bw_max,
|
||||
(unsigned long long) tiers[i].local_lat_min,
|
||||
(unsigned long long) tiers[i].local_lat_max);
|
||||
free(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
hwloc__apply_memory_tiers_subtypes(topology, nr_tiers, tiers, force_subtype);
|
||||
|
||||
for(i=0; i<nr_tiers; i++)
|
||||
hwloc_bitmap_free(tiers[i].nodeset);
|
||||
free(tiers);
|
||||
out:
|
||||
free(tiers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
28
src/3rdparty/hwloc/src/pci-common.c
vendored
28
src/3rdparty/hwloc/src/pci-common.c
vendored
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2009-2024 Inria. All rights reserved.
|
||||
* Copyright © 2009-2022 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@@ -886,12 +886,36 @@ hwloc_pcidisc_find_linkspeed(const unsigned char *config,
|
||||
unsigned offset, float *linkspeed)
|
||||
{
|
||||
unsigned linksta, speed, width;
|
||||
float lanespeed;
|
||||
|
||||
memcpy(&linksta, &config[offset + HWLOC_PCI_EXP_LNKSTA], 4);
|
||||
speed = linksta & HWLOC_PCI_EXP_LNKSTA_SPEED; /* PCIe generation */
|
||||
width = (linksta & HWLOC_PCI_EXP_LNKSTA_WIDTH) >> 4; /* how many lanes */
|
||||
/*
|
||||
* These are single-direction bandwidths only.
|
||||
*
|
||||
* Gen1 used NRZ with 8/10 encoding.
|
||||
* PCIe Gen1 = 2.5GT/s signal-rate per lane x 8/10 = 0.25GB/s data-rate per lane
|
||||
* PCIe Gen2 = 5 GT/s signal-rate per lane x 8/10 = 0.5 GB/s data-rate per lane
|
||||
* Gen3 switched to NRZ with 128/130 encoding.
|
||||
* PCIe Gen3 = 8 GT/s signal-rate per lane x 128/130 = 1 GB/s data-rate per lane
|
||||
* PCIe Gen4 = 16 GT/s signal-rate per lane x 128/130 = 2 GB/s data-rate per lane
|
||||
* PCIe Gen5 = 32 GT/s signal-rate per lane x 128/130 = 4 GB/s data-rate per lane
|
||||
* Gen6 switched to PAM with with 242/256 FLIT (242B payload protected by 8B CRC + 6B FEC).
|
||||
* PCIe Gen6 = 64 GT/s signal-rate per lane x 242/256 = 8 GB/s data-rate per lane
|
||||
* PCIe Gen7 = 128GT/s signal-rate per lane x 242/256 = 16 GB/s data-rate per lane
|
||||
*/
|
||||
|
||||
*linkspeed = hwloc__pci_link_speed(speed, width);
|
||||
/* lanespeed in Gbit/s */
|
||||
if (speed <= 2)
|
||||
lanespeed = 2.5f * speed * 0.8f;
|
||||
else if (speed <= 5)
|
||||
lanespeed = 8.0f * (1<<(speed-3)) * 128/130;
|
||||
else
|
||||
lanespeed = 8.0f * (1<<(speed-3)) * 242/256; /* assume Gen8 will be 256 GT/s and so on */
|
||||
|
||||
/* linkspeed in GB/s */
|
||||
*linkspeed = lanespeed * width / 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
11
src/3rdparty/hwloc/src/shmem.c
vendored
11
src/3rdparty/hwloc/src/shmem.c
vendored
@@ -23,7 +23,6 @@ struct hwloc_shmem_header {
|
||||
uint32_t header_length; /* where the actual topology starts in the file/mapping */
|
||||
uint64_t mmap_address; /* virtual address to pass to mmap */
|
||||
uint64_t mmap_length; /* length to pass to mmap (includes the header) */
|
||||
/* we will pad the end to a multiple of pointer size so that the topology is well aligned */
|
||||
};
|
||||
|
||||
#define HWLOC_SHMEM_MALLOC_ALIGN 8UL
|
||||
@@ -86,7 +85,6 @@ hwloc_shmem_topology_write(hwloc_topology_t topology,
|
||||
hwloc_topology_t new;
|
||||
struct hwloc_tma tma;
|
||||
struct hwloc_shmem_header header;
|
||||
uint32_t header_length = (sizeof(header) + sizeof(void*) - 1) & ~(sizeof(void*) - 1); /* pad to a multiple of pointer size */
|
||||
void *mmap_res;
|
||||
int err;
|
||||
|
||||
@@ -102,7 +100,7 @@ hwloc_shmem_topology_write(hwloc_topology_t topology,
|
||||
hwloc_internal_memattrs_refresh(topology);
|
||||
|
||||
header.header_version = HWLOC_SHMEM_HEADER_VERSION;
|
||||
header.header_length = header_length;
|
||||
header.header_length = sizeof(header);
|
||||
header.mmap_address = (uintptr_t) mmap_address;
|
||||
header.mmap_length = length;
|
||||
|
||||
@@ -129,7 +127,7 @@ hwloc_shmem_topology_write(hwloc_topology_t topology,
|
||||
|
||||
tma.malloc = tma_shmem_malloc;
|
||||
tma.dontfree = 1;
|
||||
tma.data = (char *)mmap_res + header_length;
|
||||
tma.data = (char *)mmap_res + sizeof(header);
|
||||
err = hwloc__topology_dup(&new, topology, &tma);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@@ -156,7 +154,6 @@ hwloc_shmem_topology_adopt(hwloc_topology_t *topologyp,
|
||||
{
|
||||
hwloc_topology_t new, old;
|
||||
struct hwloc_shmem_header header;
|
||||
uint32_t header_length = (sizeof(header) + sizeof(void*) - 1) & ~(sizeof(void*) - 1); /* pad to a multiple of pointer size */
|
||||
void *mmap_res;
|
||||
int err;
|
||||
|
||||
@@ -174,7 +171,7 @@ hwloc_shmem_topology_adopt(hwloc_topology_t *topologyp,
|
||||
return -1;
|
||||
|
||||
if (header.header_version != HWLOC_SHMEM_HEADER_VERSION
|
||||
|| header.header_length != header_length
|
||||
|| header.header_length != sizeof(header)
|
||||
|| header.mmap_address != (uintptr_t) mmap_address
|
||||
|| header.mmap_length != length) {
|
||||
errno = EINVAL;
|
||||
@@ -189,7 +186,7 @@ hwloc_shmem_topology_adopt(hwloc_topology_t *topologyp,
|
||||
goto out_with_mmap;
|
||||
}
|
||||
|
||||
old = (hwloc_topology_t)((char*)mmap_address + header_length);
|
||||
old = (hwloc_topology_t)((char*)mmap_address + sizeof(header));
|
||||
if (hwloc_topology_abi_check(old) < 0) {
|
||||
errno = EINVAL;
|
||||
goto out_with_mmap;
|
||||
|
||||
154
src/3rdparty/hwloc/src/topology-synthetic.c
vendored
154
src/3rdparty/hwloc/src/topology-synthetic.c
vendored
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2023 Inria. All rights reserved.
|
||||
* Copyright © 2009-2022 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@@ -23,7 +23,6 @@ struct hwloc_synthetic_attr_s {
|
||||
unsigned depth; /* For caches/groups */
|
||||
hwloc_obj_cache_type_t cachetype; /* For caches */
|
||||
hwloc_uint64_t memorysize; /* For caches/memory */
|
||||
hwloc_uint64_t memorysidecachesize; /* Single level of memory-side-cache in-front of a NUMA node */
|
||||
};
|
||||
|
||||
struct hwloc_synthetic_indexes_s {
|
||||
@@ -381,9 +380,6 @@ hwloc_synthetic_parse_attrs(const char *attrs, const char **next_posp,
|
||||
} else if (!iscache && !strncmp("memory=", attrs, 7)) {
|
||||
memorysize = hwloc_synthetic_parse_memory_attr(attrs+7, &attrs);
|
||||
|
||||
} else if (!strncmp("memorysidecachesize=", attrs, 20)) {
|
||||
sattr->memorysidecachesize = hwloc_synthetic_parse_memory_attr(attrs+20, &attrs);
|
||||
|
||||
} else if (!strncmp("indexes=", attrs, 8)) {
|
||||
index_string = attrs+8;
|
||||
attrs += 8;
|
||||
@@ -391,9 +387,10 @@ hwloc_synthetic_parse_attrs(const char *attrs, const char **next_posp,
|
||||
attrs += index_string_length;
|
||||
|
||||
} else {
|
||||
size_t length = strcspn(attrs, " )");
|
||||
fprintf(stderr, "hwloc/synthetic: Ignoring unknown attribute at '%s'\n", attrs);
|
||||
attrs += length;
|
||||
if (verbose)
|
||||
fprintf(stderr, "Unknown attribute at '%s'\n", attrs);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (' ' == *attrs)
|
||||
@@ -419,32 +416,6 @@ hwloc_synthetic_parse_attrs(const char *attrs, const char **next_posp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_synthetic_set_default_attrs(struct hwloc_synthetic_attr_s *sattr,
|
||||
int *type_count)
|
||||
{
|
||||
hwloc_obj_type_t type = sattr->type;
|
||||
|
||||
if (type == HWLOC_OBJ_GROUP) {
|
||||
if (sattr->depth == (unsigned)-1)
|
||||
sattr->depth = type_count[HWLOC_OBJ_GROUP]--;
|
||||
|
||||
} else if (hwloc__obj_type_is_cache(type)) {
|
||||
if (!sattr->memorysize) {
|
||||
if (1 == sattr->depth)
|
||||
/* 32KiB in L1 */
|
||||
sattr->memorysize = 32*1024;
|
||||
else
|
||||
/* *4 at each level, starting from 1MiB for L2, unified */
|
||||
sattr->memorysize = 256ULL*1024 << (2*sattr->depth);
|
||||
}
|
||||
|
||||
} else if (type == HWLOC_OBJ_NUMANODE && !sattr->memorysize) {
|
||||
/* 1GiB in memory nodes. */
|
||||
sattr->memorysize = 1024*1024*1024;
|
||||
}
|
||||
}
|
||||
|
||||
/* frees level until arity = 0 */
|
||||
static void
|
||||
hwloc_synthetic_free_levels(struct hwloc_synthetic_backend_data_s *data)
|
||||
@@ -494,7 +465,6 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
data->level[0].indexes.string = NULL;
|
||||
data->level[0].indexes.array = NULL;
|
||||
data->level[0].attr.memorysize = 0;
|
||||
data->level[0].attr.memorysidecachesize = 0;
|
||||
data->level[0].attached = NULL;
|
||||
type_count[HWLOC_OBJ_MACHINE] = 1;
|
||||
if (*description == '(') {
|
||||
@@ -544,7 +514,6 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
if (attached) {
|
||||
attached->attr.type = type;
|
||||
attached->attr.memorysize = 0;
|
||||
attached->attr.memorysidecachesize = 0;
|
||||
/* attached->attr.depth and .cachetype unused */
|
||||
attached->next = NULL;
|
||||
pprev = &data->level[count-1].attached;
|
||||
@@ -632,7 +601,7 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
}
|
||||
if (!item) {
|
||||
if (verbose)
|
||||
fprintf(stderr,"Synthetic string with disallowed 0 number of objects at '%s'\n", pos);
|
||||
fprintf(stderr,"Synthetic string with disallow 0 number of objects at '%s'\n", pos);
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
@@ -642,7 +611,6 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
data->level[count].indexes.string = NULL;
|
||||
data->level[count].indexes.array = NULL;
|
||||
data->level[count].attr.memorysize = 0;
|
||||
data->level[count].attr.memorysidecachesize = 0;
|
||||
if (*next_pos == '(') {
|
||||
err = hwloc_synthetic_parse_attrs(next_pos+1, &next_pos, &data->level[count].attr, &data->level[count].indexes, verbose);
|
||||
if (err < 0)
|
||||
@@ -828,7 +796,6 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
data->level[1].indexes.string = NULL;
|
||||
data->level[1].indexes.array = NULL;
|
||||
data->level[1].attr.memorysize = 0;
|
||||
data->level[1].attr.memorysidecachesize = 0;
|
||||
data->level[1].totalwidth = data->level[0].totalwidth;
|
||||
/* update arity to insert a single NUMA node per parent */
|
||||
data->level[1].arity = data->level[0].arity;
|
||||
@@ -836,14 +803,30 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
count++;
|
||||
}
|
||||
|
||||
/* set default attributes that depend on the depth/hierarchy of levels */
|
||||
for (i=0; i<count; i++) {
|
||||
struct hwloc_synthetic_attached_s *attached;
|
||||
struct hwloc_synthetic_level_data_s *curlevel = &data->level[i];
|
||||
hwloc_synthetic_set_default_attrs(&curlevel->attr, type_count);
|
||||
for(attached = curlevel->attached; attached != NULL; attached = attached->next)
|
||||
hwloc_synthetic_set_default_attrs(&attached->attr, type_count);
|
||||
hwloc_synthetic_process_indexes(data, &curlevel->indexes, curlevel->totalwidth, verbose);
|
||||
hwloc_obj_type_t type = curlevel->attr.type;
|
||||
|
||||
if (type == HWLOC_OBJ_GROUP) {
|
||||
if (curlevel->attr.depth == (unsigned)-1)
|
||||
curlevel->attr.depth = type_count[HWLOC_OBJ_GROUP]--;
|
||||
|
||||
} else if (hwloc__obj_type_is_cache(type)) {
|
||||
if (!curlevel->attr.memorysize) {
|
||||
if (1 == curlevel->attr.depth)
|
||||
/* 32KiB in L1 */
|
||||
curlevel->attr.memorysize = 32*1024;
|
||||
else
|
||||
/* *4 at each level, starting from 1MiB for L2, unified */
|
||||
curlevel->attr.memorysize = 256ULL*1024 << (2*curlevel->attr.depth);
|
||||
}
|
||||
|
||||
} else if (type == HWLOC_OBJ_NUMANODE && !curlevel->attr.memorysize) {
|
||||
/* 1GiB in memory nodes. */
|
||||
curlevel->attr.memorysize = 1024*1024*1024;
|
||||
}
|
||||
|
||||
hwloc_synthetic_process_indexes(data, &data->level[i].indexes, data->level[i].totalwidth, verbose);
|
||||
}
|
||||
|
||||
hwloc_synthetic_process_indexes(data, &data->numa_attached_indexes, data->numa_attached_nr, verbose);
|
||||
@@ -876,12 +859,6 @@ hwloc_synthetic_set_attr(struct hwloc_synthetic_attr_s *sattr,
|
||||
obj->attr->numanode.page_types[0].size = 4096;
|
||||
obj->attr->numanode.page_types[0].count = sattr->memorysize / 4096;
|
||||
break;
|
||||
case HWLOC_OBJ_MEMCACHE:
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.linesize = 64;
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.size = sattr->memorysidecachesize;
|
||||
break;
|
||||
case HWLOC_OBJ_PACKAGE:
|
||||
case HWLOC_OBJ_DIE:
|
||||
break;
|
||||
@@ -949,14 +926,6 @@ hwloc_synthetic_insert_attached(struct hwloc_topology *topology,
|
||||
|
||||
hwloc__insert_object_by_cpuset(topology, NULL, child, "synthetic:attached");
|
||||
|
||||
if (attached->attr.memorysidecachesize) {
|
||||
hwloc_obj_t mscachechild = hwloc_alloc_setup_object(topology, HWLOC_OBJ_MEMCACHE, HWLOC_UNKNOWN_INDEX);
|
||||
mscachechild->cpuset = hwloc_bitmap_dup(set);
|
||||
mscachechild->nodeset = hwloc_bitmap_dup(child->nodeset);
|
||||
hwloc_synthetic_set_attr(&attached->attr, mscachechild);
|
||||
hwloc__insert_object_by_cpuset(topology, NULL, mscachechild, "synthetic:attached:mscache");
|
||||
}
|
||||
|
||||
hwloc_synthetic_insert_attached(topology, data, attached->next, set);
|
||||
}
|
||||
|
||||
@@ -1008,14 +977,6 @@ hwloc__look_synthetic(struct hwloc_topology *topology,
|
||||
hwloc_synthetic_set_attr(&curlevel->attr, obj);
|
||||
|
||||
hwloc__insert_object_by_cpuset(topology, NULL, obj, "synthetic");
|
||||
|
||||
if (type == HWLOC_OBJ_NUMANODE && curlevel->attr.memorysidecachesize) {
|
||||
hwloc_obj_t mscachechild = hwloc_alloc_setup_object(topology, HWLOC_OBJ_MEMCACHE, HWLOC_UNKNOWN_INDEX);
|
||||
mscachechild->cpuset = hwloc_bitmap_dup(set);
|
||||
mscachechild->nodeset = hwloc_bitmap_dup(obj->nodeset);
|
||||
hwloc_synthetic_set_attr(&curlevel->attr, mscachechild);
|
||||
hwloc__insert_object_by_cpuset(topology, NULL, mscachechild, "synthetic:mscache");
|
||||
}
|
||||
}
|
||||
|
||||
hwloc_synthetic_insert_attached(topology, data, curlevel->attached, set);
|
||||
@@ -1256,7 +1217,6 @@ hwloc__export_synthetic_indexes(hwloc_obj_t *level, unsigned total,
|
||||
|
||||
static int
|
||||
hwloc__export_synthetic_obj_attr(struct hwloc_topology * topology,
|
||||
unsigned long flags,
|
||||
hwloc_obj_t obj,
|
||||
char *buffer, size_t buflen)
|
||||
{
|
||||
@@ -1264,7 +1224,6 @@ hwloc__export_synthetic_obj_attr(struct hwloc_topology * topology,
|
||||
const char * prefix = "(";
|
||||
char cachesize[64] = "";
|
||||
char memsize[64] = "";
|
||||
char memorysidecachesize[64] = "";
|
||||
int needindexes = 0;
|
||||
|
||||
if (hwloc__obj_type_is_cache(obj->type) && obj->attr->cache.size) {
|
||||
@@ -1277,19 +1236,6 @@ hwloc__export_synthetic_obj_attr(struct hwloc_topology * topology,
|
||||
prefix, (unsigned long long) obj->attr->numanode.local_memory);
|
||||
prefix = separator;
|
||||
}
|
||||
if (obj->type == HWLOC_OBJ_NUMANODE && !(flags & HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_V1)) {
|
||||
hwloc_obj_t memorysidecache = obj->parent;
|
||||
hwloc_uint64_t size = 0;
|
||||
while (memorysidecache && memorysidecache->type == HWLOC_OBJ_MEMCACHE) {
|
||||
size += memorysidecache->attr->cache.size;
|
||||
memorysidecache = memorysidecache->parent;
|
||||
}
|
||||
if (size) {
|
||||
snprintf(memorysidecachesize, sizeof(memorysidecachesize), "%smemorysidecachesize=%llu",
|
||||
prefix, (unsigned long long) size);
|
||||
prefix = separator;
|
||||
}
|
||||
}
|
||||
if (!obj->logical_index /* only display indexes once per level (not for non-first NUMA children, etc.) */
|
||||
&& (obj->type == HWLOC_OBJ_PU || obj->type == HWLOC_OBJ_NUMANODE)) {
|
||||
hwloc_obj_t cur = obj;
|
||||
@@ -1301,12 +1247,12 @@ hwloc__export_synthetic_obj_attr(struct hwloc_topology * topology,
|
||||
cur = cur->next_cousin;
|
||||
}
|
||||
}
|
||||
if (*cachesize || *memsize || *memorysidecachesize || needindexes) {
|
||||
if (*cachesize || *memsize || needindexes) {
|
||||
ssize_t tmplen = buflen;
|
||||
char *tmp = buffer;
|
||||
int res, ret = 0;
|
||||
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%s%s%s", cachesize, memsize, memorysidecachesize, needindexes ? "" : ")");
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%s%s", cachesize, memsize, needindexes ? "" : ")");
|
||||
if (hwloc__export_synthetic_update_status(&ret, &tmp, &tmplen, res) < 0)
|
||||
return -1;
|
||||
|
||||
@@ -1380,7 +1326,7 @@ hwloc__export_synthetic_obj(struct hwloc_topology * topology, unsigned long flag
|
||||
|
||||
if (!(flags & HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS)) {
|
||||
/* obj attributes */
|
||||
res = hwloc__export_synthetic_obj_attr(topology, flags, obj, tmp, tmplen);
|
||||
res = hwloc__export_synthetic_obj_attr(topology, obj, tmp, tmplen);
|
||||
if (hwloc__export_synthetic_update_status(&ret, &tmp, &tmplen, res) < 0)
|
||||
return -1;
|
||||
}
|
||||
@@ -1405,7 +1351,7 @@ hwloc__export_synthetic_memory_children(struct hwloc_topology * topology, unsign
|
||||
|
||||
if (flags & HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_V1) {
|
||||
/* v1: export a single NUMA child */
|
||||
if (parent->memory_arity > 1) {
|
||||
if (parent->memory_arity > 1 || mchild->type != HWLOC_OBJ_NUMANODE) {
|
||||
/* not supported */
|
||||
if (verbose)
|
||||
fprintf(stderr, "Cannot export to synthetic v1 if multiple memory children are attached to the same location.\n");
|
||||
@@ -1416,9 +1362,6 @@ hwloc__export_synthetic_memory_children(struct hwloc_topology * topology, unsign
|
||||
if (needprefix)
|
||||
hwloc__export_synthetic_add_char(&ret, &tmp, &tmplen, ' ');
|
||||
|
||||
/* ignore memcaches and export the NUMA node */
|
||||
while (mchild->type != HWLOC_OBJ_NUMANODE)
|
||||
mchild = mchild->memory_first_child;
|
||||
res = hwloc__export_synthetic_obj(topology, flags, mchild, 1, tmp, tmplen);
|
||||
if (hwloc__export_synthetic_update_status(&ret, &tmp, &tmplen, res) < 0)
|
||||
return -1;
|
||||
@@ -1426,25 +1369,16 @@ hwloc__export_synthetic_memory_children(struct hwloc_topology * topology, unsign
|
||||
}
|
||||
|
||||
while (mchild) {
|
||||
/* The core doesn't support shared memcache for now (because ACPI and Linux don't).
|
||||
* So, for each mchild here, recurse only in the first children at each level.
|
||||
*
|
||||
* FIXME: whenever supported by the core, really recurse to export memcaches and numanode,
|
||||
/* FIXME: really recurse to export memcaches and numanode,
|
||||
* but it requires clever parsing of [ memcache [numa] [numa] ] during import,
|
||||
* better attaching of things to describe the hierarchy.
|
||||
*/
|
||||
hwloc_obj_t numanode = mchild;
|
||||
/* Only export the first NUMA node leaf of each memory child.
|
||||
* Memcaches are ignored here, they will be summed and exported as a single attribute
|
||||
* of the NUMA node in hwloc__export_synthetic_obj().
|
||||
/* only export the first NUMA node leaf of each memory child
|
||||
* FIXME: This assumes mscache aren't shared between nodes, that's true in current platforms
|
||||
*/
|
||||
while (numanode && numanode->type != HWLOC_OBJ_NUMANODE) {
|
||||
if (verbose && numanode->memory_arity > 1) {
|
||||
static int warned = 0;
|
||||
if (!warned)
|
||||
fprintf(stderr, "Ignoring non-first memory children at non-first level of memory hierarchy.\n");
|
||||
warned = 1;
|
||||
}
|
||||
assert(numanode->arity == 1);
|
||||
numanode = numanode->memory_first_child;
|
||||
}
|
||||
assert(numanode); /* there's always a numanode at the bottom of the memory tree */
|
||||
@@ -1577,21 +1511,17 @@ hwloc_topology_export_synthetic(struct hwloc_topology * topology,
|
||||
|
||||
if (flags & HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_V1) {
|
||||
/* v1 requires all NUMA at the same level */
|
||||
hwloc_obj_t node, parent;
|
||||
hwloc_obj_t node;
|
||||
signed pdepth;
|
||||
|
||||
node = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0);
|
||||
assert(node);
|
||||
parent = node->parent;
|
||||
while (!hwloc__obj_type_is_normal(parent->type))
|
||||
parent = parent->parent;
|
||||
pdepth = parent->depth;
|
||||
assert(hwloc__obj_type_is_normal(node->parent->type)); /* only depth-1 memory children for now */
|
||||
pdepth = node->parent->depth;
|
||||
|
||||
while ((node = node->next_cousin) != NULL) {
|
||||
parent = node->parent;
|
||||
while (!hwloc__obj_type_is_normal(parent->type))
|
||||
parent = parent->parent;
|
||||
if (parent->depth != pdepth) {
|
||||
assert(hwloc__obj_type_is_normal(node->parent->type)); /* only depth-1 memory children for now */
|
||||
if (node->parent->depth != pdepth) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Cannot export to synthetic v1 if memory is attached to parents at different depths.\n");
|
||||
errno = EINVAL;
|
||||
@@ -1604,7 +1534,7 @@ hwloc_topology_export_synthetic(struct hwloc_topology * topology,
|
||||
|
||||
if (!(flags & HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS)) {
|
||||
/* obj attributes */
|
||||
res = hwloc__export_synthetic_obj_attr(topology, flags, obj, tmp, tmplen);
|
||||
res = hwloc__export_synthetic_obj_attr(topology, obj, tmp, tmplen);
|
||||
if (res > 0)
|
||||
needprefix = 1;
|
||||
if (hwloc__export_synthetic_update_status(&ret, &tmp, &tmplen, res) < 0)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user