Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ If you plan to use the hardware testing modules, you need to build the CUDA memo

```bash
cd infinimetrics/hardware/cuda-memory-benchmark
bash build.sh
bash build.sh --platform cuda
```

For MetaX, Iluvatar, Hygon, Moore Threads, Cambricon, and Ascend build and
runtime instructions, see [Hardware Benchmarks](../infinimetrics/hardware/README.md).

**Note**: This requires:
- CUDA toolkit (compatible with your GPU driver)
- C++ compiler with CUDA support
Expand Down
1 change: 1 addition & 0 deletions infinimetrics/common/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class AcceleratorType(str, Enum):
AMD = "amd" # ROCm
ASCEND = "ascend" # Huawei NPU
CAMBRICON = "cambricon" # Cambricon MLU
MTHREADS = "moore" # Moore Threads MUSA
GENERIC = "generic"


Expand Down
63 changes: 62 additions & 1 deletion infinimetrics/common/hardware_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
"default_name": "NVIDIA GPU",
"parse_output": True,
},
"moore": {
"command": ["mthreads-gmi", "-q"],
"pattern": r"\bGPU\b|\bProduct\b",
"default_name": "Moore Threads GPU",
},
"amd": {
"candidates": ["amd-smi", "rocm-smi"],
"pattern": r"\bGPU\b",
Expand Down Expand Up @@ -99,13 +104,17 @@ def collect(self, accel_type: str = "", device_ids: Any = None) -> Dict[str, Any
hw["cuda_version"] = (
self._collect_cuda_version() or hw["cuda_version"]
)
elif probe_type == "moore":
musa_ver = self._collect_musa_version()
if musa_ver:
hw["cuda_version"] = f"MUSA {musa_ver}"
return hw

return hw

def _get_probe_order(self, hint: str) -> List[str]:
"""Get probe order based on accelerator type hint."""
order = ["nvidia", "amd", "ascend", "cambricon"]
order = ["nvidia", "moore", "amd", "ascend", "cambricon"]
if hint in order:
return [hint] + [p for p in order if p != hint]
return order
Expand Down Expand Up @@ -137,6 +146,7 @@ def _probe(self, probe_type: str, hw: Dict[str, Any]) -> ProbeResult:
"""Generic probe dispatcher."""
probe_methods = {
"nvidia": self._probe_nvidia,
"moore": self._probe_mthreads,
"amd": self._probe_amd,
"ascend": self._probe_generic_command,
"cambricon": self._probe_generic_command,
Expand Down Expand Up @@ -182,6 +192,42 @@ def _probe_amd(self, probe_type: str, hw: Dict[str, Any]) -> ProbeResult:
cmd, config["pattern"], config["default_name"], hw
)

def _probe_mthreads(self, probe_type: str, hw: Dict[str, Any]) -> ProbeResult:
"""Probe Moore Threads GPU using mthreads-gmi."""
config = PROBE_CONFIGS["moore"]
if not _which(config["command"][0]):
return ProbeResult(success=False)

try:
r = subprocess.run(
config["command"], capture_output=True, text=True, timeout=5
)
if r.returncode != 0 or not r.stdout.strip():
return ProbeResult(success=False)

gpu_count = 0
gpu_name = None
for line in r.stdout.splitlines():
stripped = line.strip()
if re.match(r"^GPU\d+\s", stripped):
gpu_count += 1
if stripped.startswith("Product Name") and ":" in stripped:
gpu_name = stripped.split(":", 1)[1].strip()

if gpu_count > 0:
hw["gpu_count"] = max(hw["gpu_count"], gpu_count)
if hw["gpu_model"] == "Unknown":
hw["gpu_model"] = gpu_name or config["default_name"]

# Try to get MUSA version
musa_ver = self._collect_musa_version()
if musa_ver:
hw["cuda_version"] = f"MUSA {musa_ver}"

return ProbeResult(success=True, count=hw["gpu_count"])
except Exception:
return ProbeResult(success=False)

def _probe_generic_command(
self, probe_type: str, hw: Dict[str, Any]
) -> ProbeResult:
Expand Down Expand Up @@ -228,6 +274,21 @@ def _collect_cuda_version(self) -> Optional[str]:
logger.debug(f"Failed to collect CUDA version: {e}")
return None

def _collect_musa_version(self) -> Optional[str]:
"""Collect MUSA version using mcc."""
try:
r = subprocess.run(
["mcc", "--version"], capture_output=True, text=True, timeout=2
)
if r.returncode == 0:
for line in r.stdout.splitlines():
match = re.search(r"(\d+\.\d+\.\d+)", line)
if match:
return match.group(1)
except Exception:
pass
return None


# Singleton instance for convenience
_collector = HardwareCollector()
Expand Down
91 changes: 91 additions & 0 deletions infinimetrics/hardware/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Hardware Benchmarks

InfiniBench provides one hardware adapter for NVIDIA CUDA and six additional
accelerator platforms. Existing CUDA command shapes and metric names are kept
unchanged.

## Platforms

| Platform | `config.device` values | Build command | Binary |
| --- | --- | --- | --- |
| NVIDIA CUDA | `cuda`, `cudaUnified`, `nvidia` | `bash build.sh --platform cuda` | `cuda-memory-benchmark/build/cuda_perf_suite` |
| MetaX | `metax` | `bash build.sh --platform metax` | `cuda-memory-benchmark/build/cuda_perf_suite` |
| Iluvatar CoreX | `corex`, `iluvatar` | `bash build.sh --platform corex` | `cuda-memory-benchmark/build/cuda_perf_suite` |
| Hygon DCU | `hygon` | `bash build.sh --platform hygon` | `cuda-memory-benchmark/build/cuda_perf_suite` |
| Moore Threads | `moore` | `bash build.sh --platform moore` | `cuda-memory-benchmark/build/cuda_perf_suite` |
| Cambricon | `cambricon` | `bash build.sh` | `cambricon-memory-benchmark/build/mlu_perf_suite` |
| Ascend | `ascend` | `bash build.sh` | `ascend-memory-benchmark/build/npu_perf_suite` |

Run each build command from its benchmark directory. All binaries use the same
test selectors and common arguments:

```bash
./build/<binary> --all
./build/<binary> --memory
./build/<binary> --stream --iterations 3 --array-size 1048576
./build/<binary> --cache --device 0
```

## Platform Selection

`HardwareTestAdapter` resolves a platform in this order:

1. `config.device`, when supplied.
2. The locally installed accelerator toolchain.
3. CUDA as the compatibility fallback.

The testcase framework remains `cudaUnified` for every hardware platform. For
example, Cambricon STREAM uses:

```json
{
"testcase": "hardware.cudaUnified.Stream",
"config": {
"device": "cambricon"
}
}
```

The aliases `nvidia`, `musa`, `mthreads`, `mlu`, and `npu` are also accepted as
explicit device values. A selected non-CUDA platform is recorded in the result
configuration as `platform`; metric names remain compatible with CUDA results.

## Device Visibility

Restrict the process to an idle physical device before starting a benchmark.
The selected physical device is renumbered to device 0 inside the process.

| Platform | Visibility variable |
| --- | --- |
| NVIDIA, MetaX, Iluvatar | `CUDA_VISIBLE_DEVICES` |
| Hygon | `HIP_VISIBLE_DEVICES` and `ROCR_VISIBLE_DEVICES` |
| Moore Threads | `MUSA_VISIBLE_DEVICES` |
| Cambricon | `MLU_VISIBLE_DEVICES` |
| Ascend | `ASCEND_RT_VISIBLE_DEVICES` |

For example:

```bash
CUDA_VISIBLE_DEVICES=2 ./build/cuda_perf_suite --stream --device 0
MLU_VISIBLE_DEVICES=3 ./build/mlu_perf_suite --stream --device 0
ASCEND_RT_VISIBLE_DEVICES=4 ./build/npu_perf_suite --stream --device 0
```

## Container Notes

Hygon DTK containers may require the host driver libraries to be mounted at
the path expected by DTK:

```bash
docker run --rm --privileged \
--mount type=bind,source=/opt/hyhal,target=/opt/hyhal,readonly \
<dtk-image> bash
```

Without this mount, management tools can list DCUs while HIP applications fail
to load `libhsa-runtime64.so` or `libhydmi.so`.

Some Ascend development images can return exit code 137 after the benchmark has
printed its completion message. The adapter intentionally treats every nonzero
exit code as a failure; fix the container lifecycle rather than suppressing that
error in application code.
66 changes: 66 additions & 0 deletions infinimetrics/hardware/ascend-memory-benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
cmake_minimum_required(VERSION 3.18)
project(NpuPerfSuite VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

# Find Ascend CANN Toolkit
if(DEFINED ENV{ASCEND_HOME_PATH})
set(ASCEND_HOME $ENV{ASCEND_HOME_PATH})
elseif(DEFINED ENV{ASCEND_TOOLKIT_HOME})
set(ASCEND_HOME $ENV{ASCEND_TOOLKIT_HOME})
else()
set(ASCEND_HOME "/usr/local/Ascend/ascend-toolkit/latest")
endif()
message(STATUS "ASCEND_HOME: ${ASCEND_HOME}")

# Detect architecture for library path
execute_process(
COMMAND uname -m
OUTPUT_VARIABLE ARCH_TYPE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(ARCH_TYPE STREQUAL "aarch64")
set(ARCH_DIR "aarch64-linux")
else()
set(ARCH_DIR "x86_64-linux")
endif()

set(ASCEND_INCLUDE_DIR "${ASCEND_HOME}/${ARCH_DIR}/include")
set(ASCEND_LIB_DIR "${ASCEND_HOME}/${ARCH_DIR}/lib64")

# Verify headers exist
find_path(ACL_INCLUDE_DIR NAMES acl/acl.h HINTS ${ASCEND_INCLUDE_DIR})
if(NOT ACL_INCLUDE_DIR)
message(FATAL_ERROR "acl/acl.h not found in ${ASCEND_INCLUDE_DIR}. "
"Set ASCEND_HOME_PATH or ASCEND_TOOLKIT_HOME.")
endif()

# Find ascendcl library
find_library(ASCENDCL_LIB ascendcl HINTS ${ASCEND_LIB_DIR})
if(NOT ASCENDCL_LIB)
message(FATAL_ERROR "libascendcl.so not found in ${ASCEND_LIB_DIR}")
endif()

add_executable(npu_perf_suite src/main.cc)
target_include_directories(npu_perf_suite PRIVATE
${ACL_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(npu_perf_suite ${ASCENDCL_LIB} pthread)
target_compile_options(npu_perf_suite PRIVATE -Wall -O3)

install(TARGETS npu_perf_suite RUNTIME DESTINATION bin)

message(STATUS "")
message(STATUS "Configuration Summary:")
message(STATUS " Project: ${PROJECT_NAME} v${PROJECT_VERSION}")
message(STATUS " Build: ${CMAKE_BUILD_TYPE}")
message(STATUS " Arch: ${ARCH_DIR}")
message(STATUS " Include: ${ACL_INCLUDE_DIR}")
message(STATUS " ascendcl: ${ASCENDCL_LIB}")
message(STATUS "")
68 changes: 68 additions & 0 deletions infinimetrics/hardware/ascend-memory-benchmark/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/bash
set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

echo "=========================================="
echo " NPU Performance Suite - Build Script"
echo "=========================================="
echo ""

# Detect CANN installation
if [ -z "${ASCEND_HOME_PATH}" ] && [ -z "${ASCEND_TOOLKIT_HOME}" ]; then
# Try common locations
for dir in /usr/local/Ascend/ascend-toolkit/latest \
/usr/local/Ascend/ascend-toolkit/latest/*/ascend-toolkit/latest; do
if [ -d "$dir" ]; then
export ASCEND_HOME_PATH="$dir"
break
fi
done
if [ -z "${ASCEND_HOME_PATH}" ]; then
echo -e "${RED}ERROR: CANN toolkit not found.${NC}"
echo "Set ASCEND_HOME_PATH or ASCEND_TOOLKIT_HOME environment variable."
echo "Example: export ASCEND_TOOLKIT_HOME=/usr/local/Ascend/ascend-toolkit/latest"
exit 1
fi
fi

# Check for g++
if ! command -v g++ &> /dev/null; then
echo -e "${RED}ERROR: g++ not found.${NC}"
exit 1
fi

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_DIR="${SCRIPT_DIR}/build"

echo -e "${YELLOW}Creating build directory...${NC}"
mkdir -p "${BUILD_DIR}"
cd "${BUILD_DIR}"

echo -e "${YELLOW}Configuring with CMake...${NC}"
cmake .. -DCMAKE_BUILD_TYPE=Release

echo -e "${YELLOW}Building...${NC}"
make -j$(nproc)

if [ $? -eq 0 ]; then
echo ""
echo -e "${GREEN}Build succeeded!${NC}"
echo ""
echo "Executable: ${BUILD_DIR}/npu_perf_suite"
echo ""
echo "Usage:"
echo " ${BUILD_DIR}/npu_perf_suite --all"
echo " ${BUILD_DIR}/npu_perf_suite --memory"
echo " ${BUILD_DIR}/npu_perf_suite --stream"
echo " ${BUILD_DIR}/npu_perf_suite --cache"
echo ""
else
echo ""
echo -e "${RED}Build failed!${NC}"
echo "Please check the error messages above."
exit 1
fi
Loading
Loading