[runtime] Add a profiling mode to the model thread pool (#980)
- [runtime] Add a profiling mode to the model thread pool
A decode step runs a few hundred short parallel regions, and the time between them, when the calling thread works alone and the other threads spin, did not show in a perf profile as anything but the spinning (
worker,__kmpc_barrier). With BUDDY_THREAD_POOL_PROFILE=1 the pool times every region and prints, when the model library is unloaded, the totals (time from the first region to the last, time in regions, serial time between them, barrier waits) and per region function (+): calls, wall time, serial time before and after it, the barrier waits of all threads and of thread 0, and the barriers.On the SpacemiT K3 this attributed 7.2 ms of an 80.8 ms decode step of Qwen3-VL-30B-A3B to serial time and ~1.9 ms to load imbalance, and named the regions they precede. Timing costs two clock reads per region and per barrier (under 1% of that step); without the variable, one branch. Model results are unchanged.
test_buddy_thread_pool.py checks the profile’s call count per region function (it fails without the change).
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
- [runtime] Thread pool profile: link libdl, report slot overflow, name gaps
Review fixes:
- The model library links -ldl with the pool: dladdr is in libdl before glibc 2.34 (with 2.34 or later, as with the K3 sysroot, it binds to libc).
- A region function that finds no free slot was counted in another function’s slot. Such functions are now counted together as other+0x0, with a warning (BUDDY_THREAD_POOL_PROFILE_SLOTS sets the table size, for the test).
- The columns serial_before / serial_after are gap_before / gap_after: they are all the wall time between two regions, which includes time the process spends outside the model, not only serial work. The docs say when they measure serial work, that the two columns attribute the same gaps (not to be added), and that the overhead was measured on the K3 with 8 threads.
- The test checks that the time from the first region to the last is the time in regions plus the gaps, profiles the two-application-thread test (calls [2, 2000, 2000]), checks the overflow with 2 slots, and fails if a profiled run exits non-zero.
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
Co-authored-by: Claude Opus 5.5 noreply@anthropic.com
版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9
京公网安备 11010802047560号
BUDDY MLIR
An MLIR-based compiler framework designed for a co-design ecosystem from DSL (domain-specific languages) to DSA (domain-specific architectures). (Project page)
Getting Started
Dependencies
Please make sure the dependencies are available on your machine.
Clone and Initialize
Prepare Python Environment
pip
uv
conda
Build and Test LLVM/MLIR/CLANG
If your target machine includes an NVIDIA GPU, you can add the following configuration:
Build buddy-mlir
Set the
PYTHONPATHenvironment variable to include both the LLVM/MLIR Python bindings andbuddy-mlirPython packages:If you want to test your model end-to-end conversion and inference, you can add the following configuration
Building and running the model
Use the following to build:
For Whisper, use the same build entry point with the Whisper spec:
DeepSeek R1, Whisper, and Qwen3-VL support template-based layer-partitioned compilation. It is disabled by default. Enable it explicitly by passing
--cmake-args=-DBUDDY_MODEL_LAYER_PARTITION=ONtobuild_model.py. DeepSeek R1 also retains the existingPartitionedGraphDriverworkflow. See Layer Partitioning for details.For example, enable template-based layer partitioning for Whisper with:
To import weights from a local HuggingFace style directory (offline or a custom path), pass
--local-modelto that directory (it must containconfig.jsonand the weight files). If you omit--hf-config,build_model.pyuses<local-model>/config.jsonfor codegen when present:If CMake is configured with
-DBUDDY_BUILD_DEEPSEEK_R1_MODEL=ON, you can build the model with:To build the DeepSeek R1 f32 tiered KV cache variant for use with
buddy-cli, use the dedicated spec:Whisper uses the same
.rax/buddy-clideployment path, with an audio input:Qwen3-VL (vision-language OCR)
models/qwen3_vlis a self-contained vision-language model (ViT + DeepStack encoder feeding a dense Qwen3 decoder) that runs end-to-end on buddy-compiled kernels viabuddy-cli. Use the sametools/buddy-codegen/build_model.pyentry point with the Qwen3-VL spec (a local HuggingFace snapshot is required):See
models/qwen3_vl/README.mdfor prerequisites and details.Build Python Package
We use
setuptoolsto bundle CMake outputs (Python packages,bin/, andlib/) into a single wheel.Build x86_64 artifacts:
Build riscv64 artifacts:
This script calls
docker runinternally to enter the offical manylinux container, builds LLVM and buddy_mlir, and writes artifacts to:./build-docker/x86_64/<py_tag>/target./build-docker/riscv64/<py_tag>/targetSee Manylinux release notes for current known build notes.
Install and test the wheel:
Examples
We provide examples to demonstrate how to use the passes and interfaces in
buddy-mlir, including IR-level transformations, domain-specific applications, and testing demonstrations.For more details, please see the examples documentation.
Contributions
We welcome contributions to our open-source project!
Before contributing, please read the Contributor Guide and Code Style.
To maintain code quality, this project provides pre-commit checks:
How to Cite
If you find our project and research useful or refer to it in your own work, please cite the survey paper in which the Buddy Compiler design was first proposed:
For direct access to the paper, please visit Compiler Technologies in Deep Learning Co-Design: A Survey.