Skip to content
Closed
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
104 changes: 104 additions & 0 deletions docs/plans/2026-07-29-hardware-platform-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Hardware Platform Integration Implementation Plan

> **For Claude:** REQUIRED SUB-SKILL: Use executing-plans to implement this plan task-by-task.

**Goal:** Merge `hardware_adapt` and `cambricon_test` into `master` while preserving existing CUDA adapter behavior and adding testable support for MetaX, Iluvatar, Hygon, Moore Threads, Cambricon, and Ascend.

**Architecture:** Keep `HardwareTestAdapter` as the public entry point and preserve its existing constructor, methods, CUDA command shape, output parsing, and metric names. Add a small platform registry behind the adapter for platform-specific detection, build commands, binary paths, capabilities, and output parsers. CUDA-compatible platforms reuse the CUDA benchmark source; Cambricon and Ascend retain native benchmark directories.

**Tech Stack:** Python 3.10, pytest, C++17, CUDA/CMake, MetaX cu-bridge, CoreX, DTK/HIP, MUSA, CNToolkit/CNRT/BANG C, CANN/AscendCL.

---

### Task 1: Capture Existing CUDA Behavior

**Files:**
- Create: `tests/test_hardware_adapter.py`
- Modify: `infinimetrics/hardware/hardware_adapter.py`

**Steps:**
1. Add tests for the existing constructor argument `cuda_perf_path`, default binary path, `_build_command`, memory parsing, STREAM parsing, cache parsing, and metric names.
2. Run `pytest tests/test_hardware_adapter.py -v` against the unmerged baseline and record passing behavior.
3. Do not change implementation until the compatibility tests pass.

### Task 2: Merge Source Histories

**Files:**
- Merge: `origin/hardware_adapt`
- Merge: `origin/cambricon_test`
- Resolve: `infinimetrics/hardware/hardware_adapter.py`
- Modify: `infinimetrics/dispatcher.py`

**Steps:**
1. Merge `origin/hardware_adapt` with a merge commit.
2. Merge `origin/cambricon_test` without committing.
3. Preserve all non-conflicting native benchmark source directories.
4. Resolve `hardware_adapter.py` using the baseline compatibility tests.
5. Register `cudaunified`, `cuda`, `metax`, `corex`, `iluvatar`, `hygon`, `moore`, `cambricon`, and `ascend` hardware frameworks.

### Task 3: Add the Platform Registry

**Files:**
- Modify: `infinimetrics/hardware/hardware_adapter.py`
- Modify: `infinimetrics/common/constants.py`
- Test: `tests/test_hardware_adapter.py`

**Steps:**
1. Define immutable platform specifications for binary path, build platform, native benchmark directory, supported tests, aliases, and detection probes.
2. Resolve platform in this order: explicit `config.device`, testcase framework, runtime detection, CUDA fallback.
3. Preserve `_build_cuda_project`, `_build_command`, `_execute_test`, and `_parse_output` compatibility wrappers.
4. Preserve existing CUDA metric names: `hardware.mem_sweep_*`, `hardware.stream_*`, and `hardware.gpu_cache_*`.
5. Put platform identity in result configuration instead of metric names.
6. Add tests for every alias, resolution priority, build command, and unsupported capability.

### Task 4: Repair Native Platform Benchmarks

**Files:**
- Modify: `infinimetrics/hardware/cambricon-memory-benchmark/CMakeLists.txt`
- Modify: `infinimetrics/hardware/cambricon-memory-benchmark/src/main.mlu`
- Modify: `infinimetrics/hardware/cambricon-memory-benchmark/include/*.h`
- Modify: `infinimetrics/hardware/ascend-memory-benchmark/src/main.cc`
- Modify: `infinimetrics/hardware/ascend-memory-benchmark/include/*.h`
- Test: `tests/test_hardware_adapter.py`

**Steps:**
1. Pass the selected device ID into every native test instead of resetting to device 0.
2. Wire Cambricon cache flags to the existing NRAM and L2 implementations.
3. Fix the Cambricon CMake source filename.
4. Parse Cambricon cache into the existing cache metric schema.
5. Report Ascend D2D hierarchy sweep separately from CUDA L1/L2 cache metrics.
6. Mark estimated Ascend STREAM operations in result metadata and preserve their existing numeric output.
7. Keep default allocation sizes and CLI defaults unchanged.

### Task 5: Automated Verification

**Files:**
- Modify: `tests/test_hardware_adapter.py`
- Create: `test_inputs/configs/hardware.cambricon.Comprehensive.json`
- Create: `test_inputs/configs/hardware.ascend.Comprehensive.json`
- Modify: platform benchmark documentation

**Steps:**
1. Run `pytest tests/test_hardware_adapter.py -v`.
2. Run the complete repository test suite.
3. Run `git diff --check`.
4. Parse every modified Python file with `compileall`.
5. Validate build scripts with `bash -n`.

### Task 6: Hardware Verification

**Steps:**
1. On A100, select one verified idle GPU and build/run CUDA memory, STREAM, cache, and comprehensive modes.
2. On MetaX, Iluvatar, Moore Threads, Cambricon, and Ascend hosts, build in the prepared platform container and run `--help` plus a short STREAM smoke test.
3. Test Hygon when an SSH host or DTK environment is available; otherwise report it explicitly as unverified.
4. Save commit, command, device selection, stdout, stderr, and exit code for every platform.
5. Re-run automated tests after any platform-specific fix.

### Task 7: Integrate Master

**Steps:**
1. Review the final diff against `origin/master`.
2. Confirm the original local dirty worktree is untouched.
3. Fetch the latest `origin/master` and merge it if necessary.
4. Push the verified integration commit to `origin/master` with a normal fast-forward push.
5. Report the final commit and per-platform verification matrix.
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
8 changes: 8 additions & 0 deletions infinimetrics/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
_ADAPTER_REGISTRY = {
(TestCategory.OPERATOR, "infinicore"): lambda: _create_infinicore_adapter(),
(TestCategory.HARDWARE, "cudaunified"): lambda: _create_hardware_adapter(),
(TestCategory.HARDWARE, "cuda"): lambda: _create_hardware_adapter(),
(TestCategory.HARDWARE, "metax"): lambda: _create_hardware_adapter(),
(TestCategory.HARDWARE, "corex"): lambda: _create_hardware_adapter(),
(TestCategory.HARDWARE, "iluvatar"): lambda: _create_hardware_adapter(),
(TestCategory.HARDWARE, "hygon"): lambda: _create_hardware_adapter(),
(TestCategory.HARDWARE, "moore"): lambda: _create_hardware_adapter(),
(TestCategory.HARDWARE, "cambricon"): lambda: _create_hardware_adapter(),
(TestCategory.HARDWARE, "ascend"): lambda: _create_hardware_adapter(),
(TestCategory.COMM, "nccltest"): lambda: _create_nccltests_adapter(),
(TestCategory.INFER, "infinilm"): lambda: _create_inference_adapter(),
(TestCategory.INFER, "vllm"): lambda: _create_inference_adapter(),
Expand Down
80 changes: 80 additions & 0 deletions infinimetrics/hardware/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# 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 | Testcase framework | Build command | Binary |
| --- | --- | --- | --- |
| NVIDIA CUDA | `cuda`, `cudaUnified` | `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 framework in a testcase such as `hardware.cambricon.Stream`.
3. The locally installed accelerator toolchain.
4. CUDA as the compatibility fallback.

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 "")
Loading
Loading