Skip to content

Benchmarking DeepGEMM main vs migrate_pybind_to_torch_library_dev branch - #9

Open
cleonard530 wants to merge 13 commits into
migrate_pybind_to_torch_library_devfrom
benchmark_branch
Open

cleonard530 wants to merge 13 commits into
migrate_pybind_to_torch_library_devfrom
benchmark_branch

Conversation

@cleonard530

@cleonard530 cleonard530 commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Summary

This has 3 python scripts used for benchmarking the performance between DeepGEMM on main vs migrate_pybind_to_torch_library_dev where I migrated DeepGEMM kernel registration off pybind11 and onto TORCH_LIBRARY. In the runs on main, DeepJIT uses the current version of DeepJIT on main, while the migrate_pybind_to_torch_library_dev branch uses the updated DeepJIT on deepseek-ai/DeepJIT#11, removing the dependency of pybind11 for the GIL release (since torch.ops release the GIL already) and allowing us to build with the CPython Stable ABI (abi3). This branch of DeepJIT also moved the unstable Torch calls to Stable ABI torch calls, which isn't necessary for this first update but is our ultimate goal (see vllm-project/vllm#26946). The only call this changes, is using a stable version of the at::cuda::getCurrentCUDAStream().stream().

The 3 scripts are:

  1. scripts/benchmark_kernels.py‎ - script benchmarking all gemm kernels that can run on NVIDIA H200 (plan to run B200 later)
  2. scripts/benchmark_sm90_deepjit.py - script to benchmark a select few of the gemm kernels, including the DeepJIT compile times.
  3. scripts/benchmark_gil_production.py‎ - Test a single kernel, but testing differnce between pybind11 and TORCH_TENSORS interaction with the GIL.

Results

  1. scripts/benchmark_kernels.py‎

The kernel run times where basically identical on main and on migrate_pybind_to_torch_library_dev. You can checkout kernel_benchmark_comparison.txt to see the comparison between average run times for 1000 runs each. The results show ~ +/- 1% difference between runs on each branch.

  1. scripts/benchmark_sm90_deepjit.py

The results of this run are in ‎deepjit_main.txt and deepjit_torch_library.txt where each kernel is ran 5 times. Again, the results between main and migrate_pybind_to_torch_library_dev are nearly identical, for cold first call, disk-cache first call, and the warm calls.

  1. scripts/benchmark_gil_production.py‎

This script considers the thread management. It basically calls

start worker thread

start timer
call kernel 1,000 times
wait for all GPU work to finish
stop timer

stop worker thread

The script tests no worker, an I/O-like worker, a scheduler-like worker, and a continuously CPU-bound worker. It also measures how much progress the worker makes relative to running alone. Calls through torch.ops release the GIL around operator dispatch, allowing other Python threads to make progress. Under normal I/O-like and scheduler-like activity, this produced little or no foreground latency penalty in these measurements.
The continuously CPU-bound case exposed a tradeoff. Once that thread acquires the GIL, the main thread can be delayed before it can issue its next Python-level operator call. DeepJIT on main also releases the GIL around CUDA dispatch, but only around the kernel call. That shorter release window provides less opportunity for repeated GIL handoffs than releasing it around the complete torch.ops dispatch. Consequently, TORCH_LIBRARY improves the opportunity for competing Python threads to run, but it can increase foreground latency when many short, separate operators compete with a non-yielding CPU-bound Python thread. CUDA graph capture mitigates this case because a captured sequence can be replayed through fewer Python operator calls.

This benchmark intentionally creates an adverse GIL-contention scenario: short kernels, many separate uncaptured calls, and a continuously CPU-bound Python thread in the same process. The behavior is not specific to DeepGEMM; it is a general consideration when replacing a pybind11 binding with a torch.ops binding.

The results can be found ‎gil_production_results_torch_deepjit_main.json and gil_production_results_torch_deepjit_torch_gil.json‎ with a significant difference in median_foreground_us_per_call for the cpu_bound tests.

@cleonard530 cleonard530 changed the title Benchmark branch Benchmarking DeepGEMM main vs migrate_pybind_to_torch_library_dev branch Sep 23, 2026
@cleonard530
cleonard530 force-pushed the migrate_pybind_to_torch_library_dev branch from b201a73 to dec2595 Compare September 24, 2026 12:56
cleonard530 pushed a commit that referenced this pull request Sep 24, 2026
* fix(sm120): correct ported GEMM and MQA execution paths

Signed-off-by: Zihua Wu <13583761+lucifer1004@users.noreply.github.com>

* test(sm120): name checks by behavior and split omnibus tests

Signed-off-by: Zihua Wu <13583761+lucifer1004@users.noreply.github.com>

* test(sm120): move SM120 regressions into dedicated test files

Move all SM120-specific regression tests out of upstream-owned test
files into tests/test_sm120_{bf16,fp8_fp4,einsum,hyperconnection,skip_head}.py
so the fork's tests/ directory stays byte-identical to dev on upstream
files (one documented exception: the cross-case tensor lifetime fix in
test_paged_mqa_logits). This removes every sync-conflict surface from
upstream's per-release rewrites of the shared test files.

All moved tests switch to upstream's call-time test_filter gating, so
non-SM120 machines see zero behavior change at collection, under
pytest, in test_sanitizer.py's direct-call discovery, and via __main__.
Each new file is a self-contained script with its own __main__ runner.

Signed-off-by: Zihua Wu <13583761+lucifer1004@users.noreply.github.com>

---------

Signed-off-by: Zihua Wu <13583761+lucifer1004@users.noreply.github.com>
… branch. Will need to figure out how to handle DeepJIT.

Signed-off-by: Chris Leonard <chleonar@redhat.com>
…nd for GIL release. We will need to come back and address this later

Signed-off-by: Chris Leonard <chleonar@redhat.com>
…eplacing _C with _C_extension

Signed-off-by: Chris Leonard <chleonar@redhat.com>
…hon_api.cpp like it was before, added some checks to mega_moe.hpp to keep the new registration inline with the pybind registration.

Signed-off-by: Chris Leonard <chleonar@redhat.com>
Signed-off-by: Chris Leonard <chleonar@redhat.com>
Signed-off-by: Chris Leonard <chleonar@redhat.com>
…hpp to disable to gil.hpp in DeepJIT, this is just temporary and will need to be changed upstream

Signed-off-by: Chris Leonard <chleonar@redhat.com>
…of doing it itslef (requires changes to DeepJIT)

Signed-off-by: Chris Leonard <chleonar@redhat.com>
@cleonard530
cleonard530 force-pushed the migrate_pybind_to_torch_library_dev branch from dec2595 to 66d8928 Compare September 24, 2026 12:59
… to verify where it is being dispatched form (pybind or torch_library)
@cleonard530
cleonard530 force-pushed the migrate_pybind_to_torch_library_dev branch 2 times, most recently from 9560d13 to 45d9a65 Compare September 30, 2026 12:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant