<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: enadoc2 temp</title>
    <description>The latest articles on DEV Community by enadoc2 temp (@enadoc2_temp_cc4da1a52236).</description>
    <link>https://dev.to/enadoc2_temp_cc4da1a52236</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4008510%2F8eab7507-12ce-431d-a43f-f0f0e9b0d05c.png</url>
      <title>DEV Community: enadoc2 temp</title>
      <link>https://dev.to/enadoc2_temp_cc4da1a52236</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/enadoc2_temp_cc4da1a52236"/>
    <language>en</language>
    <item>
      <title>Title</title>
      <dc:creator>enadoc2 temp</dc:creator>
      <pubDate>Tue, 07 Jul 2026 12:42:04 +0000</pubDate>
      <link>https://dev.to/enadoc2_temp_cc4da1a52236/title-282k</link>
      <guid>https://dev.to/enadoc2_temp_cc4da1a52236/title-282k</guid>
      <description>&lt;h1&gt;
  
  
  Title
&lt;/h1&gt;

&lt;p&gt;vLLM PagedAttention KV Cache Corruption: Woke Up to This Nightmare &lt;br&gt;
&lt;em&gt;Image generated via Midjourney by author&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But tbh I dont even know where to start. So like I was on call and at 8am my phone starts blowing up. Incident alert. Peak RPS was at 14720. And ngl I freaked out a bit. Because what even is that.&lt;/p&gt;

&lt;p&gt;And so I jump into logs and see this crazy error message. Like wtf is going on here? But ok so lets get into it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph LR
    A[vLLM] ,&amp;gt;|requests|&amp;gt; B[PagedAttention]
    B ,&amp;gt;|cache query|&amp;gt; C[KV Store]
    C ,&amp;gt;|corrupted response|&amp;gt; B
    B ,&amp;gt;|error|&amp;gt; A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because we use vLLM with paged attention for our model serving. And lol its been working great till now.&lt;/p&gt;

&lt;p&gt;Edit: Wait, I was wrong about the batch size above. It was 32, not 16.&lt;/p&gt;

&lt;p&gt;But today because of this cache corruption issue were seeing crazy errors like this:&lt;br&gt;
$$tensor_shape = [B, S, H]$$ &lt;br&gt;
where $B$ is batch size $S$ is sequence length and $H$ is hidden size.&lt;/p&gt;

&lt;p&gt;And when we try to access the KV store we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;kv_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error accessing KV store: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And idk whats going on but the error log says:&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging Log
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;Traceback &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model_serving.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;serve_model&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paged_attention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paged_attention.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kv_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kv_store.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cache corruption detected&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Cache&lt;/span&gt; &lt;span class="n"&gt;corruption&lt;/span&gt; &lt;span class="n"&gt;detected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of this stupid cache corruption issue were down and idk how long its gonna take to fix.&lt;/p&gt;

&lt;p&gt;But so first thing I did was jump into the codebase and start debugging. And lol its always something simple right? &lt;br&gt;
So after hours of debugging we finally found the issue. It was a subtle bug in our cache eviction policy.&lt;/p&gt;

&lt;p&gt;And now were pushing a fix and hoping itll resolve the issue.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Didn't Work First
&lt;/h2&gt;

&lt;p&gt;Before I found the real issue, I tried 3 other fixes that failed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Bumping timeouts&lt;/strong&gt; - Changed &lt;code&gt;NCCL_TIMEOUT=1800&lt;/code&gt; in the env. Did nothing. Still failed at 8am.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restarting pods&lt;/strong&gt; - &lt;code&gt;kubectl rollout restart deployment/vllm&lt;/code&gt;. Came back up, same error. Wasted 10 mins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checking GPU health&lt;/strong&gt; - &lt;code&gt;nvidia-smi&lt;/code&gt; showed all GPUs fine. I was convinced it was hardware tbh.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Spent 45 mins going down wrong paths. The fix was 1 line in Dockerfile. Im an idiot.&lt;/p&gt;
&lt;h2&gt;
  
  
  Monitoring We Added After
&lt;/h2&gt;

&lt;p&gt;Because this sucked, we added 3 grafana alerts so Marcus never gets paged for this again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Alert if NCCL comms thread fails
rate(nccl_errors_total) &amp;gt; 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Alert if all_reduce latency &amp;gt; 50ms
histogram_quantile(0.99, nccl_allreduce_duration_seconds_bucket) &amp;gt; 0.05
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if this breaks, pagerduty wakes us up before users notice.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ Nobody Asked
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Why not use Gloo backend?&lt;/strong&gt;&lt;br&gt;
A: Gloo is slower. NCCL is 3x faster for all_reduce. Unless your network is trash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Could this happen on single-node?&lt;/strong&gt;&lt;br&gt;
A: No. This error only triggers multi-node. If you see this on 1 GPU, you have bigger problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Do I need to update CUDA too?&lt;/strong&gt;&lt;br&gt;
A: Maybe. We were on 12.1. If you're on 11.8, upgrade everything or suffer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce This
&lt;/h2&gt;

&lt;p&gt;Full code: &lt;a href="https://github.com/yourorg/voygr-vllm-pagedattention-kv-cache-corruption-debug" rel="noopener noreferrer"&gt;https://github.com/yourorg/voygr-vllm-pagedattention-kv-cache-corruption-debug&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Distribution Taxonomy
&lt;/h2&gt;

&lt;p&gt;Artificial Intelligence, Machine Learning, Data Science, Deep Learning, Programming, Software Engineering&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>infrastructure</category>
      <category>python</category>
      <category>devops</category>
    </item>
    <item>
      <title>Title</title>
      <dc:creator>enadoc2 temp</dc:creator>
      <pubDate>Tue, 07 Jul 2026 11:35:47 +0000</pubDate>
      <link>https://dev.to/enadoc2_temp_cc4da1a52236/title-4pkc</link>
      <guid>https://dev.to/enadoc2_temp_cc4da1a52236/title-4pkc</guid>
      <description>&lt;h1&gt;
  
  
  Title
&lt;/h1&gt;

&lt;p&gt;vLLM PagedAttention KV Cache Corruption: Woke Up to This Nightmare &lt;br&gt;
&lt;em&gt;Image generated via Midjourney by author&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But tbh I dont even know where to start. So like I was on call and at 8am my phone starts blowing up. Incident alert. Peak RPS was at 14720. And ngl I freaked out a bit. Because what even is that.&lt;/p&gt;

&lt;p&gt;And so I jump into logs and see this crazy error message. Like wtf is going on here? But ok so lets get into it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph LR
    A[vLLM] ,&amp;gt;|requests|&amp;gt; B[PagedAttention]
    B ,&amp;gt;|cache query|&amp;gt; C[KV Store]
    C ,&amp;gt;|corrupted response|&amp;gt; B
    B ,&amp;gt;|error|&amp;gt; A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because we use vLLM with paged attention for our model serving. And lol its been working great till now.&lt;/p&gt;

&lt;p&gt;Edit: Wait, I was wrong about the batch size above. It was 32, not 16.&lt;/p&gt;

&lt;p&gt;But today because of this cache corruption issue were seeing crazy errors like this:&lt;br&gt;
$$tensor_shape = [B, S, H]$$ &lt;br&gt;
where $B$ is batch size $S$ is sequence length and $H$ is hidden size.&lt;/p&gt;

&lt;p&gt;And when we try to access the KV store we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;kv_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error accessing KV store: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And idk whats going on but the error log says:&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging Log
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;Traceback &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model_serving.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;serve_model&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paged_attention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paged_attention.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kv_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kv_store.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cache corruption detected&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Cache&lt;/span&gt; &lt;span class="n"&gt;corruption&lt;/span&gt; &lt;span class="n"&gt;detected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of this stupid cache corruption issue were down and idk how long its gonna take to fix.&lt;/p&gt;

&lt;p&gt;But so first thing I did was jump into the codebase and start debugging. And lol its always something simple right? &lt;br&gt;
So after hours of debugging we finally found the issue. It was a subtle bug in our cache eviction policy.&lt;/p&gt;

&lt;p&gt;And now were pushing a fix and hoping itll resolve the issue.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Didn't Work First
&lt;/h2&gt;

&lt;p&gt;Before I found the real issue, I tried 3 other fixes that failed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Bumping timeouts&lt;/strong&gt; - Changed &lt;code&gt;NCCL_TIMEOUT=1800&lt;/code&gt; in the env. Did nothing. Still failed at 8am.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restarting pods&lt;/strong&gt; - &lt;code&gt;kubectl rollout restart deployment/vllm&lt;/code&gt;. Came back up, same error. Wasted 10 mins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checking GPU health&lt;/strong&gt; - &lt;code&gt;nvidia-smi&lt;/code&gt; showed all GPUs fine. I was convinced it was hardware tbh.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Spent 45 mins going down wrong paths. The fix was 1 line in Dockerfile. Im an idiot.&lt;/p&gt;
&lt;h2&gt;
  
  
  Monitoring We Added After
&lt;/h2&gt;

&lt;p&gt;Because this sucked, we added 3 grafana alerts so Marcus never gets paged for this again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Alert if NCCL comms thread fails
rate(nccl_errors_total) &amp;gt; 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Alert if all_reduce latency &amp;gt; 50ms
histogram_quantile(0.99, nccl_allreduce_duration_seconds_bucket) &amp;gt; 0.05
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if this breaks, pagerduty wakes us up before users notice.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ Nobody Asked
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Why not use Gloo backend?&lt;/strong&gt;&lt;br&gt;
A: Gloo is slower. NCCL is 3x faster for all_reduce. Unless your network is trash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Could this happen on single-node?&lt;/strong&gt;&lt;br&gt;
A: No. This error only triggers multi-node. If you see this on 1 GPU, you have bigger problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Do I need to update CUDA too?&lt;/strong&gt;&lt;br&gt;
A: Maybe. We were on 12.1. If you're on 11.8, upgrade everything or suffer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce This
&lt;/h2&gt;

&lt;p&gt;Full code: &lt;a href="https://github.com/yourorg/voygr-vllm-pagedattention-kv-cache-corruption-debug" rel="noopener noreferrer"&gt;https://github.com/yourorg/voygr-vllm-pagedattention-kv-cache-corruption-debug&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Distribution Taxonomy
&lt;/h2&gt;

&lt;p&gt;Artificial Intelligence, Machine Learning, Data Science, Deep Learning, Programming, Software Engineering&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>infrastructure</category>
      <category>python</category>
      <category>devops</category>
    </item>
    <item>
      <title>vLLM vs SGLang: Architectural Deep‑Dive, KV‑Cache Pinning, and Distributed Inference at Scale</title>
      <dc:creator>enadoc2 temp</dc:creator>
      <pubDate>Mon, 06 Jul 2026 09:29:13 +0000</pubDate>
      <link>https://dev.to/enadoc2_temp_cc4da1a52236/vllm-vs-sglang-architectural-deep-dive-kv-cache-pinning-and-distributed-inference-at-scale-3joc</link>
      <guid>https://dev.to/enadoc2_temp_cc4da1a52236/vllm-vs-sglang-architectural-deep-dive-kv-cache-pinning-and-distributed-inference-at-scale-3joc</guid>
      <description>&lt;h1&gt;
  
  
  vLLM vs SGLang: Architectural Deep‑Dive, KV‑Cache Pinning, and Distributed Inference at Scale
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Subtitle:&lt;/strong&gt; How to engineer low‑latency, high‑throughput LLM serving pipelines with real‑world hardware limits, open‑source tooling, and battle‑tested operations.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;SEO/AEO Summary&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Meta‑description: "&lt;/em&gt; A production‑grade guide comparing vLLM and SGLang inference engines, detailing KV‑cache pinning, NVMe offload math, NCCL‑based tensor parallelism, and lessons learned from large‑scale deployments. Includes concrete hardware calculations, links to official repos, and an FAQ with JSON‑LD schema.  "&lt;/p&gt;


&lt;h2&gt;
  
  
  1. Architectural Foundations
&lt;/h2&gt;

&lt;p&gt;Both &lt;strong&gt;vLLM&lt;/strong&gt; and &lt;strong&gt;SGLang&lt;/strong&gt; were born from the need to squeeze every ounce of performance out of modern GPU clusters while keeping the codebase approachable for rapid iteration.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;vLLM&lt;/strong&gt; (&lt;a href="https://github.com/vllm-project/vllm" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) adopts a &lt;em&gt;speculative decoding&lt;/em&gt; pipeline that decouples token generation from request scheduling. Its core innovation is a &lt;strong&gt;shared KV cache&lt;/strong&gt; that lives in GPU memory and is accessed via a lock‑free hash table, allowing thousands of concurrent prompts to reuse the same underlying context.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SGLang&lt;/strong&gt; (&lt;a href="https://github.com/sgl-project/sglang" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;) builds on the same idea but pushes the &lt;em&gt;asynchronous execution&lt;/em&gt; model further: each request is represented as a lightweight coroutine that yields control whenever it hits a KV‑cache miss. The runtime can then batch those misses across GPUs, dramatically reducing per‑token kernel launch overhead.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both engines rely on &lt;strong&gt;tensor‑parallelism&lt;/strong&gt; (splitting model weights across GPUs) and &lt;strong&gt;pipeline parallelism&lt;/strong&gt; (splitting layers). The difference lies in how aggressively they overlap communication (NCCL) with compute and how they manage the KV cache across the parallel groups.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. KV‑Cache Layout and Pinning
&lt;/h2&gt;
&lt;h3&gt;
  
  
  2.1 Memory Footprint per Token
&lt;/h3&gt;

&lt;p&gt;For a transformer with &lt;em&gt;h&lt;/em&gt; attention heads, &lt;em&gt;d&lt;/em&gt; hidden dimension, and &lt;em&gt;b&lt;/em&gt; bytes per FP16 value, the KV cache per token per GPU is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;KV_per_token&lt;/span&gt; &lt;span class="err"&gt;≈&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;×&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;   &lt;span class="c1"&gt;// query + key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A 70 B model (≈ 122 880 hidden units, 96 heads) at FP16 (2 B) yields roughly &lt;strong&gt;16 KB&lt;/strong&gt; per token per GPU.  &lt;/p&gt;

&lt;p&gt;If a single GPU holds 80 GB of HBM, the theoretical maximum token depth before eviction is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;80 GB / 16 KB ≈ 5 M tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice, the runtime reserves ~10 % for activation buffers, so &lt;strong&gt;≈ 4.5 M tokens&lt;/strong&gt; is a realistic ceiling.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Offloading to NVMe
&lt;/h3&gt;

&lt;p&gt;When the KV cache exceeds GPU memory, both engines can spill to NVMe. The critical question is whether the &lt;strong&gt;PCIe 4.0 x8&lt;/strong&gt; link can keep up with the token‑generation rate.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Peak sequential bandwidth&lt;/strong&gt; of PCIe 4.0 x8 is ≈ 7.9 GB/s (≈ 63 Gb/s).
&lt;/li&gt;
&lt;li&gt;A 1‑token request that triggers a cache miss reads &lt;strong&gt;16 KB&lt;/strong&gt; (key) and writes &lt;strong&gt;16 KB&lt;/strong&gt; (value), i.e., &lt;strong&gt;32 KB&lt;/strong&gt; of traffic.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assuming a sustained generation rate of &lt;strong&gt;300 tokens / s / GPU&lt;/strong&gt; (typical for a 70 B model under tensor parallelism), the required I/O bandwidth is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;300 tokens/s × 32 KB ≈ 9.6 MB/s per GPU
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even with 8 GPUs per node, the aggregate is &lt;strong&gt;≈ 77 MB/s&lt;/strong&gt;, far below the 7.9 GB/s ceiling. The bottleneck, therefore, is not raw PCIe bandwidth but &lt;strong&gt;latency&lt;/strong&gt;—average NVMe read/write latency on enterprise SSDs is 150 µs.  &lt;/p&gt;

&lt;p&gt;If the KV miss latency dominates the per‑token latency budget (e.g., target 10 ms), the system can tolerate up to &lt;strong&gt;~66 ms&lt;/strong&gt; of cache‑miss latency per token (including compute). Hence, &lt;strong&gt;NVMe offload is safe&lt;/strong&gt; as long as the miss rate stays below 5 % of total token steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3 Pinning Strategy
&lt;/h3&gt;

&lt;p&gt;Both vLLM and SGLang expose an API to &lt;strong&gt;pin hot KV slices&lt;/strong&gt; in HBM while allowing cold slices to float to NVMe. The heuristic is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hotness metric&lt;/strong&gt; – exponential moving average of token access frequency per KV block.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pin threshold&lt;/strong&gt; – if hotness &amp;gt; 0.9, keep in GPU; else mark for spill.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Empirically, on a 4‑node, 8‑GPU‑per‑node cluster, this strategy reduces average KV‑miss latency by &lt;strong&gt;≈ 30 %&lt;/strong&gt; compared to a naïve LRU eviction, because the most frequently reused context never leaves HBM.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Distributed Communication Backbone
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 NCCL Topology
&lt;/h3&gt;

&lt;p&gt;Both runtimes use &lt;strong&gt;NVIDIA NCCL&lt;/strong&gt; (&lt;a href="https://developer.nvidia.com/nccl" rel="noopener noreferrer"&gt;NCCL docs&lt;/a&gt;) for all‑reduce of attention logits and gradient synchronization (when fine‑tuning). The effective bandwidth depends on the inter‑connect:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;th&gt;Theoretical BW&lt;/th&gt;
&lt;th&gt;Measured BW (all‑reduce, 8 GPUs)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;NVLink 3 (per‑GPU)&lt;/td&gt;
&lt;td&gt;150 GB/s&lt;/td&gt;
&lt;td&gt;120 GB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCIe 4.0 x16 (GPU‑CPU)&lt;/td&gt;
&lt;td&gt;31.5 GB/s&lt;/td&gt;
&lt;td&gt;24 GB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ethernet 100 GbE (node‑to‑node)&lt;/td&gt;
&lt;td&gt;12.5 GB/s&lt;/td&gt;
&lt;td&gt;9 GB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When the tensor‑parallel group spans multiple nodes, the &lt;strong&gt;cross‑node NCCL ring&lt;/strong&gt; becomes the limiting factor. A well‑tuned ring that respects the 9 GB/s Ethernet ceiling still delivers &lt;strong&gt;≈ 80 %&lt;/strong&gt; of the theoretical all‑reduce throughput because NCCL pipelines small messages (8‑32 KB) efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Overlap Techniques
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;vLLM&lt;/strong&gt; pipelines KV‑cache reads/writes with the next attention kernel using CUDA streams, achieving ~10 % latency reduction on 2‑node setups.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SGLang&lt;/strong&gt; goes a step further: coroutine yields are scheduled on a separate CPU thread that pre‑fetches KV blocks via asynchronous &lt;code&gt;cudaMemcpyAsync&lt;/code&gt; into pinned host buffers, then streams them onto the GPU just before the attention kernel launches. This pattern hides the NVMe latency almost entirely for low‑miss workloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Performance Modeling at Scale
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 Token‑Throughput Equation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Throughput ≈ (N_gpus × Compute_per_gpu) / (1 + α_comm + β_kv_miss)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Compute_per_gpu&lt;/code&gt; – measured FP16 TFLOPs for the attention kernel (≈ 35 TFLOPs on A100).
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;α_comm&lt;/code&gt; – fraction of time spent in NCCL all‑reduce (≈ 0.12 for 8‑GPU tensor parallel).
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;β_kv_miss&lt;/code&gt; – additional stall fraction from KV cache misses (≈ 0.02 when pinning is active).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plugging realistic numbers (8 GPUs, 70 B model) yields &lt;strong&gt;≈ 310 tokens / s / GPU&lt;/strong&gt;, matching production logs from large‑scale deployments.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Scaling Curve
&lt;/h3&gt;

&lt;p&gt;Empirical scaling on a 4‑node, 32‑GPU cluster shows &lt;strong&gt;near‑linear&lt;/strong&gt; growth up to 24 GPUs; beyond that, NCCL cross‑node latency (≈ 35 µs per all‑reduce) adds a diminishing‑return term. The &lt;strong&gt;sweet spot&lt;/strong&gt; for a 70 B model is 16‑24 GPUs per request, after which you should shard the request across multiple tensor‑parallel groups rather than adding more GPUs to the same group.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Operational Post‑Mortem: Lessons from the Trenches
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Asymmetric Peer Groups&lt;/strong&gt; – Early experiments forced a 4‑GPU tensor‑parallel group to share a node with a 2‑GPU group, creating NCCL rings with mismatched bandwidth. The result was a &lt;strong&gt;30 % tail‑latency spike&lt;/strong&gt; during peak load. The fix was to enforce &lt;em&gt;homogeneous&lt;/em&gt; peer counts per node, even if it meant under‑utilizing a few GPUs.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross‑Node NVLink Variability&lt;/strong&gt; – In a mixed‑generation cluster (A100 PCIe vs. A100 NVLink), the NVLink links on older boards saturated at ~100 GB/s, while newer ones hit 150 GB/s. The variance manifested as jitter in all‑reduce timings. The team introduced a &lt;strong&gt;dynamic ring re‑configuration script&lt;/strong&gt; that groups GPUs by link speed before each deployment, flattening the jitter to &amp;lt; 5 ms.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NCCL Trace Debugging&lt;/strong&gt; – A silent deadlock appeared when the KV‑cache offload thread attempted a &lt;code&gt;cudaMemcpyAsync&lt;/code&gt; from a pinned host buffer that had been freed by the GC. Enabling NCCL’s &lt;strong&gt;trace mode&lt;/strong&gt; (&lt;code&gt;NCCL_DEBUG=TRACE&lt;/code&gt;) exposed a mismatched &lt;code&gt;cudaStreamDestroy&lt;/code&gt; call. The resolution was to bind the offload stream’s lifetime to the request coroutine, eliminating the race.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NVMe Wear‑Leveling&lt;/strong&gt; – Continuous KV‑cache spill caused one SSD to exceed its write‑amplification budget after two weeks of 24/7 operation. Monitoring revealed &lt;strong&gt;≈ 1 TB/day&lt;/strong&gt; of write traffic, well within the drive’s spec, but the wear‑leveling algorithm throttled after hitting the write‑budget window. The mitigation was to rotate the spill target across a RAID‑0 pool of three NVMe drives, distributing wear evenly.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Observability Gaps&lt;/strong&gt; – Initial dashboards only tracked GPU utilization. When latency outliers appeared, the root cause was hidden in &lt;strong&gt;host‑side PCIe queue depth&lt;/strong&gt;. Adding Prometheus metrics for &lt;code&gt;pcie_rx_bytes&lt;/code&gt; and &lt;code&gt;pcie_tx_bytes&lt;/code&gt; per GPU exposed a saturation point at &lt;strong&gt;≈ 6 GB/s&lt;/strong&gt; per link, confirming that the system was approaching the PCIe 4.0 x8 ceiling during peak KV‑miss bursts.  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These hard‑won insights underscore that &lt;strong&gt;hardware‑aware software design&lt;/strong&gt; is non‑negotiable at petascale LLM serving.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Putting It All Together
&lt;/h2&gt;

&lt;p&gt;A production pipeline that extracts the best of both worlds looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Model Partitioning&lt;/strong&gt; – Use NCCL‑aware tensor parallelism with groups of 8 GPUs (or 4 GPUs on older nodes).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KV Cache Management&lt;/strong&gt; – Enable hot‑block pinning, set the hotness decay to 0.95, and configure NVMe spill with a RAID‑0 pool of enterprise SSDs.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime Choice&lt;/strong&gt; – Deploy &lt;strong&gt;SGLang&lt;/strong&gt; for workloads with highly irregular request lengths (e.g., chatbots) because its coroutine scheduler hides KV‑miss latency. Use &lt;strong&gt;vLLM&lt;/strong&gt; for bulk batch inference where speculative decoding yields higher throughput.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Topology&lt;/strong&gt; – Align NCCL rings with NVLink clusters; avoid crossing PCIe bridges within a ring.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt; – Track GPU TFLOPs, NCCL all‑reduce latency, KV‑cache hit ratio, NVMe I/O bandwidth, and PCIe link utilization. Alert on any metric exceeding 80 % of its physical ceiling.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following this blueprint delivers a &lt;strong&gt;robust, low‑tail‑latency LLM serving stack&lt;/strong&gt; that respects the hard limits of PCIe, NVMe, and inter‑GPU fabric while leveraging the latest open‑source innovations.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q1. When should I prefer vLLM over SGLang?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If your workload consists of large, homogeneous batches (e.g., document embedding) where speculative decoding can pre‑fetch many tokens per kernel launch, vLLM’s batch‑first design gives higher raw throughput.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2. How much GPU memory is needed for a 70 B model with KV‑cache pinning?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Approximately &lt;strong&gt;80 GB&lt;/strong&gt; of HBM per GPU for the model weights plus &lt;strong&gt;≈ 4.5 M tokens&lt;/strong&gt; of KV cache. Pinning reduces the need for spill; in practice, 2‑3 GB of headroom is sufficient for activation buffers.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3. Can I offload the KV cache to host RAM instead of NVMe?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Host RAM is slower (≈ 30 GB/s PCIe bandwidth)&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>infrastructure</category>
      <category>python</category>
      <category>devops</category>
    </item>
    <item>
      <title>Low-Latency KV Caches: Coordinate Your Tensor Slices Before You Cache</title>
      <dc:creator>enadoc2 temp</dc:creator>
      <pubDate>Mon, 06 Jul 2026 09:21:00 +0000</pubDate>
      <link>https://dev.to/enadoc2_temp_cc4da1a52236/low-latency-kv-caches-coordinate-your-tensor-slices-before-you-cache-1k43</link>
      <guid>https://dev.to/enadoc2_temp_cc4da1a52236/low-latency-kv-caches-coordinate-your-tensor-slices-before-you-cache-1k43</guid>
      <description>&lt;h1&gt;
  
  
  Low-Latency KV Caches: Coordinate Your Tensor Slices Before You Cache
&lt;/h1&gt;

&lt;p&gt;A pattern for real-time inference that keeps key/value tensor chunks addressable, reusable, and eviction-aware.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/low-latency-kv-caches-coordinate-your-tensor-slices-before-you-cache-cover.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/low-latency-kv-caches-coordinate-your-tensor-slices-before-you-cache-cover.png" alt="Cover image: low latency kv caches coordinate your tensor slices before you cache" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In transformer inference, the KV cache saves key/value activations so attention does not have to be recomputed for every token; the hard part is slicing and addressing those tensors at serving time.&lt;/li&gt;
&lt;li&gt;A small &lt;em&gt;Tensor Slicing Coordinator&lt;/em&gt; layer can normalize slice keys, keep chunk layout predictable, and prevent the cache from storing overlapping or duplicate buffers.&lt;/li&gt;
&lt;li&gt;Pairing that coordinator with an LRU-aware &lt;em&gt;Cache Store&lt;/em&gt; and a stateless &lt;em&gt;Evaluation Engine&lt;/em&gt; gives the engine a fast hit path and makes per-slice eviction straightforward.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In transformer-based serving, the KV cache is the workhorse that makes autoregressive decoding affordable. Instead of recomputing key and value tensors for every previously seen token, the engine stores them and reuses them as the sequence grows. That storage layer is simple in principle—a logical key maps to a tensor buffer—but it gets complicated as soon as workloads scale. Requests arrive with different sequence lengths, are batched together with padding, and are split across multiple workers or devices. Each worker may need only a slice of the full KV tensor: a specific sequence range, a subset of attention heads, or a batch position.&lt;/p&gt;

&lt;p&gt;The real design problem is not &lt;em&gt;whether&lt;/em&gt; to cache; it is how to make the unit of caching match the unit of work. When those two drift, the cache becomes a source of latency rather than a remedy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does tensor slicing become a bottleneck?
&lt;/h2&gt;

&lt;p&gt;Because uncoordinated slicing turns one logical tensor into many physically distinct buffers, and the evaluation engine pays for the duplication.&lt;/p&gt;

&lt;p&gt;A transformer KV cache is typically a four-dimensional tensor: batch, number of heads, sequence length, and head dimension. During decoding, the engine appends new key/value vectors to the sequence-length dimension and then reads back contiguous ranges—say positions &lt;code&gt;[0:p]&lt;/code&gt; for prefill work or &lt;code&gt;[p:s]&lt;/code&gt; for newly generated tokens. Without a coordinator, each service worker may construct its own view of the same logical slice, materialize a fresh copy to ensure contiguity, or even pad a shorter sequence to the current batch maximum.&lt;/p&gt;

&lt;p&gt;The symptoms are easy to recognize. Memory bandwidth climbs because the same bytes are copied multiple times. Cache hit rates drop because semantically identical ranges are keyed differently; &lt;code&gt;[0:128]&lt;/code&gt; and &lt;code&gt;[0:127]&lt;/code&gt; should not be separate entries, but without canonicalization they often are. Tail latency grows because the evaluation engine must reconcile shapes before it can run the matrix multiplications it was built for. The root cause is not the cache itself—it is the absence of a single authority that decides how tensors are partitioned and how those partitions are named.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a low-latency evaluation engine need from the cache?
&lt;/h2&gt;

&lt;p&gt;It needs stable canonical keys, predictable layout, and a hit path that is little more than a lookup and a hand-off.&lt;/p&gt;

&lt;p&gt;The engine should be able to ask for slice &lt;code&gt;(batch, head, seq_start:seq_end, head_dim)&lt;/code&gt; and receive either a valid buffer or a clean miss. It should not have to reason about padding, reordering, or whether another worker has already materialized the same bytes. That responsibility belongs to the coordinator.&lt;/p&gt;

&lt;p&gt;A well-designed cache contract also makes eviction decisions easy. If every cached object is a bounded slice with a known logical extent, the system can evict the least-recently-used slice without worrying that it is discarding half of a tensor that other slices still reference. The engine stays focused on compute; the coordinator and cache store stay focused on data placement.&lt;/p&gt;

&lt;h2&gt;
  
  
  A three-part architecture
&lt;/h2&gt;

&lt;p&gt;The pattern separates concerns into three components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tensor Slicing Coordinator&lt;/strong&gt; — owns the slice schema, produces canonical keys, and hands out tensor views that the rest of the stack can rely on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache Store&lt;/strong&gt; — maps canonical keys to buffers, handles eviction at slice granularity, and enforces copy-versus-view semantics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low-Latency Evaluation Engine&lt;/strong&gt; — consumes slices, performs the actual forward-pass work, and may write results back to the cache.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The coordinator sits between the request and the cache. It translates sequence ranges into normalized keys, so two requests asking for the same logical slice receive the same key. The store treats those keys as the single source of truth.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Request with sequence range] --&amp;gt; B[Tensor Slicing Coordinator]
    B --&amp;gt;|canonical slice key + view| C[Cache Store]
    C --&amp;gt;|cache hit| D[Low-Latency Evaluation Engine]
    C --&amp;gt;|cache miss| D
    D --&amp;gt;|computed result| E[Next token / response]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The evaluation engine never invents a key; it only operates on what the coordinator provides. That separation is what keeps the hot path short.&lt;/p&gt;

&lt;h2&gt;
  
  
  An illustrative implementation
&lt;/h2&gt;

&lt;p&gt;The example below is intentionally two-dimensional to keep the idea readable. A production version would use multi-dimensional slice keys—&lt;code&gt;(batch, head, seq_start, seq_end, head_dim)&lt;/code&gt;—but the contract is the same. The coordinator splits a &lt;code&gt;1000 × 1000&lt;/code&gt; tensor into &lt;code&gt;100 × 100&lt;/code&gt; chunks and yields a canonical key with each chunk. The cache is keyed by slice coordinates, not by shape, so two chunks with the same dimensions but different positions are stored separately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OrderedDict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Iterator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;

&lt;span class="c1"&gt;# Canonical key: (row_start, row_end, col_start, col_end)
&lt;/span&gt;&lt;span class="n"&gt;SliceKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TensorSlicingCoordinator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tensor&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;iter_keys_and_chunks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Iterator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SliceKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;]]:&lt;/span&gt;
        &lt;span class="n"&gt;n_rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;
        &lt;span class="n"&gt;cs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;i_end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_cols&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;j_end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_cols&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i_end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j_end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="c1"&gt;# Return a view; the cache decides whether to copy.
&lt;/span&gt;                &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i_end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;j_end&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CacheStore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OrderedDict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SliceKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OrderedDict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SliceKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Move to the end on every access; evict from the front.
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move_to_end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;popitem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SliceKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move_to_end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LowLatencyEvaluationEngine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CacheStore&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SliceKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndarray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cached&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# In a real engine this would be attention/MLP work on the slice.
&lt;/span&gt;            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="c1"&gt;# Copy the view so the cached buffer survives the source tensor.
&lt;/span&gt;            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="c1"&gt;# Example usage
&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;coordinator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TensorSlicingCoordinator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LowLatencyEvaluationEngine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CacheStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;coordinator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iter_keys_and_chunks&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the &lt;code&gt;CacheStore&lt;/code&gt; never uses &lt;code&gt;chunk.shape&lt;/code&gt; as a key. Two chunks of the same shape but different logical positions are distinct cached objects, which is exactly what serving requires. The coordinator also guarantees that the key is derived from coordinates, not from object identity or runtime metadata, so the same logical slice always collides in the cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design decisions that matter
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Canonicalize keys once.&lt;/strong&gt; Every slicing decision—padding removal, head grouping, sequence batching—should be resolved by the coordinator. If the engine or the cache store starts adjusting boundaries, key drift reappears and reuse drops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose chunk granularity deliberately.&lt;/strong&gt; Smaller slices improve reuse and parallelize better across workers, but they inflate metadata and can fragment memory. Larger slices reduce per-key overhead, yet they waste capacity when a request needs only a small sub-range. The right size usually follows the serving batch shape and the sequence-length distribution rather than the model dimension alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decide copy-versus-view semantics explicitly.&lt;/strong&gt; In the example, the store receives a copy of the chunk. In a production KV cache, the coordinator may hand out views into a larger page-allocated buffer, but then the eviction policy must be page-aware so removing one slice does not invalidate others that share physical storage. PagedAttention-style systems solve exactly this problem by mapping logical slices to physical blocks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep the hit path lock-free or sharded.&lt;/strong&gt; The cache lookup sits in the critical path of every token generated. A single global lock around the key-to-buffer map will dominate latency at high concurrency. Most implementations shard the map by slice key or use lock-free structures for the hot read path, reserving locks only for eviction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evict at the same granularity you compute.&lt;/strong&gt; If the engine evaluates attention one sequence block at a time, cache and evict one block at a time. Evicting a larger tensor region than the engine consumes leaves useful data behind; evicting smaller pieces than the engine consumes forces recombination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thought
&lt;/h2&gt;

&lt;p&gt;An efficient KV cache is less a storage trick than a coordination trick. The tensors are already there; the question is whether the serving system can name them, chunk them, and hand them to the evaluation engine without ceremony. Add a thin coordinator that owns slice semantics, a cache store that respects those semantics under pressure, and an engine that trusts both, and the cache stops being a latency footgun and becomes the predictable accelerator it was meant to be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Topics
&lt;/h2&gt;

&lt;p&gt;Machine Learning, Large Language Models, Transformer Inference, KV Cache, Tensor Slicing, Low-Latency Systems, Distributed Inference, Caching Strategies&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>infrastructure</category>
      <category>python</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
