Skip to content

Optimize DeepSeek V4 startup with reusable programs and prepacked weights - #124

Open
puddingfjz wants to merge 1 commit into
hw-native-sys:mainfrom
puddingfjz:codex/combine-deepseek-startup-optimizations
Open

Optimize DeepSeek V4 startup with reusable programs and prepacked weights#124
puddingfjz wants to merge 1 commit into
hw-native-sys:mainfrom
puddingfjz:codex/combine-deepseek-startup-optimizations

Conversation

@puddingfjz

@puddingfjz puddingfjz commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Reduce DeepSeek V4 model preparation time by combining three complementary startup optimizations:

  • compile PyPTO programs directly from tensor signatures instead of materializing large dummy tensors;
  • reuse compiled programs and assembled callable artifacts across launches;
  • load an optional prepacked rank-stacked weight sidecar when it is already resident in the Linux page cache.

In the steady-state configuration with a warm kernel cache and hot weight sidecar, model registration decreased from 506.758 seconds to an average of 90.595 seconds: an 82.1% reduction, or 5.59x speedup.

Changes

Signature-based compilation

  • Build the four DeepSeek programs from evaluated tensor signatures and scalar arguments.
  • Remove large dummy-tensor materialization, including the expensive MTP argument preparation.
  • Preserve distinct signatures for main prefill, main decode, MTP prefill, and MTP decode.

Persistent callable cache

  • Add an optional --kernel-cache-dir serving argument.
  • Persist compiled programs together with fully assembled callable output directories.
  • Validate cache entries using code, JIT signature, and scalar-argument fingerprints.
  • Calculate cache fingerprints without reconstructing the removed dummy tensors.
  • Recompile automatically when an entry is missing, stale, or unusable.

Prepacked layer weights

  • Add a tool for generating a rank-stacked DeepSeek V4 safetensors sidecar.
  • Validate its format, source checkpoint fingerprint, tensor names, shapes, and rank layout.
  • Map the prepacked tensors directly and skip the normal hidden-layer load and packing process.
  • Sample Linux page-cache residency with mincore().
  • Fall back to the original checkpoint loader when fewer than 95% of sampled sidecar pages are resident.

The default path remains unchanged when no kernel cache or usable sidecar is available.

Performance

Environment:

  • pypto-serving base: e57e14f
  • PyPTO: 478ddad5a
  • Simpler runtime: 9922afdb
  • pypto-lib: 7e7d4cc
  • PTOAS: 0.48
  • Model: DeepSeek V4 Flash W8A8
  • Parallelism: DP=8, EP=8, MTP enabled
Scenario Registration Change from control
Control 506.758 s
Cache miss + publication, cold-sidecar fallback 349.297 s -31.1%
Cache hit, cold-sidecar fallback 276.206 s -45.5%
Cache hit + hot sidecar, run 1 94.058 s -81.4%
Cache hit + hot sidecar, run 2 87.133 s -82.8%
Hot steady-state average 90.595 s -82.1%, 5.59x faster

Hot-run component times:

Component Time
Layer load and pack approximately 0 s
Persistent worker creation 3.1–4.0 s
Main weight upload 53.9–58.8 s
MTP weight upload 0.8–1.2 s

The cache-hit/cold-sidecar launch ran under unusually heavy Host load: layer packing increased from the control's 90.642 seconds to 223.768 seconds. It validates the cache-hit path but is not used as a clean absolute steady-state comparison.

Sidecar behavior

The sidecar contains 322.818 GiB of prepacked weights. A cold sidecar is deliberately rejected because synchronously reading that amount of data can be slower than the original loader. The measured first full read took 577.710 seconds under concurrent machine load.

A hot mmap-backed sidecar still increases main upload from approximately 25 seconds to 50–59 seconds. Page-cache residency avoids disk I/O, but each serving process must still establish page-table mappings and pin or map approximately 84.6 million pages during the first device upload. Avoiding approximately 91 seconds of layer packing nevertheless provides a substantial net improvement.

Validation

  • 56 targeted DeepSeek and kernel-cache tests passed.
  • Ruff checks passed.
  • Header and English-only checks passed.
  • The four DeepSeek program signatures produce distinct stable cache keys.
  • Hardware launches confirmed four cache hits and successful prepacked-sidecar mapping.
  • Two independent hot-sidecar launches reproduced 87–94 second registration times.

Hardware-test limitation

The hardware launches completed program preparation, worker creation, and resident main/MTP weight upload. They then failed while sizing the KV cache because residual device allocations left only approximately 6.2 GB free, which was insufficient under npu_memory_utilization=0.90.

The reported PyptoExecutor.register_model trace spans are complete through the upload and capacity-check boundary, but these measurements do not replace a clean end-to-end health, prefill, and decode validation. A follow-up run on devices without residual HBM allocations is still required.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 190f4145-fb2b-49a6-af7d-0447b70d1f4b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds shared persistent kernel caching, DeepSeek V4 runtime integration, validated prepacked weight sidecars, a prepacking CLI, packaging and documentation updates, and expanded tests.

Changes

DeepSeek V4 serving enhancements

Layer / File(s) Summary
Shared kernel-cache infrastructure
pypto_serving/model/common/kernel_cache.py, pypto_serving/model/qwen/kernel_cache.py, tests/test_kernel_cache.py
Adds shared source and specialization fingerprints, atomic compiled-program cache storage, and updates Qwen to use the shared cache implementation.
Prepacked weight sidecar
pypto_serving/model/deepseek/weight_loader.py, pypto_serving/tools/prepack_deepseek_v4.py, pyproject.toml, docs/dev/model/deepseek-v4.md, tests/test_deepseek_v4.py
Adds validated rank-stacked safetensors loading, atomic sidecar generation, a console command, documentation, and sidecar tests.
DeepSeek runtime integration
pypto_serving/model/deepseek/kernel_cache.py, pypto_serving/model/deepseek/npu_executor.py, pypto_serving/model/deepseek/npu_runner.py, pypto_serving/cli/main.py, tests/test_deepseek_v4.py
Wires kernel-cache configuration into DeepSeek compilation and execution, fingerprints scalar specializations, reuses compiled programs, and passes prepacked weights through the runner.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant CLI
  participant DeepSeekExecutor
  participant KernelCache
  participant WeightStore
  participant ModelRunner
  Operator->>CLI: start DeepSeek V4 with cache directory
  CLI->>DeepSeekExecutor: pass kernel_cache_dir
  DeepSeekExecutor->>WeightStore: load validated prepacked layer weights
  DeepSeekExecutor->>KernelCache: load compiled L3 program by fingerprints
  KernelCache-->>DeepSeekExecutor: cached program or miss
  DeepSeekExecutor->>ModelRunner: provide compiled kernels and weights
  ModelRunner->>KernelCache: store newly assembled binaries
Loading

Poem

A rabbit hops where kernels compile,
Sidecars stack weights in a tidy line.
Old launches bloom with cached delight,
Fingerprints guard each program right.
“Prepack!” cries Bun, “then run with glee!”

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No pull request description was provided, so the description's relevance cannot be assessed. Add a brief description of the DeepSeek startup optimization changes and expected behavior.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly matches the main change: faster DeepSeek V4 startup via reusable compiled programs and prepacked weights.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@puddingfjz puddingfjz changed the title Codex/combine deepseek startup optimizations Optimize DeepSeek V4 startup with reusable programs and prepacked weights Jul 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
tests/test_kernel_cache.py (1)

117-161: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider covering the fingerprint-unavailable path.

Both new tests exercise the happy path. A case asserting compute_params_fingerprint("x", object(), scalar_args=None, platform="a2a3", block_dim=None) == UNKNOWN would pin the contract that a missing _func disables reuse (which KernelCache._usable depends on).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_kernel_cache.py` around lines 117 - 161, Add a test covering the
unavailable-fingerprint path by calling compute_params_fingerprint with an
object lacking _func, no scalar arguments, platform "a2a3", and no block
dimension, then assert it returns UNKNOWN. Keep the existing happy-path
fingerprint tests unchanged and ensure the assertion captures the contract used
by KernelCache._usable.
pypto_serving/tools/prepack_deepseek_v4.py (1)

103-119: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

mkstemp publishes the sidecar with 0600 permissions.

tempfile.mkstemp creates the file mode 0600, and os.replace preserves it, so a sidecar built by one user is unreadable by a serving process running as another (silently falling back to full repacking). Consider os.chmod(temporary_path, 0o644 & ~current_umask) — or matching the mode of a source shard — before the replace.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pypto_serving/tools/prepack_deepseek_v4.py` around lines 103 - 119, Update
the temporary sidecar creation flow around mkstemp and os.replace to set the
temporary file’s permissions to the intended readable mode before publishing it.
Account for the current umask (or match the source shard mode) so the replaced
output is readable by other serving users while preserving appropriate
permission restrictions.
pypto_serving/model/deepseek/weight_loader.py (1)

825-832: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Tensor-name drift raises instead of falling back.

Once the fingerprint matches, a name-set mismatch can only mean _DEEPSEEK_V4_PACKED_WEIGHT_NAMES changed without bumping DEEPSEEK_V4_PACKED_FORMAT. Hard-failing startup for an optional optimization is harsher than the stale/cold paths, which log and repack. Either fold the name set into the fingerprint/format so old sidecars are simply "stale", or log a warning and return None here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pypto_serving/model/deepseek/weight_loader.py` around lines 825 - 832, The
packed-weight loader currently raises on tensor-name drift after the fingerprint
matches; change the validation in the DeepSeekV4 sidecar loading path to log a
warning and return None so the caller follows the existing stale/cold repack
fallback. Preserve the missing/extra diagnostics in the warning, and avoid
hard-failing startup for this optional optimization.
tests/test_deepseek_v4.py (1)

461-498: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Pin residency in the happy-path sidecar test.

This test relies on the real _sample_file_page_cache_residency reporting ≥ 95% for the just-written file. On platforms without mincore (or under restrictive containers) it returns None, the sidecar is skipped, and the test then falls into real checkpoint packing and fails on the pytest.fail stub. Monkeypatch it to 1.0 like test_deepseek_weight_store_skips_cold_prepacked_sidecar does.

💚 Proposed fix
+    monkeypatch.setattr(weight_loader, "_sample_file_page_cache_residency", lambda path: 1.0)
     monkeypatch.setattr(
         store,
         "load_packed_layer_weights",
         lambda *args, **kwargs: pytest.fail("valid sidecar must skip checkpoint packing"),
     )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_deepseek_v4.py` around lines 461 - 498, Update
test_deepseek_weight_store_maps_valid_prepacked_sidecar to monkeypatch
_sample_file_page_cache_residency to return 1.0, matching
test_deepseek_weight_store_skips_cold_prepacked_sidecar, so the valid sidecar
path is deterministic across platforms and skips checkpoint packing.
pypto_serving/model/common/kernel_cache.py (1)

145-166: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Concurrent store publish is not fully atomic despite the docstring.

shutil.rmtree(slot) followed by os.replace(tmp, slot) leaves a window where the slot is absent, and two launches storing the same name can collide (the loser's rmtree/replace raises and is swallowed). Practically safe since a concurrent load degrades to a MISS, but consider softening the docstring or guarding with a lock file if parallel launches share one cache dir.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pypto_serving/model/common/kernel_cache.py` around lines 145 - 166, Update
the store method’s docstring to avoid claiming the publish is fully atomic, or
add synchronization for same-name concurrent stores using a lock file around the
slot replacement sequence. Ensure concurrent writers do not surface
rmtree/replace collisions and concurrent loads retain valid cache behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pypto_serving/model/deepseek/kernel_cache.py`:
- Around line 47-76: The DeepSeek cache fingerprint must include resolved layout
and deployment dimensions so specializations cannot collide when annotations are
lazy. Update compute_params_fingerprint to incorporate decode_batch, decode_seq,
decode_tokens, and prefill_seq, and revise pypto_serving/cli/main.py lines 51-58
so its invalidation help accurately describes the dimensions covered by the
fingerprint.

In `@pypto_serving/model/deepseek/npu_executor.py`:
- Around line 369-377: Update
DeepSeekV4ModelRunner._materialize_resident_weights to clear the compiled
prepacked layer-weight reference after its tensors have been uploaded, matching
the existing embedding_weight cleanup. Release
DeepSeekV4CompiledKernels.prepacked_layer_weights (including its tensors) before
dropping _stacked_host_weights, while preserving the uploaded device weights and
released_parent_host_bytes logging.

In `@pypto_serving/model/deepseek/weight_loader.py`:
- Around line 248-299: Move the os.open call inside the guarded logic of
_sample_file_page_cache_residency so open failures are caught and return None,
preserving fallback behavior. Track the file descriptor as optional and close it
only when successfully opened. Ensure the ctypes anchor is released before
mapping.close(), and include BufferError in the handled probe failures so
cleanup issues also degrade to None rather than escaping.

In `@pypto_serving/tools/prepack_deepseek_v4.py`:
- Around line 82-95: Move the packed_stacked_layer_weights_fingerprint call
before load_stacked_layer_weights in the prepacking flow, while keeping the same
fingerprint arguments. Ensure the fingerprint is captured before the lengthy
packing operation and then used unchanged for subsequent sidecar validation.

---

Nitpick comments:
In `@pypto_serving/model/common/kernel_cache.py`:
- Around line 145-166: Update the store method’s docstring to avoid claiming the
publish is fully atomic, or add synchronization for same-name concurrent stores
using a lock file around the slot replacement sequence. Ensure concurrent
writers do not surface rmtree/replace collisions and concurrent loads retain
valid cache behavior.

In `@pypto_serving/model/deepseek/weight_loader.py`:
- Around line 825-832: The packed-weight loader currently raises on tensor-name
drift after the fingerprint matches; change the validation in the DeepSeekV4
sidecar loading path to log a warning and return None so the caller follows the
existing stale/cold repack fallback. Preserve the missing/extra diagnostics in
the warning, and avoid hard-failing startup for this optional optimization.

In `@pypto_serving/tools/prepack_deepseek_v4.py`:
- Around line 103-119: Update the temporary sidecar creation flow around mkstemp
and os.replace to set the temporary file’s permissions to the intended readable
mode before publishing it. Account for the current umask (or match the source
shard mode) so the replaced output is readable by other serving users while
preserving appropriate permission restrictions.

In `@tests/test_deepseek_v4.py`:
- Around line 461-498: Update
test_deepseek_weight_store_maps_valid_prepacked_sidecar to monkeypatch
_sample_file_page_cache_residency to return 1.0, matching
test_deepseek_weight_store_skips_cold_prepacked_sidecar, so the valid sidecar
path is deterministic across platforms and skips checkpoint packing.

In `@tests/test_kernel_cache.py`:
- Around line 117-161: Add a test covering the unavailable-fingerprint path by
calling compute_params_fingerprint with an object lacking _func, no scalar
arguments, platform "a2a3", and no block dimension, then assert it returns
UNKNOWN. Keep the existing happy-path fingerprint tests unchanged and ensure the
assertion captures the contract used by KernelCache._usable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3dd17a2a-5527-476f-8e56-ea2d942ba2ce

📥 Commits

Reviewing files that changed from the base of the PR and between e57e14f and d0cef65.

📒 Files selected for processing (12)
  • docs/dev/model/deepseek-v4.md
  • pyproject.toml
  • pypto_serving/cli/main.py
  • pypto_serving/model/common/kernel_cache.py
  • pypto_serving/model/deepseek/kernel_cache.py
  • pypto_serving/model/deepseek/npu_executor.py
  • pypto_serving/model/deepseek/npu_runner.py
  • pypto_serving/model/deepseek/weight_loader.py
  • pypto_serving/model/qwen/kernel_cache.py
  • pypto_serving/tools/prepack_deepseek_v4.py
  • tests/test_deepseek_v4.py
  • tests/test_kernel_cache.py

Comment thread pypto_serving/model/deepseek/kernel_cache.py
Comment thread pypto_serving/model/deepseek/npu_executor.py
Comment thread pypto_serving/model/deepseek/weight_loader.py Outdated
Comment thread pypto_serving/tools/prepack_deepseek_v4.py
Compile DeepSeek programs from signatures, reuse assembled kernel artifacts, and load validated hot prepacked weights without rebuilding the stacked layout. Harden cache fingerprints, sidecar fallback, permissions, and Host mapping cleanup.
@puddingfjz
puddingfjz force-pushed the codex/combine-deepseek-startup-optimizations branch from d0cef65 to 6527c66 Compare July 30, 2026 10:00
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