Skip to content

[Engine] DeepSeek 0.1.51: 256K auto RAM store shrinks from 48 GB to 17.8 GB on 2x RTX 3090 #4147

Closed

Description

@Burntgogi

Area

[Engine] (speed, kernels, models, the server and API)

Desktop app, Terminal or source?

Source checkout using serve/server.py with the official prebuilt Linux CUDA13 DeepSeek engine packages. No locally rebuilt or patched native engine.

What happened

After updating from Strata source v0.2.4.2 / DeepSeek engine 0.1.49.2 to v0.2.6 / engine 0.1.51, the automatic expert RAM-store ceiling fell from 48.0 GB to about 17.8 GB on the same two discrete RTX 3090 cards and 64 GB-class RAM system, with a 262144-token context.

The new run retained substantial reclaimable memory headroom: the minimum sampled Linux MemAvailable during validation was about 35.4 GiB. This includes reclaimable file cache; I am not treating it as physically unused RAM, process RSS, or memory that can all safely be allocated.

The new configuration also ran slower in the saved long-context workload. The sizing behavior is locally observed; the degree to which it causes the speed difference has not been isolated by a same-version cache-size A/B.

Expected: automatic sizing should distinguish a discrete-GPU machine from a true unified-memory GPU before applying the additional UMA context reserve. I am not asking it to overcommit RAM or fit the entire CPU expert lane into this 64 GB machine.

Smallest steps or command that reproduce it

These are the conditions under which the startup sizing was observed, not a claim that every dual-GPU machine will reproduce it:

  1. Make both discrete RTX 3090 cards visible and use the existing IST-DAS 2.00bpw pack.
  2. Start the official 0.1.51 engine through the source Python server at context 262144, leaving expert-store size, mmap mode, prefill chunk, CPU threads and expert count at their generated/automatic settings.
  3. Observe the startup RAM-store sizing. This happened on both successful 0.1.51 starts, including a process restart: approximately 17.8 GB and 17.7 GB respectively.

Native invocation recorded by the server, with executable and pack paths replaced by placeholders:

<engine> --serve --pack <PACK_DIR> --max-context 262144 --eos 1 --dspark auto --dspark-conf 0.65 --tp 2 --layer-split auto

There was no explicit --ssd-cache or --mmap-experts setting in the tested model configuration. The native log selected 8192-token prompt chunks and 8 CPU threads. Both versions reported effective TP 2 -> 1 due to this pack's 256-value-block / n_ff 2304 constraint, with layers distributed over both GPUs; this was not a one-card run. DSpark auto did not load the drafter. Expert count was left automatic, with no faster-mode reduction message.

Reproduction status

Reproduced locally: the much smaller automatic RAM-store allocation on this discrete-GPU configuration, and the slower recorded workload. The source explanation below is consistent with the logs and hardware query, but total performance causality is not established.

Strata version

  • Before: source v0.2.4.2; official DeepSeek engine 0.1.49.2, CUDA13.
  • After: source v0.2.6 (4b9e05a2a806a3fe24f7b2560d98626c37dade35); official DeepSeek engine 0.1.51, declared build source 562a0c2ed7169ff6373f893b162106d55a828297, CUDA13.

Graphics card, memory and system

  • 2 x NVIDIA GeForce RTX 3090, 24 GiB VRAM each.
  • 64 GB-class installed RAM; approximately 62.7 GiB usable MemTotal.
  • AMD Ryzen 7 5700X, Ubuntu 24.04.5 LTS, x86_64.
  • NVIDIA driver 595.91.07 at reporting time; the old run did not separately record driver metadata.
  • A read-only CUDA driver query returned CU_DEVICE_ATTRIBUTE_INTEGRATED = 0 for both cards.

Model, size and settings

  • DeepSeek-V4.1-Flash-1017 GSQ-RCO, ISTA-DASLab IQ2_XXS / IST-DAS-2.00bpw set; same prepared model weights, not requantized.
  • Context: 262144 in both comparisons; text-only requests, no image inputs.
  • Sequential streaming workload, thinking off, temperature 0, top_p 1, seed 11. Initial long answers had a 256-token output allowance; follow-ups had 128. Short probe/side requests had 32.
  • Same frozen initial public-document A/B prompts, with 245754 / 245784 input tokens in each version. Continuations used each run's actual assistant answers. The independent approximately 27K-token side prompt differed slightly between the two runs.
  • 15 requests per version: two long conversations, continued turns, a short probe and an independent side conversation. This was a local cache-validation workload, not a standard strata bench run protocol submission.

Logs

Only the relevant numeric startup lines are included; no original log files, prompts, local paths, device identifiers or deployment metadata are attached.

0.1.49.2:

ds4: RAM store: up to 4672 slots of 10.3 MB (48.0 GB), policy 0, 8 reader threads, unbuffered reads
ds4: RAM store: 4416 of the profile's hottest experts read in (34.3 GB) in 10.0 s
ds4: 11152 routed experts on the CPU lane (96.1 GB, in place in the model's files), 8 threads

0.1.51:

ds4: RAM store: 56.9 GB of RAM free after the GPU's weights: store sized 17.9 GB, not 51.1
ds4: RAM store: up to 1737 slots of 10.3 MB (17.8 GB), policy 0, 8 reader threads, unbuffered reads
ds4: RAM store: 1481 of the profile's hottest experts read in (11.5 GB) in 3.3 s
ds4: 11150 routed experts on the CPU lane (96.1 GB, in place in the model's files), 8 threads

The store GB figures are slot-capacity ceilings, not measured RSS. The preload counts are useful evidence, but the printed preload GB values use an estimate based on the first layer's blob size; they are not exact unique quantized payload measurements for a mixed-format pack.

Suspected sizing mechanism

The installed build's post-upload RAM-sizing rule infers UMA from the drop in available RAM rather than the actual integrated-GPU attribute:

const bool uma = avail0_ != ~uint64_t{0} && avail0_ > avail && (double) (avail0_ - avail) / 1e9 >= 4.0;
const double ctx_gb = uma ? 1.1e-4 * std::max(0.0, (double) o.max_context - 16384.0) : 0.0;
const double room = (double) avail / 1e9 - 12.0 - ctx_gb;

At context 262144, the extra reserve is 27.0336 decimal GB. The recorded values match that branch:

  • Initial automatic target 51.1 GB implies roughly 63.1 GB available under the initial available - 12 rule.
  • After GPU-weight loading, the log says 56.9 GB available: an inferred drop of about 6.2 GB, exceeding the 4 GB threshold.
  • 56.9 - 12 - 27.0336 = 17.8664 GB, matching the logged 17.9 GB target before slot rounding.
  • Without that UMA-specific extra reserve, the same arithmetic gives about 44.9 GB, not a requirement to use the whole RAM pool.

This appears to apply the UMA-specific reservation to a machine whose two CUDA devices both report integrated = 0. Could this check use the actual memory architecture, or otherwise avoid treating ordinary host-memory changes during discrete-GPU loading as a UMA signal?

Recorded performance impact and limits

Metric 0.1.49.2 0.1.51 Change
Cold prefill, weighted over the two long requests 438.1 tok/s 356.9 tok/s -18.5%
Decode, weighted over the 15 requests 10.15 tok/s 7.21 tok/s -29.0%
Cold first-content latency, median 561.53 s 689.22 s +22.7%
Switched-return first-content latency, median 2.66 s 4.23 s +59.0%

Prefill is newly read tokens / native prompt time, excluding reused tokens. Decode is generated tokens / native decode time, not generated tokens / whole-request time. First-content latency is measured at the streaming client.

Conversation KV reuse itself remained functional: both traces had 10/10 switched returns above 95% reuse, minimum approximately 99.985%, and 15/15 controlled identifier checks correct. The new run also restored long contexts after RAM-slot eviction and process restart. This does not measure expert-weight cache hit rate.

Important limitations:

  • These are historical measurements on the same hardware, not an interleaved, contemporaneous or engine-only A/B; the Python source server also changed versions.
  • Initial expert-profile contents, OS file-cache state, clocks/temperature and all background activity were not frozen as matched variables. The newer deployment also pinned physical-device selection explicitly and used a fresh versioned conversation-cache directory; matched physical GPU ordering was not established.
  • The two cold long prompts are identical, but the full continued trace is not asserted bit-identical and the side prompt differs slightly. This is one 15-request session per version, not three independent repeats.
  • The saved request histories have null expert hit-rate / RAM-file-byte fields; matched expert-store misses, waits and actual storage I/O were not captured. Missing measurements are not zeros.
  • No same-version explicit 42/44/48 GB store experiment, forced-copy experiment, or native-code fix has been tested. There is no claim that increasing the store alone will recover all of the speed difference.
All 15 per-request numeric observations (old / new; no prompts or private identifiers)
Case Input tokens old / new Reused old / new Generated old / new PP tok/s old / new Decode tok/s old / new First content s old / new
A-first 245754 / 245754 0 / 0 104 / 104 428.7 / 355.7 9.10 / 7.70 573.84 / 691.60
A-live 245894 / 245894 245857 / 245857 29 / 29 2.2 / 10.5 7.20 / 7.20 16.88 / 3.83
B-first 245784 / 245784 0 / 0 104 / 104 447.9 / 358.1 10.50 / 7.80 549.21 / 686.84
A-return-1 245959 / 245959 245922 / 245922 27 / 27 10.7 / 8.8 11.30 / 6.80 3.69 / 4.44
B-return-1 245924 / 245924 245887 / 245887 28 / 28 15.8 / 10.3 12.50 / 6.70 2.77 / 4.02
A-return-2 246022 / 246022 245985 / 245985 27 / 27 14.8 / 9.5 11.60 / 7.10 2.74 / 4.13
B-return-2 245988 / 245988 245951 / 245951 28 / 28 16.5 / 9.1 12.10 / 7.00 2.48 / 4.34
short-probe 16 / 16 0 / 0 3 / 3 8.4 / 6.5 14.80 / 12.50 1.90 / 2.47
A-after-probe-1 246085 / 246085 246048 / 246048 27 / 27 16.8 / 9.4 11.70 / 6.80 2.43 / 4.19
B-after-probe-1 246052 / 246052 246015 / 246015 26 / 26 16.8 / 9.9 11.70 / 6.90 2.44 / 3.99
A-after-probe-2 246148 / 246148 246111 / 246111 29 / 29 15.7 / 8.9 11.50 / 6.80 2.58 / 4.37
B-after-probe-2 246114 / 246114 246077 / 246077 28 / 28 16.5 / 9.4 11.70 / 6.90 2.49 / 4.18
subagent-27K 27607 / 27641 0 / 0 6 / 6 352.8 / 301.6 9.20 / 5.80 78.30 / 91.69
A-after-subagent 246213 / 246213 246176 / 246176 27 / 27 8.4 / 8.6 7.40 / 7.00 4.62 / 4.56
B-after-subagent 246178 / 246178 246141 / 246141 28 / 28 12.6 / 9.2 10.20 / 6.70 3.18 / 4.27

PP is the native rate for newly read prompt tokens. Very short continuations are not bulk-prefill measurements.

Related search found #3942, which concerns an older RAM-store limit on a different system; this report is specifically about the extra post-upload UMA reserve and the observed allocation reduction on discrete GPUs at 256K. No engine hang was observed in these measured requests.

Activity

  1. tha80 commented on Oct 25, 2026

    @tha80

    I am having exactly the same problem, but with just one RTX 3090 in my 64 GB system. My context size is also set to 262144 and with the old version I had about 45-50GB RAM usage and 9-12 token/s. With 0.1.51 I am seeing only about 20GB RAM usage and just 3-4 token/s.

  2. Burntgogi commented on Oct 27, 2026

    @Burntgogi
    Author

    Follow-up: 0.2.7 / DeepSeek 0.1.52 still shows the reduced automatic RAM store at 256K

    A separate local comparison of the official 0.2.7 CUDA13 package shows that the behavior reported above persists on this system. The comparison used the same installed model weights and an isolated 0.2.7 installation; no production configuration was changed.

    Setup

    • Two discrete NVIDIA RTX 3090 cards (24 GiB VRAM each), 64 GB-class system RAM, Linux x86_64, NVIDIA driver 595.91.07. The two cards previously reported cudaDevAttrIntegrated = 0.
    • DeepSeek-V4.1-Flash-1017, ISTA-DASLab GSQ-RCO IQ2_XXS / IST-DAS-2.00bpw. Configured context 262,144; two CUDA devices in a layer split. The requested --tp 2 resolves to one tensor-parallel group for this pack, with different layers on the two GPUs.
    • Old: Strata source 0.2.4.2 / DeepSeek engine 0.1.49.2. New: Strata source 0.2.7 / official DeepSeek engine 0.1.52. Both CUDA13. The released 0.2.7 engine is built from a42cc3d7df70.
    • Same native options, model files and a separate identical copy of the initial expert-profile seed. Automatic store sizing, expert count, prefill and DSpark settings were retained. No --ssd-cache, DS4_STORE_GB or forced expert-copy override was set. Each arm used a fresh process, private pack/profile and empty private conversation-cache directory.
    • Fixed workload: two distinct cold prompts of 245,754 and 245,784 input tokens, followed by four alternating conversation returns. Each return used the actual generated assistant history. The six request hashes, generated-answer hashes and input/output token counts were identical across the two runs. Temperature 0, top_p 1, seed 11; cold output cap 256, return cap 128.

    Observations

    Metric 0.2.4.2 / 0.1.49.2 0.2.7 / 0.1.52 Change
    Automatic expert RAM store slot-capacity ceiling 48.0 GB 15.4 GB -67.9%
    Startup hottest-expert preload, native log estimate 34.3 GB 11.6 GB —
    Cold prefill, weighted over both long prompts 454.1 tok/s 342.0 tok/s -24.7%
    Decode, weighted over all six requests 8.32 tok/s 7.04 tok/s -15.4%
    Cold time to first content, mean of two 541.8 s 719.1 s +32.7%
    Switched-return time to first content, mean of four 7.52 s 4.64 s -38.2%
    Switched-return KV prefix reuse 4/4; minimum 99.985% 4/4; minimum 99.985% unchanged
    Controlled identifier answers 6/6 6/6 unchanged

    Prefill is new prompt tokens divided by native prompt time, excluding reused tokens. Decode is generated tokens divided by native decode time, summed over the six requests. Time to first content is client-observed. The RAM store figures are slot-capacity ceilings, not RSS; the native preload GB figures are estimates, not exact unique quantized-payload sizes.

    Sanitized native startup lines from 0.1.52:

    ds4: RAM store: 54.4 GB of RAM free after the GPU's weights: store sized 15.4 GB, not 49.9
    ds4: RAM store: up to 1495 slots of 10.3 MB (15.4 GB), policy 0, 8 reader threads, unbuffered reads
    ds4: RAM store: 1495 of the profile's hottest experts read in (11.6 GB) in 3.3 s
    

    For comparison, the old run logged 4672 slots / 48.0 GB and 4416 preloaded profile entries / estimated 34.3 GB. There were no cgroup OOM events or process restarts. The old run's cgroup swap peak was about 685 MiB; the new run's was 0 MiB. This is a resource tradeoff, not proof that every old-run expert stayed resident in RAM.

    Sizing rule and requested review

    The 0.1.52 release build's post-upload sizing code still infers UMA from a decrease of at least 4 GB in host available RAM after loading GPU weights, and then reserves an additional amount proportional to context. At 262,144 tokens that reserve is approximately 27.03 decimal GB. This is consistent with the new startup numbers, although ordinary host-memory fluctuations can also cross that threshold on discrete GPUs.

    Could the automatic post-upload rule distinguish discrete GPUs from actual unified-memory devices, or otherwise avoid that extra UMA-specific reserve for a discrete-GPU system? The goal is a safe automatic sizing decision, not a request to overcommit the entire CPU expert lane.

    Limits

    • One fresh process per version; two cold prompts and four returns. This is not an interleaved or repeated statistical benchmark.
    • The new run preceded the old run. OS page-cache state, clocks, temperatures and background activity were not fully controlled. The Python source server and native engine changed together, so this is not an engine-only A/B.
    • There was no same-version store-size ablation. The smaller store and slower workload were observed together; the measurements do not establish that store sizing alone caused all of the speed difference.
    • 256K is the configured context; the actual cold inputs were approximately 240K tokens. The cache observations do not measure the expert-weight cache hit rate.
    • This is a follow-up to the earlier 0.2.6 / 0.1.51 observation in the original issue. Its approximately 17.8 GB figure came from that earlier run, not from the new two-arm comparison.
  3. Niko1221 commented on Oct 29, 2026

    @Niko1221
    Owner

    Found it. After the weights are on the GPU, the start decided whether the GPU shares the PC's RAM by one test: did the free RAM fall by 4 GB or more. On a discrete pair the pinned staging buffers and the page cache cause the same drop, so every 256K start took the Strix Halo context reserve (about 27 GB) off the store. Fixed on our side; the fix ships in the next update (0.2.8). The decision now also needs a device that reports itself as integrated (Strix Halo and the DGX Spark do; a discrete card never does).

    On two RTX A6000 at 256K: store sized 77.7 GB (6827 slots) before, 106.5 GB (9355 slots) after. If you can, send the RAM store: lines from the next engine.

  4. Niko1221 commented on Oct 29, 2026

    @Niko1221
    Owner

    Found and fixed in 0.2.8. The start took a drop in free RAM as proof that the GPU shares the PC's memory; on a discrete pair, pinned buffers cause the same drop. The decision now also needs a device that reports itself as integrated. On two RTX A6000 at 256K the RAM store went from 77.7 to 106.5 GB. Run strata update. Closing; reopen with the RAM store: lines if it still looks small.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions