<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mini-SGLang: LLM 서빙 프레임워크의 스케줄러 읽기 on Jaehun's Blog</title><link>https://jaehun.me/series/sgl-project--mini-sglang/</link><description>Recent content in Mini-SGLang: LLM 서빙 프레임워크의 스케줄러 읽기 on Jaehun's Blog</description><generator>Hugo</generator><language>ko-kr</language><atom:link href="https://jaehun.me/series/sgl-project--mini-sglang/index.xml" rel="self" type="application/rss+xml"/><item><title>1. 요청 하나가 지나는 프로세스와 경계</title><link>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-01/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0900</pubDate><guid>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-01/</guid><description>&lt;p&gt;LLM 서빙 프레임워크를 처음 열면 대개 스케줄러부터 찾는다. 하지만 스케줄러 코드를&#10;아무리 읽어도 &amp;ldquo;이 함수는 누가 부르고, 저 큐에는 누가 넣는가&amp;quot;가 풀리지 않는다.&#10;Mini-SGLang 은 한 프로세스짜리 프로그램이 아니기 때문이다. HTTP 요청 하나가&#10;답으로 돌아오기까지 최소 네 종류의 프로세스를 지나고, 그 사이는 전부 메시지로만&#10;이어져 있다.&lt;/p&gt;</description></item><item><title>2. Req와 Batch, 요청 하나의 상태 장부</title><link>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-02/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0900</pubDate><guid>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-02/</guid><description>&lt;p&gt;1편에서 스케줄러가 받은 것은 CPU 위의 1차원 int32 텐서였다. 그 토큰열이 답으로&#10;자라는 동안, 시스템은 &amp;ldquo;이 요청이 어디까지 갔는가&amp;quot;를 어딘가에 적어 두어야 한다.&#10;그 장부가 &lt;code&gt;Req&lt;/code&gt; 다.&lt;/p&gt;</description></item><item><title>3. prefill 배치를 짜는 예산과 chunked prefill</title><link>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-03/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0900</pubDate><guid>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-03/</guid><description>&lt;p&gt;2편에서 요청 하나는 세 길이로 표현되는 장부가 됐다. 이제 질문은 하나다. 대기 중인&#10;요청이 여럿일 때, 이번 스텝에 &lt;strong&gt;무엇을 얼마나&lt;/strong&gt; 넣을 것인가.&lt;/p&gt;&#10;&lt;p&gt;답은 예산 두 개와 조건 다섯 개다. 그리고 예산을 넘는 프롬프트를 어떻게 처리하는지에&#10;이 저장소의 깔끔한 선택이 하나 더 있다.&lt;/p&gt;</description></item><item><title>4. 페이지 할당과 raw location을 담는 page table</title><link>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-04/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0900</pubDate><guid>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-04/</guid><description>&lt;p&gt;3편에서 요청 하나가 &amp;ldquo;자리를 잡았다&amp;quot;고 했다. 그 자리의 정체가 이 편의 주제다.&lt;/p&gt;&#10;&lt;p&gt;KV cache 는 페이지 단위로 관리된다. 그런데 요청마다 하나씩 있는 &lt;code&gt;page_table&lt;/code&gt; 을&#10;열어 보면 페이지 번호가 아니라 &lt;strong&gt;토큰 하나하나의 위치&lt;/strong&gt;가 적혀 있다. 페이지로&#10;잡으면서 왜 표에는 토큰 위치를 적는가. 저장소가 그 답을 주석 한 줄로 적어 두었다.&lt;/p&gt;</description></item><item><title>5. 접두사를 재사용하는 radix cache와 eviction</title><link>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-05/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0900</pubDate><guid>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-05/</guid><description>&lt;p&gt;4편에서 요청 하나가 자기 자리를 잡는 법을 봤다. 그런데 같은 시스템 프롬프트로&#10;들어오는 요청 백 개가 각자 같은 계산을 반복하면 그 자리는 금방 동난다.&lt;/p&gt;&#10;&lt;p&gt;그래서 이미 계산한 접두사를 다시 쓴다. 다시 쓰기 시작하면 두 가지 질문이 새로&#10;생긴다. &lt;strong&gt;어디까지 같은가&lt;/strong&gt;를 어떻게 빠르게 찾는가, 그리고 공간이 모자랄 때&#10;&lt;strong&gt;무엇을 버려도 되는가&lt;/strong&gt;를 어떻게 아는가.&lt;/p&gt;</description></item><item><title>6. 두 스트림으로 CPU 스케줄링을 감추기</title><link>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-06/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0900</pubDate><guid>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-06/</guid><description>&lt;p&gt;지금까지 다섯 편에 걸쳐 스케줄러가 하는 일을 봤다. 메시지를 받고, 예산을 계산하고,&#10;트리를 걷고, 페이지를 잡고, 표를 채운다. 전부 &lt;strong&gt;CPU 일&lt;/strong&gt;이다.&lt;/p&gt;&#10;&lt;p&gt;그동안 GPU 는 무엇을 하고 있는가. 아무것도 안 하고 있다면, 모델을 아무리 빨리&#10;돌려도 그 사이사이가 비어 있다는 뜻이다. 이 편은 그 빈틈을 메우는 루프를 읽는다.&lt;/p&gt;</description></item><item><title>7. 장부가 커널 인자로 바뀌는 지점과 CUDA graph</title><link>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-07/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0900</pubDate><guid>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-07/</guid><description>&lt;p&gt;6편 마지막에 &lt;code&gt;_prepare_batch&lt;/code&gt; 의 일곱 줄을 열거하면서 마지막 두 줄을 남겨 뒀다.&#10;&lt;code&gt;pad_batch&lt;/code&gt; 와 &lt;code&gt;prepare_metadata&lt;/code&gt; 다. 이 편이 그 둘을 연다.&lt;/p&gt;&#10;&lt;p&gt;지금까지 세운 것은 전부 파이썬 객체였다. &lt;code&gt;Req&lt;/code&gt; 의 길이 세 개, 슬롯 번호, page&#10;table 의 한 행. 커널은 그런 것을 모른다. 커널이 받는 것은 텐서 몇 개다. 그 변환이&#10;어디서 어떻게 일어나는지, 그리고 CUDA graph 가 그 텐서들을 어떻게 고정하는지를&#10;본다.&lt;/p&gt;</description></item><item><title>8. 여러 rank가 같은 장부를 공유하는 법</title><link>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-08/</link><pubDate>Fri, 18 Sep 2026 00:00:00 +0900</pubDate><guid>https://jaehun.me/posts/code-series-sgl-project--mini-sglang-08/</guid><description>&lt;p&gt;1편에서 스케줄러가 TP 크기만큼 뜬다는 것을 보고, 그 뒤 여섯 편은 &lt;strong&gt;하나의&lt;/strong&gt;&#10;스케줄러 안에서 일어나는 일을 읽었다. 이제 그 전부를 rank 수만큼 복제한다.&lt;/p&gt;&#10;&lt;p&gt;여기서 문제가 생긴다. 스케줄러는 매 스텝 결정을 내린다. 어떤 요청을 배치에 넣을지,&#10;어느 페이지를 잡을지, 언제 무엇을 버릴지. rank 들이 각자 결정하는데 서로 다른 답에&#10;이르면 같은 모델을 쪼개 든 GPU 들이 다른 계산을 하게 된다. 어떻게 같은 답에&#10;도달하는가.&lt;/p&gt;</description></item></channel></rss>