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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/CI_DOCKER.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Start ci container
```
docker container create --name ci-mtml-py --env MTHREADS_VISIBLE_DEVICES=all --env MTHREADS_DRIVER_CAPABILITIES=all -v $PWD:/app/test -it registry.cn-hangzhou.aliyuncs.com/fishingfly/mthreads-ml-py-ci:latest bash
```
```
2 changes: 1 addition & 1 deletion .github/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ RUN chown -R mccxadmin:mccxadmin /app

USER mccxadmin

CMD ["/bin/bash"]
CMD ["/bin/bash"]
48 changes: 48 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Hooks every change to this repository has to pass.
#
# pre-commit install # run them on every commit
# pre-commit run --all-files # check the whole tree (formatting hooks fix)
#
# The checks mirror what the Makefile used to call directly (flake8 with the
# same limits, isort, black); pre-commit provisions each tool in its own
# environment, so no global install of them is needed.
default_stages: [pre-commit, manual]

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-ast
- id: check-yaml
- id: end-of-file-fixer
exclude: ^mtml_2\.2\.0\.h$
- id: trailing-whitespace
exclude: ^mtml_2\.2\.0\.h$
- id: check-merge-conflict
- id: detect-private-key
- id: debug-statements
- repo: https://github.com/PyCQA/isort
rev: 7.0.0
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 26.1.0
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 7.1.1
hooks:
- id: flake8
# The Makefile's limits, extended rather than replaced so flake8's own
# defaults keep working. E203 is what black produces; E266 allows the
# `##` banner comments this file has always used; F403/F405 cover the
# `from pymtml import *` that the examples and tests are meant to use.
args: ["--max-line-length=120", "--extend-ignore=E203,E501,W503,E266,F403,F405"]
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
- id: codespell
# musa/mtml/pymtml and renderD (from the /dev/dri/renderD128 path) are
# names, not misspellings. The vendored C header keeps its own text.
exclude: ^mtml_2\.2\.0\.h$
args: ['-L', 'musa,musas,mtml,musa_,pymtml,renderD']
1 change: 0 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,3 @@ mtmlDeviceFreeMemory(memory)
- `nvmlDeviceGetCudaComputeCapability()` returns `(0, 0)` unless torch_musa is available
- Use `patch_torch_c_for_musa()` to patch torch._C with functions from torch_musa._MUSAC
- PCI busId field may be empty from driver; library auto-fills from sbdf if needed

20 changes: 12 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,32 @@
# Default Python interpreter
PYTHON ?= python3

# The lint and format tools are pinned in .pre-commit-config.yaml; pre-commit
# provisions each one in its own environment, so no global install is needed.
PRECOMMIT ?= pre-commit

# Package name
PACKAGE = pymtml

help:
@echo "Available targets:"
@echo " format - Format code with isort + black"
@echo " lint - Run linter (flake8)"
@echo " format - Format the tree with the pinned pre-commit hooks"
@echo " lint - Run the read-only checks (flake8, codespell, ast)"
@echo " test - Run tests"
@echo " build - Build wheel package"
@echo " clean - Clean build artifacts"
@echo " publish - Upload wheel to PyPI"
@echo " all - Format, lint, test, build"

# Format code using isort + black
# Format the tree (isort, black, whitespace and end-of-file hooks)
format:
$(PYTHON) -m isort $(PACKAGE).py example.py test_*.py
$(PYTHON) -m black $(PACKAGE).py example.py test_*.py
$(PRECOMMIT) run --all-files

# Lint code using flake8
# Read-only checks: lint, spelling and syntax, the same hooks the gate runs
lint:
$(PYTHON) -m flake8 $(PACKAGE).py example.py --max-line-length=120 --ignore=E501,W503
$(PRECOMMIT) run flake8 --all-files
$(PRECOMMIT) run codespell --all-files
$(PRECOMMIT) run check-ast --all-files

# Run tests
test:
Expand All @@ -45,4 +50,3 @@ publish: build

# Run all checks and build
all: format lint test build

2 changes: 1 addition & 1 deletion PUBLISH.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
python setup.py bdist_wheel
# Upload the packages to PyPI
python -m twine upload --repository pypi dist/*
```
```
20 changes: 15 additions & 5 deletions examples/02_device_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
print(f" 名称: {mtmlDeviceGetName(device)}")
print(f" 索引: {mtmlDeviceGetIndex(device)}")
print(f" UUID: {mtmlDeviceGetUUID(device)}")
print(f" 品牌: {'MTT' if mtmlDeviceGetBrand(device) == MTML_BRAND_MTT else 'Unknown'}")
print(
f" 品牌: {'MTT' if mtmlDeviceGetBrand(device) == MTML_BRAND_MTT else 'Unknown'}"
)

try:
print(f" 序列号: {mtmlDeviceGetSerialNumber(device)}")
Expand All @@ -33,8 +35,10 @@
print(f" MtBIOS 版本: [不可用: {e}]")

print(f" GPU 核心数: {mtmlDeviceCountGpuCores(device)}")
print(f" 功耗: {mtmlDeviceGetPowerUsage(device)} mW "
f"({mtmlDeviceGetPowerUsage(device) / 1000:.1f} W)")
print(
f" 功耗: {mtmlDeviceGetPowerUsage(device)} mW "
f"({mtmlDeviceGetPowerUsage(device) / 1000:.1f} W)"
)

# PCI 信息
pci = mtmlDeviceGetPciInfo(device)
Expand All @@ -43,7 +47,9 @@
print(f" PCI 设备ID: {pci.pciDeviceId:#010x}")
print(f" PCIe 代数: 当前 Gen{pci.pciCurGen} / 最大 Gen{pci.pciMaxGen}")
print(f" PCIe 宽度: 当前 x{pci.pciCurWidth} / 最大 x{pci.pciMaxWidth}")
print(f" PCIe 速率: 当前 {pci.pciCurSpeed:.1f} GT/s / 最大 {pci.pciMaxSpeed:.1f} GT/s")
print(
f" PCIe 速率: 当前 {pci.pciCurSpeed:.1f} GT/s / 最大 {pci.pciMaxSpeed:.1f} GT/s"
)

# PCIe 插槽信息
try:
Expand All @@ -54,7 +60,11 @@

# 设备属性
prop = mtmlDeviceGetProperty(device)
virt_cap = "支持" if prop.virtCapability == MTML_DEVICE_SUPPORT_VIRTUALIZATION else "不支持"
virt_cap = (
"支持"
if prop.virtCapability == MTML_DEVICE_SUPPORT_VIRTUALIZATION
else "不支持"
)
mpc_cap = "支持" if prop.mpcCapability == MTML_DEVICE_SUPPORT_MPC else "不支持"
print(f" 虚拟化: {virt_cap}")
print(f" MPC: {mpc_cap}")
Expand Down
2 changes: 1 addition & 1 deletion examples/03_gpu_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
print(f" GPU 时钟: {clock} / {max_clock} MHz")

# 各引擎利用率
print(f" 引擎利用率:")
print(" 引擎利用率:")
for engine_id, engine_name in engine_names.items():
try:
engine_util = mtmlGpuGetEngineUtilization(gpu, engine_id)
Expand Down
24 changes: 16 additions & 8 deletions examples/05_vpu_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,38 @@
# 编码器会话状态
try:
enc_states = mtmlVpuGetEncoderSessionStates(vpu, 8)
active_enc = sum(1 for s in enc_states if s.state == MTML_CODEC_SESSION_STATE_ACTIVE)
active_enc = sum(
1 for s in enc_states if s.state == MTML_CODEC_SESSION_STATE_ACTIVE
)
print(f" 活跃编码会话: {active_enc}")
for s in enc_states:
if s.state == MTML_CODEC_SESSION_STATE_ACTIVE:
metrics = mtmlVpuGetEncoderSessionMetrics(vpu, s.sessionId)
print(f" 编码会话 {s.sessionId}: {metrics.width}x{metrics.height}, "
f"codec={metrics.codecType}, fps={metrics.fps}")
print(
f" 编码会话 {s.sessionId}: {metrics.width}x{metrics.height}, "
f"codec={metrics.codecType}, fps={metrics.fps}"
)
break
except MTMLError:
print(f" 活跃编码会话: [不可用]")
print(" 活跃编码会话: [不可用]")

# 解码器会话状态
try:
dec_states = mtmlVpuGetDecoderSessionStates(vpu, 8)
active_dec = sum(1 for s in dec_states if s.state == MTML_CODEC_SESSION_STATE_ACTIVE)
active_dec = sum(
1 for s in dec_states if s.state == MTML_CODEC_SESSION_STATE_ACTIVE
)
print(f" 活跃解码会话: {active_dec}")
for s in dec_states:
if s.state == MTML_CODEC_SESSION_STATE_ACTIVE:
metrics = mtmlVpuGetDecoderSessionMetrics(vpu, s.sessionId)
print(f" 解码会话 {s.sessionId}: {metrics.width}x{metrics.height}, "
f"codec={metrics.codecType}, fps={metrics.fps}")
print(
f" 解码会话 {s.sessionId}: {metrics.width}x{metrics.height}, "
f"codec={metrics.codecType}, fps={metrics.fps}"
)
break
except MTMLError:
print(f" 活跃解码会话: [不可用]")
print(" 活跃解码会话: [不可用]")

except MTMLError as e:
print(f" VPU 不可用: {e}")
Expand Down
28 changes: 20 additions & 8 deletions examples/07_ecc_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,35 +28,47 @@
# 已纠正错误 (Volatile)
try:
corrected_vol = mtmlMemoryGetEccErrorCounter(
memory, MTML_MEMORY_ERROR_TYPE_CORRECTED,
MTML_VOLATILE_ECC, MTML_MEMORY_LOCATION_DRAM)
memory,
MTML_MEMORY_ERROR_TYPE_CORRECTED,
MTML_VOLATILE_ECC,
MTML_MEMORY_LOCATION_DRAM,
)
print(f" 已纠正错误 (当前会话): {corrected_vol}")
except MTMLError as e:
print(f" 已纠正错误 (当前会话): [不可用: {e}]")

# 未纠正错误 (Volatile)
try:
uncorrected_vol = mtmlMemoryGetEccErrorCounter(
memory, MTML_MEMORY_ERROR_TYPE_UNCORRECTED,
MTML_VOLATILE_ECC, MTML_MEMORY_LOCATION_DRAM)
memory,
MTML_MEMORY_ERROR_TYPE_UNCORRECTED,
MTML_VOLATILE_ECC,
MTML_MEMORY_LOCATION_DRAM,
)
print(f" 未纠正错误 (当前会话): {uncorrected_vol}")
except MTMLError as e:
print(f" 未纠正错误 (当前会话): [不可用: {e}]")

# 已纠正错误 (Aggregate)
try:
corrected_agg = mtmlMemoryGetEccErrorCounter(
memory, MTML_MEMORY_ERROR_TYPE_CORRECTED,
MTML_AGGREGATE_ECC, MTML_MEMORY_LOCATION_DRAM)
memory,
MTML_MEMORY_ERROR_TYPE_CORRECTED,
MTML_AGGREGATE_ECC,
MTML_MEMORY_LOCATION_DRAM,
)
print(f" 已纠正错误 (累计): {corrected_agg}")
except MTMLError as e:
print(f" 已纠正错误 (累计): [不可用: {e}]")

# 未纠正错误 (Aggregate)
try:
uncorrected_agg = mtmlMemoryGetEccErrorCounter(
memory, MTML_MEMORY_ERROR_TYPE_UNCORRECTED,
MTML_AGGREGATE_ECC, MTML_MEMORY_LOCATION_DRAM)
memory,
MTML_MEMORY_ERROR_TYPE_UNCORRECTED,
MTML_AGGREGATE_ECC,
MTML_MEMORY_LOCATION_DRAM,
)
print(f" 未纠正错误 (累计): {uncorrected_agg}")
except MTMLError as e:
print(f" 未纠正错误 (累计): [不可用: {e}]")
Expand Down
48 changes: 34 additions & 14 deletions examples/08_topology_and_mtlink.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
print(f" 设备 {i}: {name}")

# MtLink 信息
print(f"\n--- MtLink 信息 ---")
print("\n--- MtLink 信息 ---")
mtlink_state_names = {
MTML_MTLINK_STATE_DOWN: "断开",
MTML_MTLINK_STATE_UP: "连接",
Expand Down Expand Up @@ -75,7 +75,7 @@
MTML_TOPOLOGY_SYSTEM: "跨NUMA节点",
}

print(f"\n--- 拓扑关系矩阵 ---")
print("\n--- 拓扑关系矩阵 ---")
for i in range(device_count):
for j in range(i + 1, device_count):
try:
Expand All @@ -86,36 +86,54 @@
print(f" 设备 {i} <-> 设备 {j}: [不可用: {e}]")

# P2P 状态
print(f"\n--- P2P 状态 ---")
print("\n--- P2P 状态 ---")
for i in range(device_count):
for j in range(i + 1, device_count):
try:
read_status = mtmlDeviceGetP2PStatus(devices[i], devices[j], MTML_P2P_CAPS_READ)
write_status = mtmlDeviceGetP2PStatus(devices[i], devices[j], MTML_P2P_CAPS_WRITE)
read_ok = "OK" if read_status == MTML_P2P_STATUS_OK else f"Status={read_status}"
write_ok = "OK" if write_status == MTML_P2P_STATUS_OK else f"Status={write_status}"
read_status = mtmlDeviceGetP2PStatus(
devices[i], devices[j], MTML_P2P_CAPS_READ
)
write_status = mtmlDeviceGetP2PStatus(
devices[i], devices[j], MTML_P2P_CAPS_WRITE
)
read_ok = (
"OK"
if read_status == MTML_P2P_STATUS_OK
else f"Status={read_status}"
)
write_ok = (
"OK"
if write_status == MTML_P2P_STATUS_OK
else f"Status={write_status}"
)
print(f" 设备 {i} <-> 设备 {j}: 读={read_ok}, 写={write_ok}")
except MTMLError as e:
print(f" 设备 {i} <-> 设备 {j}: [不可用: {e}]")

# MtLink 布局
print(f"\n--- MtLink 布局 ---")
print("\n--- MtLink 布局 ---")
for i in range(device_count):
for j in range(i + 1, device_count):
try:
link_count = mtmlDeviceCountMtLinkLayouts(devices[i], devices[j])
print(f" 设备 {i} <-> 设备 {j}: {link_count} 条链路")
if link_count > 0:
layouts = mtmlDeviceGetMtLinkLayouts(devices[i], devices[j], link_count)
layouts = mtmlDeviceGetMtLinkLayouts(
devices[i], devices[j], link_count
)
for layout in layouts:
print(f" 本地链路ID={layout.localLinkId} <-> 远程链路ID={layout.remoteLinkId}")
print(
f" 本地链路ID={layout.localLinkId} <-> 远程链路ID={layout.remoteLinkId}"
)
except MTMLError as e:
print(f" 设备 {i} <-> 设备 {j}: [不可用: {e}]")

# MtLink 最短路径 (两设备间)
print(f"\n--- MtLink 最短路径 ---")
print("\n--- MtLink 最短路径 ---")
try:
path_count, path_length = mtmlDeviceCountMtLinkShortestPaths(devices[0], devices[1])
path_count, path_length = mtmlDeviceCountMtLinkShortestPaths(
devices[0], devices[1]
)
print(f" 设备 0 -> 设备 1: {path_count} 条路径, 长度 {path_length}")
if path_count > 0 and path_length > 0:
paths = mtmlDeviceGetMtLinkShortestPaths(
Expand All @@ -127,12 +145,14 @@
print(f" [不可用: {e}]")

# 按拓扑层级统计设备 / 获取同层级设备
print(f"\n--- 按拓扑层级设备 ---")
print("\n--- 按拓扑层级设备 ---")
for level in range(MTML_TOPOLOGY_SYSTEM + 1):
try:
count = mtmlDeviceCountDeviceByTopologyLevel(devices[0], level)
if count > 0:
level_devs = mtmlDeviceGetDeviceByTopologyLevel(devices[0], level, count)
level_devs = mtmlDeviceGetDeviceByTopologyLevel(
devices[0], level, count
)
print(f" 层级 {level}: {count} 个设备 (GetDeviceByTopologyLevel)")
except MTMLError:
pass
Expand Down
Loading
Loading