Problem Statement
MetaX C500 support is functional with the current OpenMPI backend, but the
backend moves accelerator buffers through host staging memory:
- device buffer -> host buffer
- MPI collective or point-to-point operation on host memory
- host buffer -> device buffer
This path is portable and useful as a bootstrap implementation, but the current
performance is limited by host staging overhead. The first experiment showed
that repeated host buffer allocation was a major avoidable cost for larger
messages.
Environment
- Host:
res-macloud-b01
- Accelerator: 4 x MetaX C500 (
XCORE1000, reported by macainfo)
- MACA SDK:
/opt/maca -> /opt/maca-3.7.0
mxcc: mxcc version 1.0.0 (d9102a1572)
- OpenMPI:
/opt/maca/ompi, mpirun (Open MPI) 4.1.6
- CMake:
3.31.10
- Backend/device configuration:
WITH_METAX=ON, WITH_OMPI=ON
Manual build command used for reliable MetaX compilation:
export MACA_PATH=/opt/maca
export PATH="$MACA_PATH/ompi/bin:$PATH"
export LD_LIBRARY_PATH="$MACA_PATH/lib:$MACA_PATH/ompi/lib:$LD_LIBRARY_PATH"
export OMPI_CC="$PWD/scripts/devices/mxcc_wrapper.sh"
export OMPI_CXX="$PWD/scripts/devices/mxcc_wrapper.sh"
cmake -S . -B build-metax-fixed \
-DCMAKE_BUILD_TYPE=Release \
-DWITH_METAX=ON -DWITH_OMPI=ON \
-DAUTO_DETECT_DEVICES=OFF -DAUTO_DETECT_BACKENDS=OFF \
-DCMAKE_C_COMPILER="$MACA_PATH/ompi/bin/mpicc" \
-DCMAKE_CXX_COMPILER="$MACA_PATH/ompi/bin/mpicxx"
cmake --build build-metax-fixed -j 8
Note: OpenMPI cannot initialize sockets inside the restricted sandbox used by
the agent, so runtime experiments were launched outside the sandbox.
Experiments
Correctness smoke tests
All internal examples passed on 2 ranks:
all_reduce
all_gather
all_to_all
broadcast
reduce
reduce_scatter
send_recv
Example command:
mpirun --allow-run-as-root -np 2 ./build-metax-fixed/examples/all_reduce
Observed all_reduce result:
Correct: YES
Expect: 3.00
Actual: 3.00
Microbenchmark
A new benchmark was added at examples/metax_bench.cc to compare:
copy_d2h: device-to-host copy
copy_h2d: host-to-device copy
copy_roundtrip: D2H + H2D
host_allreduce: host-only MPI_Allreduce
stage_reuse: manual D2H + MPI + H2D with reusable host buffers
stage_alloc: manual D2H + MPI + H2D with per-call malloc/free
infiniccl_allreduce: public InfiniCCL API path
Example command:
mpirun --allow-run-as-root -np 4 ./build-metax-fixed/examples/metax_bench \
--elements 65536,262144,1048576,4194304 \
--modes host_allreduce,stage_reuse,stage_alloc,infiniccl_allreduce \
--warmup 5 --iters 20 --validate
Key Findings
Before host staging buffer reuse
infiniccl_allreduce was close to stage_alloc, which indicated that repeated
host buffer allocation was a major cost.
| Case |
stage_reuse |
Original infiniccl_allreduce |
| 2 ranks, 4 MB |
3.36 ms |
9.02 ms |
| 2 ranks, 16 MB |
12.78 ms |
36.41 ms |
| 4 ranks, 4 MB |
4.89 ms |
10.19 ms |
| 4 ranks, 16 MB |
17.57 ms |
42.29 ms |
After host staging buffer reuse
A reusable thread-local host staging buffer was added for the OpenMPI backend.
After the change, infiniccl_allreduce moved close to the stage_reuse
baseline.
| Case |
Optimized infiniccl_allreduce |
| 2 ranks, 4 MB |
3.47 ms |
| 2 ranks, 16 MB |
12.74 ms |
| 4 ranks, 4 MB |
4.45 ms |
| 4 ranks, 16 MB |
16.69 ms |
This is roughly a 2x-3x improvement for large AllReduce messages compared with
the original implementation.
Changes Made During Investigation
Build and documentation
- Removed late mutation of
CMAKE_C_COMPILER and CMAKE_CXX_COMPILER from the
MetaX branch in top-level CMakeLists.txt.
- Updated
scripts/build.sh to detect MetaX and use MACA OpenMPI wrappers with
OMPI_CC/OMPI_CXX pointing to scripts/devices/mxcc_wrapper.sh.
- Made
scripts/build.sh tolerate a read-only ~/.bashrc.
- Documented the MetaX + OpenMPI manual build path in
README.md.
- Ignored
build-* directories.
Runtime/backend
- Added
src/ompi/staging_buffer.h.
- Replaced per-call host staging
malloc/free in the OpenMPI backend with
reusable thread-local staging buffers.
- Applied the staging buffer reuse to:
AllReduce
AllGather
AllToAll
Broadcast
Reduce
ReduceScatter
Send
Recv
- Added
examples/metax_bench.cc for repeatable MetaX/OpenMPI experiments.
Remaining Issues
1. OpenMPI backend is still host-staging based
The current path still copies data through host memory. Buffer reuse removes a
large allocation overhead, but it does not remove the D2H/H2D copies.
Follow-up options:
- Investigate MACA/MCCL backend support for native accelerator collectives.
- Investigate whether MACA OpenMPI supports GPU-aware MPI for MetaX buffers.
- Add an optional direct device-buffer MPI path if supported and safe.
2. Staging buffers are pageable host memory
The reusable buffers currently use std::malloc. Copy bandwidth may improve if
MACA provides pinned/page-locked host allocation APIs.
Follow-up options:
- Check MACA runtime support for pinned host memory.
- Add a staging allocator abstraction with normal malloc fallback.
- Benchmark pageable vs pinned host staging.
3. ReduceScatter still needs separate analysis
Correctness passes, but reduce_scatter did not show the same clear timing
improvement as AllReduce in the example-level test. It should be investigated
separately with a benchmark mode that matches the exact ReduceScatter data
layout and counts.
Follow-up options:
- Extend
metax_bench with reduce_scatter modes.
- Compare
MPI_Reduce_scatter_block against alternative decompositions.
- Check if count, buffer size, or MPI algorithm selection is dominating.
4. MPI errors abort the process
INFINI_CHECK_MPI currently aborts on MPI errors. This is harsh for a library
API that otherwise returns ReturnStatus.
Follow-up options:
- Convert MPI error handling to return
ReturnStatus.
- Include MPI error strings in logs.
- Keep abort behavior only under an explicit debug/fail-fast option.
5. Device binding is OpenMPI-specific
MetaX device selection currently relies on OMPI_COMM_WORLD_LOCAL_RANK.
Follow-up options:
- Add fallbacks for common MPI/PMI local-rank environment variables.
- Query MetaX device count and validate selected device IDs.
- Consider modulo mapping or explicit
devlist behavior for oversubscription.
6. Reusable staging buffer retention needs policy
The new thread-local staging buffers keep the largest capacity seen by each
thread. This is good for repeated collectives but can retain large host memory
after a single large operation.
Follow-up options:
- Add an upper bound or shrink policy.
- Add an environment variable for staging buffer cache size.
- Add communicator-level or backend-level cleanup hooks if needed.
Proposed Next Steps
- Keep the reusable host staging buffer optimization; it gives a clear
improvement with low API risk.
- Extend
metax_bench to cover all_gather, all_to_all, broadcast,
reduce, reduce_scatter, send, and recv.
- Add pinned host staging support if MACA exposes a suitable API.
- Investigate MCCL or GPU-aware MPI support as the higher-ceiling path.
- Harden error handling and device binding before larger multi-node testing.
Problem Statement
MetaX C500 support is functional with the current OpenMPI backend, but the
backend moves accelerator buffers through host staging memory:
This path is portable and useful as a bootstrap implementation, but the current
performance is limited by host staging overhead. The first experiment showed
that repeated host buffer allocation was a major avoidable cost for larger
messages.
Environment
res-macloud-b01XCORE1000, reported bymacainfo)/opt/maca -> /opt/maca-3.7.0mxcc:mxcc version 1.0.0 (d9102a1572)/opt/maca/ompi,mpirun (Open MPI) 4.1.63.31.10WITH_METAX=ON,WITH_OMPI=ONManual build command used for reliable MetaX compilation:
Note: OpenMPI cannot initialize sockets inside the restricted sandbox used by
the agent, so runtime experiments were launched outside the sandbox.
Experiments
Correctness smoke tests
All internal examples passed on 2 ranks:
all_reduceall_gatherall_to_allbroadcastreducereduce_scattersend_recvExample command:
Observed
all_reduceresult:Microbenchmark
A new benchmark was added at
examples/metax_bench.ccto compare:copy_d2h: device-to-host copycopy_h2d: host-to-device copycopy_roundtrip: D2H + H2Dhost_allreduce: host-onlyMPI_Allreducestage_reuse: manual D2H + MPI + H2D with reusable host buffersstage_alloc: manual D2H + MPI + H2D with per-callmalloc/freeinfiniccl_allreduce: public InfiniCCL API pathExample command:
Key Findings
Before host staging buffer reuse
infiniccl_allreducewas close tostage_alloc, which indicated that repeatedhost buffer allocation was a major cost.
stage_reuseinfiniccl_allreduceAfter host staging buffer reuse
A reusable thread-local host staging buffer was added for the OpenMPI backend.
After the change,
infiniccl_allreducemoved close to thestage_reusebaseline.
infiniccl_allreduceThis is roughly a 2x-3x improvement for large AllReduce messages compared with
the original implementation.
Changes Made During Investigation
Build and documentation
CMAKE_C_COMPILERandCMAKE_CXX_COMPILERfrom theMetaX branch in top-level
CMakeLists.txt.scripts/build.shto detect MetaX and use MACA OpenMPI wrappers withOMPI_CC/OMPI_CXXpointing toscripts/devices/mxcc_wrapper.sh.scripts/build.shtolerate a read-only~/.bashrc.README.md.build-*directories.Runtime/backend
src/ompi/staging_buffer.h.malloc/freein the OpenMPI backend withreusable thread-local staging buffers.
AllReduceAllGatherAllToAllBroadcastReduceReduceScatterSendRecvexamples/metax_bench.ccfor repeatable MetaX/OpenMPI experiments.Remaining Issues
1. OpenMPI backend is still host-staging based
The current path still copies data through host memory. Buffer reuse removes a
large allocation overhead, but it does not remove the D2H/H2D copies.
Follow-up options:
2. Staging buffers are pageable host memory
The reusable buffers currently use
std::malloc. Copy bandwidth may improve ifMACA provides pinned/page-locked host allocation APIs.
Follow-up options:
3.
ReduceScatterstill needs separate analysisCorrectness passes, but
reduce_scatterdid not show the same clear timingimprovement as AllReduce in the example-level test. It should be investigated
separately with a benchmark mode that matches the exact ReduceScatter data
layout and counts.
Follow-up options:
metax_benchwithreduce_scattermodes.MPI_Reduce_scatter_blockagainst alternative decompositions.4. MPI errors abort the process
INFINI_CHECK_MPIcurrently aborts on MPI errors. This is harsh for a libraryAPI that otherwise returns
ReturnStatus.Follow-up options:
ReturnStatus.5. Device binding is OpenMPI-specific
MetaX device selection currently relies on
OMPI_COMM_WORLD_LOCAL_RANK.Follow-up options:
devlistbehavior for oversubscription.6. Reusable staging buffer retention needs policy
The new thread-local staging buffers keep the largest capacity seen by each
thread. This is good for repeated collectives but can retain large host memory
after a single large operation.
Follow-up options:
Proposed Next Steps
improvement with low API risk.
metax_benchto coverall_gather,all_to_all,broadcast,reduce,reduce_scatter,send, andrecv.