Skip to content

[KV-offload][FS] : Batch store/load_block in C - #49152

Merged
DarkLight1337 merged 3 commits into
vllm-project:mainfrom
neuralmagic:varun/allioc
Jul 28, 2026
Merged

DarkLight1337 merged 3 commits into
vllm-project:mainfrom
neuralmagic:varun/allioc

Conversation

@varun-sundar-rabindranath

Copy link
Copy Markdown
Contributor

Purpose

We have pools of python threads to read and write KV files from/to disk. These python threads compete for the GIL and submit bursty read/write commands to the disk. This prevents the disk from reaching 100% utilization.

Changes:

  1. Add C implementations for store_block and load_block that does the heavy-lifting inside a GIL-free region. Note that we still use the python thread pool, the optimization is just that the work done by the threads is now GIL-free.
  2. Batching : This PR introduces a semantics change to thread work assignment.
  • On main : 1 request == 1 job == many keys == many reads/writes == each thread consumes a single read/write at a time.
  • This PR : 1 request == 1 job == many keys == many reads/writes == 1 thread does all the reads/writes.
    This 1 request to 1 thread mapping is likely detrimental at low concurrency. We can batch at the "keys" level and this I believe would be better to introduce in a followup PR and have this PR focus on the C implementation.

Performance

MODEL="openai/gpt-oss-120b"
TP_SIZE=2
CPU_BYTES=25769803776 # 25GB

    KV_TRANSFER_CONFIG=$(cat <<EOF
{
  "kv_connector": "OffloadingConnector",
  "kv_role": "kv_both",
  "kv_connector_extra_config": {
    "spec_name": "TieringOffloadingSpec",
    "cpu_bytes_to_use": ${CPU_BYTES},
    "eviction_policy": "lru",
    "secondary_tiers": [{
       "type": "fs",
       "root_dir": "/mnt/nvme-storage/",
       "n_read_threads": ${THREADS},
       "n_write_threads": ${THREADS}
    }]
  }
}
EOF
)
    vllm serve "${MODEL}" \
      --tensor-parallel-size="${TP_SIZE}" \
      --kv-transfer-config "${KV_TRANSFER_CONFIG}" \
      --gpu-memory-utilization 0.7 \
      --enable-prefix-caching \
      --no-disable-hybrid-kv-cache-manager \
      --disable-uvicorn-access-log \
      --port 8000 

guidellm bench command

BENCH_RATE="64"
BENCH_RATE_TYPE="concurrent"
BENCH_MAX_SECONDS="700"
BENCH_RANDOM_SEED="889"
BENCH_TURNS=5
BENCH_PROMPT_TOKENS="4096"
BENCH_OUTPUT_TOKENS="512"
BENCH_PREFIX_TOKENS="10000"
PREFIX_COUNT=$((4 * BENCH_RATE))
#PREFIX_COUNT=$BENCH_RATE

DATA="{\"kind\":\"synthetic_text\",\"prompt_tokens\":${BENCH_PROMPT_TOKENS},\"output_tokens\":${BENCH_OUTPUT_TOKENS},\"turns\":${BENCH_TURNS},\"prefix_buckets\": [{\"bucket_weight\": 100, \"prefix_count\": ${PREFIX_COUNT}, \"prefix_tokens\": ${BENCH_PREFIX_TOKENS}}]}"
    guidellm run \
      --backend "kind=openai_http,target=${TARGET_URL},request_format=/v1/completions" \
      --profile "kind=concurrent,streams=${BENCH_RATE}" \
      --constraint "kind=max_duration,seconds=${BENCH_MAX_SECONDS}" \
      --seed "kind=static,value=${BENCH_RANDOM_SEED}" \
      --data "$DATA" 

The benchmark and vllm serve is setup to load KV from disk as much as possible.

main

n_read_threads=4, n_write_threads=4

ℹ Server Throughput Statistics (All Requests)                                                                                      
|============|=======|======|=========|==============|===============|==============|                                              
| Benchmark  | Requests             ||| Input Tokens | Output Tokens | Total Tokens |                                              
| Strategy   | Concurrency || Per Sec | Per Sec      | Per Sec       | Per Sec      |                                              
|            | Mdn   | Mean | Mean                                               ||||                                              
|------------|-------|------|---------|--------------|---------------|--------------|                                              
| concurrent | 64.0  | 63.7 | 1.7     | 41330.8      | 903.2         | 42234.0      |                                              
|============|=======|======|=========|==============|===============|==============|  

n_read_threads=16, n_write_threads=16

ℹ Server Throughput Statistics (All Requests)
|============|=======|======|=========|==============|===============|==============|
| Benchmark  | Requests             ||| Input Tokens | Output Tokens | Total Tokens |
| Strategy   | Concurrency || Per Sec | Per Sec      | Per Sec       | Per Sec      |
|            | Mdn   | Mean | Mean                                               ||||
|------------|-------|------|---------|--------------|---------------|--------------|
| concurrent | 64.0  | 63.7 | 1.8     | 42917.0      | 949.8         | 43866.8      |
|============|=======|======|=========|==============|===============|==============|
Screenshot 2026-07-20 at 12 06 45 AM Screenshot 2026-07-20 at 12 06 58 AM Screenshot 2026-07-20 at 12 07 16 AM

PR

n_read_threads=4, n_write_threads=4

ℹ Server Throughput Statistics (All Requests)                                                                                      
|============|=======|======|=========|==============|===============|==============|                                              
| Benchmark  | Requests             ||| Input Tokens | Output Tokens | Total Tokens |                                              
| Strategy   | Concurrency || Per Sec | Per Sec      | Per Sec       | Per Sec      |                                              
|            | Mdn   | Mean | Mean                                               ||||                                              
|------------|-------|------|---------|--------------|---------------|--------------|                                              
| concurrent | 64.0  | 63.7 | 2.3     | 54333.4      | 1209.0        | 55542.3      |                                              
|============|=======|======|=========|==============|===============|==============|  

n_read_threads=16, n_write_threads=16

ℹ Server Throughput Statistics (All Requests)                                                                                      
|============|=======|======|=========|==============|===============|==============|
| Benchmark  | Requests             ||| Input Tokens | Output Tokens | Total Tokens |
| Strategy   | Concurrency || Per Sec | Per Sec      | Per Sec       | Per Sec      |
|            | Mdn   | Mean | Mean                                               ||||
|------------|-------|------|---------|--------------|---------------|--------------|
| concurrent | 64.0  | 63.7 | 2.3     | 53658.9      | 1181.1        | 54840.0      |
|============|=======|======|=========|==============|===============|==============|     
Screenshot 2026-07-19 at 2 29 58 PM Screenshot 2026-07-19 at 2 30 11 PM Screenshot 2026-07-19 at 2 30 28 PM

Things to note

    1. increased throughput
    1. Higher external tokens count
    1. Disk :
      • main - 4 threads throughput : 3 GB/s ; utilization : mostly <60%
      • main - 16 threads throughput : 3.8 GB/s; utilization : mostly <60%
      • PR - 4 threads throughput : 4.5 GB/s; utilization : around 80%
      • PR - 16 threads throughput : 4.5 GB/s; utilization : around 70%
        Note that the PR doesn't rely that much on the number of threads.

Test Plan

Compare lm-evals without and with offloading.

without offloading:

  vllm serve openai/gpt-oss-120b \
    --tensor-parallel-size=2 \
    --gpu-memory-utilization 0.7 \
    --enable-prefix-caching \
    --no-disable-hybrid-kv-cache-manager \
    --disable-uvicorn-access-log \
    --port 8000 

with offloading:

build_kv_transfer_config() {
  cat <<EOF
{
  "kv_connector": "OffloadingConnector",
  "kv_role": "kv_both",
  "kv_connector_extra_config": {
    "spec_name": "TieringOffloadingSpec",
    "cpu_bytes_to_use": 68719476736,
    "eviction_policy": "lru",
    "secondary_tiers": [{
       "type": "fs",
       "root_dir": "/mnt/nvme-storage/"
    }]
  }
}
EOF
}

  vllm serve openai/gpt-oss-120b \
    --tensor-parallel-size=2 \
    --gpu-memory-utilization 0.7 \
    --enable-prefix-caching \
    --no-disable-hybrid-kv-cache-manager \
    --disable-uvicorn-access-log \
    --port 8000 \
    --kv-transfer-config "$(build_kv_transfer_config)" 

lm-eval command:

  lm-eval \
    --model local-completions \
    --model_args "model=openai/gpt-oss-120b,base_url=http://127.0.0.1:8000/v1/completions,tokenized_requests=False,num_concurrent=1000,trust_remote_code=True,max_retries=10" \
    --tasks gsm8k \
    --seed 42 \
    --num_fewshot 25 \
    --gen_kwargs temperature=0.0 

Test Result

baseline: without offloading

|Tasks|Version|     Filter     |n-shot|  Metric   |   |Value |   |Stderr|
|-----|------:|----------------|-----:|-----------|---|-----:|---|-----:|
|gsm8k|      3|flexible-extract|    25|exact_match|↑  |0.4473|±  |0.0137|
|     |       |strict-match    |    25|exact_match|↑  |0.2767|±  |0.0123|

with offloading : run 1 - cold cache

|Tasks|Version|     Filter     |n-shot|  Metric   |   |Value |   |Stderr|

|-----|------:|----------------|-----:|-----------|---|-----:|---|-----:|
|gsm8k|      3|flexible-extract|    25|exact_match|↑  |0.4579|±  |0.0137|
|     |       |strict-match    |    25|exact_match|↑  |0.2889|±  |0.0125|

with offloading: run 2 - warm cache

|Tasks|Version|     Filter     |n-shot|  Metric   |   |Value |   |Stderr|
|-----|------:|----------------|-----:|-----------|---|-----:|---|-----:|
|gsm8k|      3|flexible-extract|    25|exact_match|↑  |0.4526|±  |0.0137|
|     |       |strict-match    |    25|exact_match|↑  |0.2835|±  |0.0124|

@claude claude 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.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@mergify mergify Bot added the v1 label Jul 20, 2026

@orozery orozery left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks @varun-sundar-rabindranath !
I see fs_io.cpp is growing significantly with this.
Can we somehow reduce/simplify?

This is what Claude suggested:

Remove the IOResult struct and safe_* wrappers (~70 lines)

These are an over-engineered error-reporting mechanism. The C functions could just return the index of the first failing operation (or -1 for success) and let Python reconstruct the exception from errno + the path at that index:

// Instead of IOResult + safe_open + safe_write + safe_close + safe_rename + safe_unlink...
static Py_ssize_t _store_block(const char* tmp_path, const char* dest_path,
                                const char* src, size_t size) {
    if (access(dest_path, F_OK) == 0) return 0;  // already exists

    int fd = open(tmp_path, O_CREAT | O_EXCL | O_WRONLY | kODirectFlag, 0644);
    if (fd < 0) return -1;

    ssize_t w = write(fd, src, size);
    close(fd);

    if (w < 0 || (size_t)w != size) { unlink(tmp_path); return -1; }
    if (rename(tmp_path, dest_path) != 0) { unlink(tmp_path); return -1; }
    return 0;
}

Then in the Python entry point: return the failing index, and Python raises using the path from its list + errno.

Comment thread vllm/v1/kv_offload/tiering/fs/io.py Outdated
@varun-sundar-rabindranath

Copy link
Copy Markdown
Contributor Author

Thanks for the review @orozery .

Not having the safe* functions and IOResult, made the store_block and load_block harder to read, as I had to track a lot of errno for the operations between actual work and cleanup. I agree that the file is big. I'll take another shot at it.

@varun-sundar-rabindranath

Copy link
Copy Markdown
Contributor Author

Hi @orozery

I could shave off ~70 lines from fs_io.cpp. I believe the PR is ready for another round of review. PTAL ! Thanks 🙌

@orozery orozery added the ready ONLY add when PR is ready to merge/full CI is needed label Jul 22, 2026

@orozery orozery left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@mergify

mergify Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @varun-sundar-rabindranath.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify

mergify Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Hi @varun-sundar-rabindranath, the pre-commit checks have failed. Please run:

uv pip install pre-commit>=4.5.1
pre-commit install
pre-commit run --all-files

Then, commit the changes and push to your branch.

For future commits, pre-commit will run automatically on changed files before each commit.

@mergify

mergify Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Hi @varun-sundar-rabindranath, the pre-commit checks have failed. Please run:

uv pip install pre-commit>=4.5.1
pre-commit install
pre-commit run --all-files

Then, commit the changes and push to your branch.

For future commits, pre-commit will run automatically on changed files before each commit.

Varun Sundar Rabindranath added 3 commits July 27, 2026 15:29
Signed-off-by: Varun Sundar Rabindranath <varun-sundar-rabindranath@h100-01.nemg-001.lab.rdu2.dc.redhat.com>

Signed-off-by:  <>
Signed-off-by: Varun Sundar Rabindranath <varun-sundar-rabindranath@h100-01.nemg-001.lab.rdu2.dc.redhat.com>

Signed-off-by:  <>
Signed-off-by: Varun Sundar Rabindranath <varun-sundar-rabindranath@h100-01.nemg-001.lab.rdu2.dc.redhat.com>

Signed-off-by:  <>
RobbieJ added a commit to RobbieJ/vllm that referenced this pull request Aug 8, 2026
…s a miss

A failed secondary-tier load livelocks the requesting request (vllm-project#49176): the
async lookup cache records a positive verdict per key and nothing corrects it
on load failure, so the scheduler re-issues the same doomed promotion every
step until the request is aborted.

- On a failed load the owning tier marks the cached lookup verdict as a miss
  (mark_miss), from get_finished_jobs on the scheduler thread. A cached miss is
  returned on subsequent lookups without re-probing, so the request recomputes
  on the GPU and never retries it, which structurally cannot loop. The tier
  already learns of its own failed loads, so no new SecondaryTierManager API is
  needed. A key is enqueued for probing exactly once, so drain_results asserts
  that invariant, keeping a late or duplicate result from resurrecting a
  corrected verdict.

- Loads are batched. The C loader reports how many blocks were read before the
  first failure, so the tier fills JobResult.successful_keys (vllm-project#50321) and marks
  only the failed block onward as a miss. The manager keeps the blocks that did
  load in the primary tier, so they stay a hit; only the failed tail is
  recomputed, and the miss clears when the request finishes.

- load_block removes the block file only on a provable short read, in both the
  C (_load_block) and Python paths. Stores are atomic, so a too-short existing
  file is genuine corruption; removing it makes future requests miss instead of
  repeating the failed load. Open failures and read errors leave the file
  untouched, and a harmless close after a full read no longer fails the load,
  so a transient host hiccup is not turned into permanent data loss or a
  spurious miss. This narrows the delete-on-any-error added in vllm-project#49152.

Lookup keeps upstream's access-based existence check.

Tests: per-tier livelock regressions, partial-batch keep (loaded blocks stay a
hit, only the failed tail misses), delete-on-short-read and
transient-leaves-file across the C and Python paths, and mark_miss unit tests
including the enqueue-once invariant. 345 tiering tests pass (356 with the
fs_io_C extension built).

Fixes vllm-project#49176

Signed-off-by: Robbie J <RobbieJ@users.noreply.github.com>
ningjingbengxiaohai pushed a commit to vllm-project/vllm-ascend that referenced this pull request Sep 8, 2026
### What this PR does / why we need it?
refer to: vllm-project/vllm#40020 ,
vllm-project/vllm#49152 ,
vllm-project/vllm#46713 and
vllm-project/vllm#49734 , add multi-tier KV
cache offloading framework, reusing the c operator from the upstream
vllm for batch loading, saving, and searching.

### How was this patch tested?

test reuslt:
|num-clients/max-active-conversations|base(without offload,
TTFT/TPOT)|with dram(TTFT/TPOT)|with dram+ssd(TTFT/TPOT)|
 | :---:|:---:|:---:|:---:|
 |8/24|1151.21/87.28|863.02/67.62|605.81/49.87|
 |16/48|7251.86/108.90|5679.01/83.75|3667.07/59.05|

model script:
```
export TP=1
export MODEL_PATH=/nas/disk1/Qwen3-14B
export MODEL_NAME=Qwen3-14B
export PORT=10113
#export CUDA_VISIBLE_DEVICES=3
export ASCEND_RT_VISIBLE_DEVICES=4

python3 -m vllm.entrypoints.openai.api_server  --host 0.0.0.0 --port ${PORT} --dtype bfloat16 --model ${MODEL_PATH} --served-model-name ${MODEL_NAME} --tensor-parallel-size ${TP} --gpu-memory-utilization 0.6  --no-enable-prefix-caching --max-model-len  32768 --trust-remote-code --kv-transfer-config '{
    "kv_connector": "OffloadingConnector",
    "kv_role": "kv_both",
    "kv_connector_extra_config": {
      "spec_name": "TieringOffloadingSpec",
      "cpu_bytes_to_use": 10737418240,
      "block_size": 128,
      "eviction_policy": "lru",
      "secondary_tiers": [
        {
          "type": "fs",
          "root_dir": "/mnt/kv_cache4",
          "n_read_threads": 32,
          "n_write_threads": 16
        }
      ]
    }
  }'
```
test script:
```
export MODEL_NAME=/nas/disk1/Qwen3-14B
python /model/vllm/benchmarks/multi_turn/benchmark_serving_multi_turn.py --url http://127.0.0.1:10113 --model $MODEL_NAME --served-model-name Qwen3-14B --seed 1234 --input-file /model/vllm/benchmarks/multi_turn/generate_multi_turn2.json \
--num-clients 8 --max-active-conversations 24
```
generate_multi_turn2.json
```
{
    "filetype": "generate_conversations",
    "num_conversations": 96,
    "text_files": ["pg1184.txt"],
    "print_stats": false,
    "prompt_input": {
        "num_turns": {
            "distribution": "uniform",
            "min": 12,
            "max": 18
        },
        "common_prefix_num_tokens": {
            "distribution": "constant",
            "value": 2000
        },
        "prefix_num_tokens": {
            "distribution": "lognormal",
            "average": 2000,
            "max": 10000
        },
        "num_tokens": {
            "distribution": "uniform",
            "min": 240,
            "max": 320
        }
    },
    "prompt_output": {
        "num_tokens": {
            "distribution": "uniform",
            "min": 80,
            "max": 120
        }
    }
}
```


- vLLM main:
vllm-project/vllm@e6bfe03

---------

Signed-off-by: HF-001 <1670186653@qq.com>
jiangli221 pushed a commit to jiangli221/vllm-ascend that referenced this pull request Sep 9, 2026
…10575)

### What this PR does / why we need it?
refer to: vllm-project/vllm#40020 ,
vllm-project/vllm#49152 ,
vllm-project/vllm#46713 and
vllm-project/vllm#49734 , add multi-tier KV
cache offloading framework, reusing the c operator from the upstream
vllm for batch loading, saving, and searching.

### How was this patch tested?

test reuslt:
|num-clients/max-active-conversations|base(without offload,
TTFT/TPOT)|with dram(TTFT/TPOT)|with dram+ssd(TTFT/TPOT)|
 | :---:|:---:|:---:|:---:|
 |8/24|1151.21/87.28|863.02/67.62|605.81/49.87|
 |16/48|7251.86/108.90|5679.01/83.75|3667.07/59.05|

model script:
```
export TP=1
export MODEL_PATH=/nas/disk1/Qwen3-14B
export MODEL_NAME=Qwen3-14B
export PORT=10113
#export CUDA_VISIBLE_DEVICES=3
export ASCEND_RT_VISIBLE_DEVICES=4

python3 -m vllm.entrypoints.openai.api_server  --host 0.0.0.0 --port ${PORT} --dtype bfloat16 --model ${MODEL_PATH} --served-model-name ${MODEL_NAME} --tensor-parallel-size ${TP} --gpu-memory-utilization 0.6  --no-enable-prefix-caching --max-model-len  32768 --trust-remote-code --kv-transfer-config '{
    "kv_connector": "OffloadingConnector",
    "kv_role": "kv_both",
    "kv_connector_extra_config": {
      "spec_name": "TieringOffloadingSpec",
      "cpu_bytes_to_use": 10737418240,
      "block_size": 128,
      "eviction_policy": "lru",
      "secondary_tiers": [
        {
          "type": "fs",
          "root_dir": "/mnt/kv_cache4",
          "n_read_threads": 32,
          "n_write_threads": 16
        }
      ]
    }
  }'
```
test script:
```
export MODEL_NAME=/nas/disk1/Qwen3-14B
python /model/vllm/benchmarks/multi_turn/benchmark_serving_multi_turn.py --url http://127.0.0.1:10113 --model $MODEL_NAME --served-model-name Qwen3-14B --seed 1234 --input-file /model/vllm/benchmarks/multi_turn/generate_multi_turn2.json \
--num-clients 8 --max-active-conversations 24
```
generate_multi_turn2.json
```
{
    "filetype": "generate_conversations",
    "num_conversations": 96,
    "text_files": ["pg1184.txt"],
    "print_stats": false,
    "prompt_input": {
        "num_turns": {
            "distribution": "uniform",
            "min": 12,
            "max": 18
        },
        "common_prefix_num_tokens": {
            "distribution": "constant",
            "value": 2000
        },
        "prefix_num_tokens": {
            "distribution": "lognormal",
            "average": 2000,
            "max": 10000
        },
        "num_tokens": {
            "distribution": "uniform",
            "min": 240,
            "max": 320
        }
    },
    "prompt_output": {
        "num_tokens": {
            "distribution": "uniform",
            "min": 80,
            "max": 120
        }
    }
}
```


- vLLM main:
vllm-project/vllm@e6bfe03

---------

Signed-off-by: HF-001 <1670186653@qq.com>
sunny-rain-63 pushed a commit to sunny-rain-63/vllm-ascend that referenced this pull request Sep 12, 2026
…10575)

### What this PR does / why we need it?
refer to: vllm-project/vllm#40020 ,
vllm-project/vllm#49152 ,
vllm-project/vllm#46713 and
vllm-project/vllm#49734 , add multi-tier KV
cache offloading framework, reusing the c operator from the upstream
vllm for batch loading, saving, and searching.

### How was this patch tested?

test reuslt:
|num-clients/max-active-conversations|base(without offload,
TTFT/TPOT)|with dram(TTFT/TPOT)|with dram+ssd(TTFT/TPOT)|
 | :---:|:---:|:---:|:---:|
 |8/24|1151.21/87.28|863.02/67.62|605.81/49.87|
 |16/48|7251.86/108.90|5679.01/83.75|3667.07/59.05|

model script:
```
export TP=1
export MODEL_PATH=/nas/disk1/Qwen3-14B
export MODEL_NAME=Qwen3-14B
export PORT=10113
#export CUDA_VISIBLE_DEVICES=3
export ASCEND_RT_VISIBLE_DEVICES=4

python3 -m vllm.entrypoints.openai.api_server  --host 0.0.0.0 --port ${PORT} --dtype bfloat16 --model ${MODEL_PATH} --served-model-name ${MODEL_NAME} --tensor-parallel-size ${TP} --gpu-memory-utilization 0.6  --no-enable-prefix-caching --max-model-len  32768 --trust-remote-code --kv-transfer-config '{
    "kv_connector": "OffloadingConnector",
    "kv_role": "kv_both",
    "kv_connector_extra_config": {
      "spec_name": "TieringOffloadingSpec",
      "cpu_bytes_to_use": 10737418240,
      "block_size": 128,
      "eviction_policy": "lru",
      "secondary_tiers": [
        {
          "type": "fs",
          "root_dir": "/mnt/kv_cache4",
          "n_read_threads": 32,
          "n_write_threads": 16
        }
      ]
    }
  }'
```
test script:
```
export MODEL_NAME=/nas/disk1/Qwen3-14B
python /model/vllm/benchmarks/multi_turn/benchmark_serving_multi_turn.py --url http://127.0.0.1:10113 --model $MODEL_NAME --served-model-name Qwen3-14B --seed 1234 --input-file /model/vllm/benchmarks/multi_turn/generate_multi_turn2.json \
--num-clients 8 --max-active-conversations 24
```
generate_multi_turn2.json
```
{
    "filetype": "generate_conversations",
    "num_conversations": 96,
    "text_files": ["pg1184.txt"],
    "print_stats": false,
    "prompt_input": {
        "num_turns": {
            "distribution": "uniform",
            "min": 12,
            "max": 18
        },
        "common_prefix_num_tokens": {
            "distribution": "constant",
            "value": 2000
        },
        "prefix_num_tokens": {
            "distribution": "lognormal",
            "average": 2000,
            "max": 10000
        },
        "num_tokens": {
            "distribution": "uniform",
            "min": 240,
            "max": 320
        }
    },
    "prompt_output": {
        "num_tokens": {
            "distribution": "uniform",
            "min": 80,
            "max": 120
        }
    }
}
```


- vLLM main:
vllm-project/vllm@e6bfe03

---------

Signed-off-by: HF-001 <1670186653@qq.com>
like-0517 pushed a commit to like-0517/vllm-ascend that referenced this pull request Sep 15, 2026
…10575)

### What this PR does / why we need it?
refer to: vllm-project/vllm#40020 ,
vllm-project/vllm#49152 ,
vllm-project/vllm#46713 and
vllm-project/vllm#49734 , add multi-tier KV
cache offloading framework, reusing the c operator from the upstream
vllm for batch loading, saving, and searching.

### How was this patch tested?

test reuslt:
|num-clients/max-active-conversations|base(without offload,
TTFT/TPOT)|with dram(TTFT/TPOT)|with dram+ssd(TTFT/TPOT)|
 | :---:|:---:|:---:|:---:|
 |8/24|1151.21/87.28|863.02/67.62|605.81/49.87|
 |16/48|7251.86/108.90|5679.01/83.75|3667.07/59.05|

model script:
```
export TP=1
export MODEL_PATH=/nas/disk1/Qwen3-14B
export MODEL_NAME=Qwen3-14B
export PORT=10113
#export CUDA_VISIBLE_DEVICES=3
export ASCEND_RT_VISIBLE_DEVICES=4

python3 -m vllm.entrypoints.openai.api_server  --host 0.0.0.0 --port ${PORT} --dtype bfloat16 --model ${MODEL_PATH} --served-model-name ${MODEL_NAME} --tensor-parallel-size ${TP} --gpu-memory-utilization 0.6  --no-enable-prefix-caching --max-model-len  32768 --trust-remote-code --kv-transfer-config '{
    "kv_connector": "OffloadingConnector",
    "kv_role": "kv_both",
    "kv_connector_extra_config": {
      "spec_name": "TieringOffloadingSpec",
      "cpu_bytes_to_use": 10737418240,
      "block_size": 128,
      "eviction_policy": "lru",
      "secondary_tiers": [
        {
          "type": "fs",
          "root_dir": "/mnt/kv_cache4",
          "n_read_threads": 32,
          "n_write_threads": 16
        }
      ]
    }
  }'
```
test script:
```
export MODEL_NAME=/nas/disk1/Qwen3-14B
python /model/vllm/benchmarks/multi_turn/benchmark_serving_multi_turn.py --url http://127.0.0.1:10113 --model $MODEL_NAME --served-model-name Qwen3-14B --seed 1234 --input-file /model/vllm/benchmarks/multi_turn/generate_multi_turn2.json \
--num-clients 8 --max-active-conversations 24
```
generate_multi_turn2.json
```
{
    "filetype": "generate_conversations",
    "num_conversations": 96,
    "text_files": ["pg1184.txt"],
    "print_stats": false,
    "prompt_input": {
        "num_turns": {
            "distribution": "uniform",
            "min": 12,
            "max": 18
        },
        "common_prefix_num_tokens": {
            "distribution": "constant",
            "value": 2000
        },
        "prefix_num_tokens": {
            "distribution": "lognormal",
            "average": 2000,
            "max": 10000
        },
        "num_tokens": {
            "distribution": "uniform",
            "min": 240,
            "max": 320
        }
    },
    "prompt_output": {
        "num_tokens": {
            "distribution": "uniform",
            "min": 80,
            "max": 120
        }
    }
}
```

- vLLM main:
vllm-project/vllm@e6bfe03

---------

Signed-off-by: HF-001 <1670186653@qq.com>
Signed-off-by: like-0517 <ithwlike@126.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready ONLY add when PR is ready to merge/full CI is needed v1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants