<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>김신건의 로그 - 위키 / ml</title><description>&apos;ml&apos; 카테고리 위키 페이지 최신 업데이트</description><link>https://shinkeonkim.com/</link><language>ko-KR</language><item><title>분산 학습</title><link>https://shinkeonkim.com/wiki/ml/distributed-training/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/distributed-training/</guid><pubDate>Sat, 18 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;분산 학습 (Distributed Training)&lt;/strong&gt; 은 한 [[GPU]] 또는 [[TPU]] 에 들어가지 않는 큰 모델을 &lt;strong&gt;여러 가속기에 나눠서&lt;/strong&gt; 학습시키는 기법.&lt;/p&gt;
&lt;p&gt;현대 LLM (Llama 405B, GPT-4, Gemini Ultra 등) 은 &lt;strong&gt;수천 ~ 수만 개의 GPU 로 동시에 학습&lt;/strong&gt;된다. 한 GPU 가 메모리, 컴퓨트, 통신 등 어느 한 자원이 부족할 때 다양한 방식으로 분할한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;문제-상황과-동기&quot;&gt;문제 상황과 동기&lt;/h2&gt;
&lt;p&gt;단일 GPU 학습의 한계:&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;제약&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;설명&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;VRAM 한계&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;A100 80GB 기준, Llama 70B float16 = 140GB. 한 GPU 불가.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;컴퓨트 한계&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1조 token 학습에 A100 1대로 수십 년.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;통신 병목&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;대규모 batch 는 gradient 크기가 너무 커서 동기화 자체가 부담.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;이를 해결하기 위해 데이터, 레이어, 텐서, 시퀀스 차원을 각각 나눠 수천 개 GPU 를 동시에 활용한다.&lt;/p&gt;
&lt;h2 id=&quot;핵심-4가지-병렬화-전략&quot;&gt;핵심 4가지 병렬화 전략&lt;/h2&gt;
&lt;p&gt;대규모 모델 학습은 보통 &lt;strong&gt;4가지 (이상의) parallelism 을 조합&lt;/strong&gt;해서 사용한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    All[&quot;분산 학습 전략&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    All --&gt; DP[&quot;Data Parallelism (DP)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    All --&gt; TP[&quot;Tensor Parallelism (TP)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    All --&gt; PP[&quot;Pipeline Parallelism (PP)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    All --&gt; ZeRO[&quot;ZeRO / FSDP&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    All --&gt; CP[&quot;Context Parallelism (CP)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    All --&gt; EP[&quot;Expert Parallelism (EP)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    DP --&gt; DPnote[&quot;전체 모델 복제, 데이터만 분할&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    TP --&gt; TPnote[&quot;레이어 내 행렬 분할&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    PP --&gt; PPnote[&quot;레이어 단위 분할&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ZeRO --&gt; ZeROnote[&quot;Optimizer/Grad/Param sharding&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;1-data-parallelism-dp-가장-단순&quot;&gt;1. Data Parallelism (DP), 가장 단순&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 0: 전체 모델 + 데이터 batch 의 1/N&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 1: 전체 모델 + 데이터 batch 의 1/N&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU N: 전체 모델 + 데이터 batch 의 1/N&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;→ 각자 forward + backward&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;→ all-reduce 로 gradient 동기화&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;→ 같은 step 후 모델이 동일해짐&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;장점&lt;/strong&gt;: 구현 가장 단순 (PyTorch DDP 한 줄)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단점&lt;/strong&gt;: 각 GPU 에 전체 모델이 들어가야 함 (메모리 부족 시 사용 불가)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;통신&lt;/strong&gt;: 매 step backward 후 all-reduce (전체 모델 gradient 동기화)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-tensor-parallelism-tp-한-layer-를-쪼개기&quot;&gt;2. Tensor Parallelism (TP), 한 layer 를 쪼개기&lt;/h3&gt;
&lt;p&gt;큰 행렬 곱셈을 가로/세로로 분할.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Original: Y = X @ W  (W: [hidden, ff] = [4096, 16384])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Tensor Parallel (4-way):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  GPU 0: W_0 = W[:, 0:4096]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  GPU 1: W_1 = W[:, 4096:8192]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  GPU 2: W_2 = W[:, 8192:12288]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  GPU 3: W_3 = W[:, 12288:16384]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  각 GPU: Y_i = X @ W_i&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  결합: Y = concat([Y_0, Y_1, Y_2, Y_3])  # all-gather&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;장점&lt;/strong&gt;: 큰 layer 도 분할 가능&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단점&lt;/strong&gt;: forward 마다 통신 (all-reduce/all-gather) 필요, 노드 내 NVLink 같은 빠른 연결 필수&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;대표&lt;/strong&gt;: Megatron-LM 의 TP 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-pipeline-parallelism-pp-layer-를-분할&quot;&gt;3. Pipeline Parallelism (PP), layer 를 분할&lt;/h3&gt;
&lt;p&gt;모델의 layer 를 GPU 들에 수직 분배.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 0: Layer 1-10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 1: Layer 11-20&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 2: Layer 21-30&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 3: Layer 31-40&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;→ 입력 → GPU 0 → GPU 1 → GPU 2 → GPU 3 → 출력&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;순차적이라 idle 시간 발생. &lt;strong&gt;micro-batching&lt;/strong&gt; 으로 pipeline 채움 (GPipe, PipeDream).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;시간 →&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 0: [B1] [B2] [B3] [B4] [bw4][bw3][bw2][bw1]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 1:      [B1] [B2] [B3] [B4] [bw4][bw3][bw2][bw1]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 2:           [B1] [B2] [B3] [B4] [bw4][bw3][bw2][bw1]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 3:                [B1] [B2] [B3] [B4] [bw4][bw3][bw2][bw1]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;장점&lt;/strong&gt;: 통신 비용 작음 (인접 GPU 만), 매우 깊은 모델에 효과적&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단점&lt;/strong&gt;: bubble (idle 시간) 발생, 정확한 schedule 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-zero--fsdp-메모리-sharding&quot;&gt;4. ZeRO / FSDP, 메모리 sharding&lt;/h3&gt;
&lt;p&gt;Microsoft DeepSpeed 의 ZeRO (&lt;a href=&quot;https://arxiv.org/abs/1910.02054&quot;&gt;arXiv:1910.02054&lt;/a&gt;), PyTorch FSDP 가 대표.&lt;/p&gt;
&lt;p&gt;데이터 병렬의 메모리 비효율을 해결. 각 GPU 가 모델 일부만 저장.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Stage&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;shard 대상&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;메모리 절약&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;ZeRO-1&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Optimizer state&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;4x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;ZeRO-2&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;+ Gradient&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8x&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;ZeRO-3 (FSDP)&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;+ Parameter&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;N x&lt;/strong&gt; (GPU 수에 비례)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;ZeRO-3 / FSDP 동작:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;평소: parameter 도 shard 되어 있음&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;forward 시: 필요한 layer 의 parameter 를 all-gather 로 모음&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;backward 시: gradient 계산 후 reduce-scatter 로 다시 분산&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;장점&lt;/strong&gt;: Data Parallelism + 메모리 효율&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;단점&lt;/strong&gt;: gather/scatter 통신 비용 추가&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;5-context-parallelism-cp-시퀀스-차원-분할&quot;&gt;5. Context Parallelism (CP), 시퀀스 차원 분할&lt;/h2&gt;
&lt;p&gt;긴 컨텍스트 (32K, 100K+ token) 학습 시 시퀀스 자체를 GPU 에 분할.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 0: token 0~8K&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 1: token 8K~16K&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 2: token 16K~24K&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;GPU 3: token 24K~32K&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;→ attention 시 ring exchange 로 통신&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Google Gemini 1.5 Pro (1M context), Llama 3 (128K context) 학습에 사용.&lt;/p&gt;
&lt;h2 id=&quot;6-expert-parallelism-ep-moe-모델&quot;&gt;6. Expert Parallelism (EP), MoE 모델&lt;/h2&gt;
&lt;p&gt;Mixture of Experts (MoE) 모델에서 각 expert 를 다른 GPU 에 배치. 라우팅으로 활성 expert 만 통신.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mixtral 8x7B&lt;/li&gt;
&lt;li&gt;DeepSeek V3 (671B parameter, 활성 37B)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;조합-3d--4d--5d-parallelism&quot;&gt;조합: 3D / 4D / 5D Parallelism&lt;/h2&gt;
&lt;p&gt;대규모 학습은 보통 여러 차원을 조합:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Total GPUs = TP × PP × DP × CP × EP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;예: Llama 3.1 405B 학습 (16,000 H100):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  TP: 8 (노드 내, NVLink)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  PP: 16 (노드 간, InfiniBand)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  DP: 125 (전체 batch 분산)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Total: 8 × 16 × 125 = 16,000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;각 차원의 통신 패턴:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TP&lt;/strong&gt;: forward 마다 all-reduce/all-gather → &lt;strong&gt;고대역폭 필수&lt;/strong&gt; (NVLink)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PP&lt;/strong&gt;: layer 경계에서 1회 → &lt;strong&gt;저대역폭 OK&lt;/strong&gt; (InfiniBand)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DP&lt;/strong&gt;: backward 후 all-reduce → 중간 대역폭&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CP&lt;/strong&gt;: ring exchange → 노드 내 추천&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EP&lt;/strong&gt;: 라우팅 통신 → all-to-all&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;동기화-패턴-collective-communication&quot;&gt;동기화 패턴 (Collective Communication)&lt;/h2&gt;
&lt;p&gt;분산 학습의 핵심은 &lt;strong&gt;collective operation&lt;/strong&gt; 들.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;all-reduce:  [a,b,c,d] → 각 노드에 sum=a+b+c+d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;all-gather:  [a,b,c,d] → 각 노드에 [a,b,c,d]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;reduce-scatter: [a,b,c,d] → 각 노드에 일부 sum&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;broadcast:   [a,...,...,...] → [a,a,a,a]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;all-to-all:  matrix transpose 같은 전체 재분배&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이 연산들이 분산 학습의 통신 비용. 효율적인 구현이 NVIDIA NCCL, AMD RCCL, Google CC 라이브러리.&lt;/p&gt;
&lt;h2 id=&quot;프레임워크&quot;&gt;프레임워크&lt;/h2&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;프레임워크&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;주력&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;비고&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;PyTorch DDP&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DP&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가장 단순, 한 줄로 사용&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;PyTorch FSDP&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DP + ZeRO-3&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;메모리 효율 DP&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Megatron-LM&lt;/strong&gt; (NVIDIA)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;TP + PP + CP + DP + EP&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;LLM 학습 표준&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;DeepSpeed&lt;/strong&gt; (Microsoft)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;ZeRO 1/2/3 + PP&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MoE 지원&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Colossal-AI&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;모든 전략 통합&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;학습 + 추론 통합&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;JAX/Flax + pmap/pjit&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SPMD 스타일 분할&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Google TPU 표준&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;어디서-사용&quot;&gt;어디서 사용?&lt;/h2&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;모델&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;학습에 쓴 전략&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Llama 2/3 (70B+)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DP + TP + PP + FSDP&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Mixtral 8x7B (MoE)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DP + EP + TP&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;GPT-4 (추정)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DP + TP + PP + EP&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Gemini 1.5 Pro (1M context)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DP + TP + CP&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;DeepSeek V3 (671B MoE)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DP + EP + TP&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;h3 id=&quot;1-tp-degree-와-nvlink&quot;&gt;1. TP degree 와 NVLink&lt;/h3&gt;
&lt;p&gt;Tensor Parallelism 은 forward 마다 통신이 발생해 &lt;strong&gt;노드 내 NVLink&lt;/strong&gt; 가 없으면 성능이 급락한다. TP degree 는 노드 내 GPU 수 (보통 8) 를 초과하지 않는 것이 원칙.&lt;/p&gt;
&lt;h3 id=&quot;2-pipeline-bubble&quot;&gt;2. Pipeline bubble&lt;/h3&gt;
&lt;p&gt;PP 에서 micro-batch 수가 적으면 GPU idle 시간(bubble) 이 커진다. bubble fraction = (PP-1) / (PP-1+microbatches). microbatches 를 늘리거나 interleaved schedule 적용 필요.&lt;/p&gt;
&lt;h3 id=&quot;3-zero-3-와-메모리-재집합-비용&quot;&gt;3. ZeRO-3 와 메모리 재집합 비용&lt;/h3&gt;
&lt;p&gt;ZeRO-3 는 parameter 를 분산하므로 각 forward 단계에서 all-gather 가 필요. 작은 batch size 에서 통신이 오히려 bottleneck 이 될 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;4-체크포인트-복잡도&quot;&gt;4. 체크포인트 복잡도&lt;/h3&gt;
&lt;p&gt;TP+PP+DP 조합에서 체크포인트는 각 rank 마다 다른 파일이 생긴다. 학습 재개 시 정확히 같은 parallelism 설정이 필요하거나 변환 스크립트 필요.&lt;/p&gt;
&lt;h2 id=&quot;cs-에-미친-영향&quot;&gt;CS 에 미친 영향&lt;/h2&gt;
&lt;p&gt;분산 학습은 단순한 엔지니어링 기법을 넘어 ML 연구 전체를 바꿨다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;모델 크기 폭증&lt;/strong&gt;: 1B → 7B → 70B → 405B → 1T (3년에 1000배)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데이터센터 설계 변화&lt;/strong&gt;: NVLink, InfiniBand, 광 통신이 핵심 인프라&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;새로운 연구 분야&lt;/strong&gt;: scaling law, parallelism 자동 탐색 (Alpa, GSPMD)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;분산 시스템 지식 필수&lt;/strong&gt;: ML 엔지니어가 통신, 동기화, 장애 복구를 알아야&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SPMD]] - 분산 학습의 프로그래밍 모델&lt;/li&gt;
&lt;li&gt;[[양자화]] - 학습된 모델 압축&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ai</category><category>training</category><category>parallelism</category><category>scaling</category><author>koa (김신건)</author></item><item><title>HBM</title><link>https://shinkeonkim.com/wiki/ml/hbm/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/hbm/</guid><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;HBM&lt;/strong&gt; (High Bandwidth Memory)는 DRAM die 를 수직으로 적층해 매우 높은 대역폭을 제공하는 메모리 패키지. AI 시대 GPU/TPU 의 메모리 병목 해결을 담당한다.&lt;/p&gt;
&lt;p&gt;기존 GDDR 메모리가 PCB 위에서 칩 옆에 배치되는 것과 달리, HBM 은 GPU/TPU die 와 같은 &lt;strong&gt;interposer&lt;/strong&gt; 위에 수 mm 거리에 배치되어 &lt;strong&gt;수천 개의 병렬 채널&lt;/strong&gt;로 연결된다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;gddr-대비-차이&quot;&gt;GDDR 대비 차이&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph GDDR[&quot;GDDR (기존 방식)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        G_GPU[&quot;GPU die&quot;] &amp;#x3C;--&gt;|&quot;PCB 배선\n(32-bit x N 채널)&quot;| G_MEM[&quot;GDDR6X\n(칩 측면 배치)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph HBM_PKG[&quot;HBM (2.5D 패키징)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        H_GPU[&quot;GPU die&quot;] &amp;#x3C;--&gt;|&quot;Silicon Interposer\n(1024-bit 병렬)&quot;| H_MEM[&quot;HBM Stack\n(GPU 위/옆 mm 단위)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;GDDR6X&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;HBM3e&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;버스 폭&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;32-bit per chip&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1024-bit per stack&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;대역폭 (단일)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~56 GB/s&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~1,218 GB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;레이턴시&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~낮음&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~비슷&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;전력 효율&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;낮음&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;높음 (TSV 짧음)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;비용&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;저렴&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;비쌈 (~20배)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;용량&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;높음&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;제한적 (die 수)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;사용처&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;게임 GPU&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;AI GPU/TPU&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;구조&quot;&gt;구조&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                     [HBM Stack]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        |     DRAM Die (layer 12) |  ← HBM3e 까지 12 단&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        |     DRAM Die (layer 11) |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        |          ...            |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        |     DRAM Die (layer 1)  |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        |     Base Die (Logic)    |  ← I/O + Refresh + ECC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-----+-------+-----+-----+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              |       |     |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              ↓       ↓     ↓  (TSV: 수천 개의 실리콘 관통 전극)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-----+-------+-----+-----+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        |    Silicon Interposer   |  ← 마이크론 단위 배선&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-----+-------+-----+-----+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;              |       |     |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-----+-------+-----+-----+&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        |       GPU / TPU         |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        +-------------------------+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;base-die-logic-die&quot;&gt;Base Die (Logic Die)&lt;/h3&gt;
&lt;p&gt;스택의 가장 아래. DRAM die 가 아니라 &lt;strong&gt;로직 회로&lt;/strong&gt; 만 들어있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I/O 컨트롤러&lt;/li&gt;
&lt;li&gt;ECC (Error Correcting Code) 회로&lt;/li&gt;
&lt;li&gt;Refresh 로직 (DRAM 셀이 주기적 갱신 필요)&lt;/li&gt;
&lt;li&gt;Channel 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;through-silicon-via-tsv&quot;&gt;Through-Silicon Via (TSV)&lt;/h3&gt;
&lt;p&gt;핵심 기술. die 를 수직으로 관통하는 전극.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HBM3 기준 한 스택에 &lt;strong&gt;약 1,024 개 TSV&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;직경 수 마이크로미터&lt;/li&gt;
&lt;li&gt;모든 die 를 통과해야 하므로 정렬 정밀도가 핵심&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;silicon-interposer&quot;&gt;Silicon Interposer&lt;/h3&gt;
&lt;p&gt;GPU/TPU die 와 HBM stack 을 연결하는 작은 PCB 같은 실리콘 기판. 일반 PCB 보다 훨씬 미세한 배선 (마이크론 단위).&lt;/p&gt;
&lt;p&gt;HBM 의 비용 큰 이유 중 하나가 interposer + 패키징 (2.5D 패키징, 또는 CoWoS).&lt;/p&gt;
&lt;h2 id=&quot;channel-과-bank-구조&quot;&gt;Channel 과 Bank 구조&lt;/h2&gt;
&lt;p&gt;HBM 한 스택은 내부적으로 여러 channel 로 나뉜다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1 HBM3 stack&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ├── 8 channels (병렬 접근 가능)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  │   ├── 16 banks 각각&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  │   └── 각 bank: row + column address&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  └── 1024-bit wide interface&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Channel&lt;/strong&gt;: 독립적으로 read/write 가능. 8 channel = 8 개 메모리 컨트롤러가 동시 동작&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bank&lt;/strong&gt;: 한 channel 안에서 여러 행이 동시 활성화. bank parallelism 으로 throughput 증가&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wide interface&lt;/strong&gt;: 한 cycle 에 1024 bit (128 bytes) 동시 전송&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;GPU 메모리 컨트롤러는 이 8 channels × 16 banks 를 잘 활용해야 최대 대역폭을 낸다. 그래서 GPU 의 메모리 접근 패턴 (coalesced access) 이 중요.&lt;/p&gt;
&lt;h2 id=&quot;동작-원리&quot;&gt;동작 원리&lt;/h2&gt;
&lt;p&gt;DRAM 의 기본 동작은 같다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1. ACTIVATE: row 를 row buffer 로 가져오기 (RAS, ~15ns)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2. READ/WRITE: row buffer 의 column 선택 (CAS, ~15ns)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;3. PRECHARGE: 다음 access 를 위해 row 닫기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;HBM 의 트릭:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- 8 channel × 16 bank = 128개 작업을 동시 진행&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- TSV 가 짧아 latency 가 일반 DDR 과 비슷 (~80ns) 이지만&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- 동시 처리량은 ~20배 (1.2 TB/s vs 50 GB/s)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;즉 HBM 은 &lt;em&gt;latency&lt;/em&gt; 가 아니라 &lt;em&gt;throughput&lt;/em&gt; 으로 이긴다. 한 access 의 응답 시간은 비슷하지만 &lt;strong&gt;동시 처리 가능 수가 압도적&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;세대별-대역폭&quot;&gt;세대별 대역폭&lt;/h2&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;세대&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;출시&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;스택당 대역폭&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;비고&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;HBM1&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2015&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;128 GB/s&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;AMD Fiji&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;HBM2&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2016&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;256 GB/s&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA V100&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;HBM2e&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2019&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;460 GB/s&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA A100&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;HBM3&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;2022&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;819 GB/s&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA H100, TPU v5p&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;HBM3e&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;2024&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;1,218 GB/s&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA H200, B200 (12-stack)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;HBM4&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2026 예정&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~2,048 GB/s&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA Rubin, AMD MI400&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;비교용으로, DDR5 한 채널은 약 51 GB/s. &lt;strong&gt;HBM3e 한 스택이 DDR5 의 24배&lt;/strong&gt; 대역폭.&lt;/p&gt;
&lt;h2 id=&quot;왜-ai-에-필수인가&quot;&gt;왜 AI 에 필수인가&lt;/h2&gt;
&lt;h3 id=&quot;roofline-model-산술-강도&quot;&gt;Roofline Model: 산술 강도&lt;/h3&gt;
&lt;p&gt;AI 워크로드를 분류하는 핵심 개념.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;산술 강도 = FLOPs / 메모리 바이트 전송량&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;메모리 바운드&lt;/strong&gt;: 산술 강도 낮음. GPU 연산 유닛이 놀고 메모리 기다림. HBM 이 직접 영향.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;컴퓨트 바운드&lt;/strong&gt;: 산술 강도 높음. 메모리보다 연산이 병목. Tensor Core 가 영향.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;LLM 추론 예:&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;단계&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;산술 강도&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;병목&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Prefill (긴 입력 처리)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;높음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;컴퓨트 바운드&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Decode (토큰 생성)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;낮음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;메모리 바운드&lt;/strong&gt; (HBM 직결)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Attention (긴 컨텍스트)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;낮음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;메모리 바운드&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;LLM 서빙 속도는 대부분 &lt;strong&gt;HBM 대역폭이 결정&lt;/strong&gt;한다.&lt;/p&gt;
&lt;h3 id=&quot;실제-수치&quot;&gt;실제 수치&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;GPT-3 175B 모델은 FP16 으로 350 GB&lt;/li&gt;
&lt;li&gt;매 토큰 생성마다 모델 가중치를 전부 메모리에서 가져와야 함&lt;/li&gt;
&lt;li&gt;1초에 100 토큰 생성하려면 35 TB/s 대역폭 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 수치는 HBM 8 스택 (8 × 1.2 TB/s = 9.6 TB/s) 으로도 부족하다. 그래서:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모델 분할 (multi-GPU)&lt;/li&gt;
&lt;li&gt;양자화 (FP16 → INT8 → INT4)&lt;/li&gt;
&lt;li&gt;KV cache 최적화 (Flash Attention)&lt;/li&gt;
&lt;li&gt;HBM4, HBM5 로의 지속 진화&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;flash-attention-과-hbm&quot;&gt;Flash Attention 과 HBM&lt;/h3&gt;
&lt;p&gt;Flash Attention (Dao et al., 2022) 은 HBM I/O 를 최소화하는 어텐션 구현.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;기존 Attention:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Q, K, V 행렬 HBM → SRAM 이동 (대용량)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  S = QK^T 계산&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  S HBM 에 저장&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  P = softmax(S) 계산&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  P HBM 에 저장&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  O = PV 계산 → HBM&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Flash Attention:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Q, K, V 타일(tile)만 SRAM 에 로드&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  타일 단위 내에서 softmax + 곱 완결&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  HBM write 획기적 감소 (2-4배 속도 향상)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;HBM 대역폭을 아끼는 알고리즘 설계가 성능의 핵심.&lt;/p&gt;
&lt;h2 id=&quot;비용-구조&quot;&gt;비용 구조&lt;/h2&gt;
&lt;p&gt;HBM 은 비싸다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;일반 DDR5 16GB: ~$50&lt;/li&gt;
&lt;li&gt;HBM3e 16GB: ~$1,000 (20배)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이유:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;TSV 공정 복잡 (수율 낮음)&lt;/li&gt;
&lt;li&gt;수직 적층 패키징 비용&lt;/li&gt;
&lt;li&gt;SK Hynix 사실상 독점 (HBM3e 의 75%+ 점유)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;NVIDIA H100 의 HBM 비용이 전체 칩 가격 (~$30,000) 의 약 1/3 을 차지한다.&lt;/p&gt;
&lt;h2 id=&quot;cpu-vs-gpu-메모리-격차&quot;&gt;CPU vs GPU 메모리 격차&lt;/h2&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;프로세서&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;메모리 종류&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;대역폭&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Intel Core i9 (DDR5)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DDR5-5600&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~89 GB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Apple M4 Max (LPDDR5X)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;unified&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~546 GB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;AMD Threadripper (DDR5)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DDR5-5200&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~166 GB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;NVIDIA H100 (HBM3)&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;HBM3 5 stack&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;~3,350 GB/s&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;NVIDIA B200 (HBM3e)&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;HBM3e 8 stack&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;~8,000 GB/s&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;GPU/TPU 가 AI 워크로드를 압도하는 핵심 이유 = HBM 의 대역폭.&lt;/p&gt;
&lt;h2 id=&quot;용량-vs-대역폭-trade-off&quot;&gt;용량 vs 대역폭 trade-off&lt;/h2&gt;
&lt;p&gt;HBM 은 대역폭은 압도적이지만 &lt;strong&gt;용량 한계&lt;/strong&gt;가 있다.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;시스템&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;HBM 용량&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;GDDR/DDR 최대&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA H100 (80GB)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;80 GB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;(DDR5 호스트 2TB)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA H200&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;141 GB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;(DDR5 호스트 2TB)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Google TPU v5p pod&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;스택 수에 비례&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;(TPU HBM only)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;GPU 가속기에서 모델이 HBM 용량을 초과하면 두 가지 선택:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Multi-GPU 샤딩&lt;/strong&gt;: tensor/pipeline parallelism 으로 분산&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Offloading&lt;/strong&gt;: CPU RAM 으로 overflow (대역폭 급감)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;HBM 용량은 AI 모델 크기의 자연적 상한선이다.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;대역폭이 높아도 접근 패턴이 비효율이면 낭비&lt;/strong&gt;: GPU 는 coalesced memory access (연속된 주소) 일 때 최대 대역폭을 낸다. 랜덤 접근이면 대역폭의 일부만 활용.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;용량 한계&lt;/strong&gt;: HBM3e 최대 약 96 GB (H200). 모델이 이를 초과하면 multi-GPU 분산이 불가피. HBM 용량은 GDDR 대비 여전히 제한적.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[GPU]] - GPU 아키텍처: Tensor Core, SIMT, SM&lt;/li&gt;
&lt;li&gt;[[TPU]] - Google TPU 와 HBM 활용&lt;/li&gt;
&lt;li&gt;[[SIMT]] - GPU 실행 모델: warp, coalesced access&lt;/li&gt;
&lt;li&gt;[[분산 학습]] - HBM 한계 초과 시: tensor/pipeline parallelism&lt;/li&gt;
&lt;li&gt;[[quantization]] - 메모리 절약으로 HBM 부담 줄이기&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>hardware</category><category>memory</category><category>gpu</category><category>tpu</category><category>dram</category><author>koa (김신건)</author></item><item><title>SIMT</title><link>https://shinkeonkim.com/wiki/ml/simt/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/simt/</guid><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;SIMT&lt;/strong&gt; (Single Instruction, Multiple Threads) 는 NVIDIA 가 정립한 GPU 의 실행 모델이다. 한 명령(instruction) 을 한 그룹의 thread(warp) 가 동시에 실행하되, &lt;strong&gt;각 thread 는 자기 레지스터와 데이터&lt;/strong&gt;를 갖는다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;언제-쓰이나&quot;&gt;언제 쓰이나&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GPU 프로그래밍 (CUDA, ROCm, OpenCL) 의 실행 원리 이해&lt;/li&gt;
&lt;li&gt;커널 최적화: warp divergence, memory coalescing, occupancy&lt;/li&gt;
&lt;li&gt;ML 모델 추론/학습 시 GPU 활용률 분석&lt;/li&gt;
&lt;li&gt;[[TPU|TPU]] 의 Systolic Array 와 비교 시 기준점&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;simd-와의-차이&quot;&gt;SIMD 와의 차이&lt;/h2&gt;
&lt;p&gt;SIMD (Single Instruction Multiple Data) 와 헷갈리기 쉽다.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;SIMD&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;SIMT&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;데이터 그룹&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;벡터 레지스터 (예: AVX-512 = 16 floats)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;thread (수 십개)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;분기 처리&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;어렵음 (masked operation)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;자동 (warp divergence)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;프로그래밍 모델&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;명시적 SIMD intrinsic&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;평범한 thread 코드&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;레지스터&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;공유 벡터 레지스터&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;각 thread 독립 레지스터&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;대표 사례&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;CPU AVX, ARM NEON&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA CUDA, AMD ROCm&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;CUDA 코드는 마치 각 thread 가 독립적으로 도는 것처럼 작성하지만, 하드웨어는 32 thread (= 1 warp)를 lockstep 으로 함께 실행한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__global__ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; blockIdx.x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; blockDim.x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; threadIdx.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n) c[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b[i];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 각 thread 가 c[i] = a[i] + b[i] 를 자기 i 로 수행&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 한 warp 의 32 thread 가 동시에 ADD 명령 실행&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;thread-계층-thread--block--grid&quot;&gt;Thread 계층: Thread / Block / Grid&lt;/h2&gt;
&lt;p&gt;CUDA 커널은 3단계 계층으로 thread 를 구성한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Grid[&quot;Grid\n(전체 커널)&quot;] --&gt; B0[&quot;Block 0&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Grid --&gt; B1[&quot;Block 1&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Grid --&gt; BN[&quot;Block N&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    B0 --&gt; W0[&quot;Warp 0\n(32 threads)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    B0 --&gt; W1[&quot;Warp 1\n(32 threads)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    B0 --&gt; WK[&quot;Warp K\n(32 threads)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    W0 --&gt; T[&quot;Thread 0 ~ 31\n(각자 레지스터 + 데이터)&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Thread&lt;/strong&gt;: 독립적 레지스터 + 스택. 고유 &lt;code&gt;threadIdx&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block&lt;/strong&gt;: 공유 메모리(SRAM)를 공유하는 thread 그룹. 한 SM 에 할당.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grid&lt;/strong&gt;: 전체 커널 실행 범위. 여러 SM 에 분산.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 예: 1M 원소 덧셈&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Grid = 1000 blocks, Block = 1024 threads&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1024&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(a, b, c, N);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// threadIdx.x: 0~1023 (블록 내)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// blockIdx.x : 0~999  (그리드 내)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// globalIdx   = blockIdx.x * 1024 + threadIdx.x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;sm-streaming-multiprocessor-아키텍처&quot;&gt;SM (Streaming Multiprocessor) 아키텍처&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;SM (Streaming Multiprocessor)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        WS[&quot;Warp Scheduler\n(64 warp 관리)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        RF[&quot;Register File\n(65536 x 32-bit)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        SMEM[&quot;Shared Memory / L1\n(228KB, H100)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        CC[&quot;CUDA Cores\n(128개 FP32)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        TC[&quot;Tensor Cores\n(4개 BF16/FP8)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    SMEM &amp;#x3C;--&gt; CC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    SMEM &amp;#x3C;--&gt; TC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    WS --&gt; CC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    WS --&gt; TC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    SMEM --&gt; L2[&quot;L2 Cache&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    L2 --&gt; HBM[&quot;HBM&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;H100 SM 기준:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;128 CUDA Cores (FP32)&lt;/li&gt;
&lt;li&gt;4 Tensor Cores (BF16/FP8 matmul)&lt;/li&gt;
&lt;li&gt;최대 64 warp 동시 보유, 한 cycle 에 4 warp 디스패치&lt;/li&gt;
&lt;li&gt;Shared Memory: 228 KB / SM (L1 와 공유)&lt;/li&gt;
&lt;li&gt;Register File: 65536 x 32-bit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;NVIDIA H100 = 132 SM × 64 warp × 32 thread = &lt;strong&gt;약 27만 thread 동시 처리&lt;/strong&gt; 가능.&lt;/p&gt;
&lt;h2 id=&quot;warp&quot;&gt;Warp&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Warp 크기&lt;/strong&gt;: NVIDIA = 32 threads, AMD wavefront = 32 또는 64&lt;/li&gt;
&lt;li&gt;1 warp 의 모든 thread 는 &lt;strong&gt;같은 PC (program counter)&lt;/strong&gt; 를 공유 → 같은 명령 동시 수행&lt;/li&gt;
&lt;li&gt;각 thread 는 &lt;strong&gt;고유한 thread index&lt;/strong&gt; + 자기 레지스터 보유&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;SM (Streaming Multiprocessor) 한 개:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - 64 개의 warp 동시 보유 가능&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - 한 cycle 에 1~4 개의 warp 명령 디스패치&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - 같은 SM 의 warp 들은 공유 메모리(SRAM) 접근 가능&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;occupancy&quot;&gt;Occupancy&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Occupancy&lt;/strong&gt; = SM 에 실제 할당된 warp 수 / SM 최대 warp 수.&lt;/p&gt;
&lt;p&gt;높은 occupancy 는 메모리 레이턴시를 숨기는 데 중요하다. 한 warp 가 메모리 대기 중일 때 다른 warp 를 실행해 파이프라인을 채운다.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Occupancy 저하 요인&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;영향&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;레지스터 과다 사용&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1 SM 의 Register File 총량 초과 시 block 수 감소&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;공유 메모리 과사용&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1 SM 의 SRAM 을 여러 block 이 나눠 씀&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Block 크기가 warp 배수 아님&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;마지막 warp 에 idle thread 발생&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;큰 Block&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;한 SM 에 몇 개 block 만 들어감&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Occupancy 계산 보조 API&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numBlocks;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cudaOccupancyMaxActiveBlocksPerMultiprocessor&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;numBlocks,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    myKernel,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    blockSize,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sharedMemBytes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;warp-divergence&quot;&gt;Warp Divergence&lt;/h2&gt;
&lt;p&gt;SIMT 의 가장 큰 함정.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_A&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_B&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;같은 warp 의 일부 thread 만 &lt;code&gt;if&lt;/code&gt; 경로를 타고 나머지가 &lt;code&gt;else&lt;/code&gt; 를 타면, &lt;strong&gt;GPU 는 두 경로를 직렬로 실행&lt;/strong&gt;한다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Cycle 1: warp 의 (x&gt;0) thread 만 활성, compute_A 실행&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;         (x&amp;#x3C;=0) thread 는 idle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Cycle 2: warp 의 (x&amp;#x3C;=0) thread 만 활성, compute_B 실행&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;         (x&gt;0) thread 는 idle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;결과적으로 같은 warp 안에서 분기가 갈리면 &lt;strong&gt;활용률이 절반&lt;/strong&gt;으로 떨어진다.&lt;/p&gt;
&lt;h3 id=&quot;divergence-최소화-패턴&quot;&gt;Divergence 최소화 패턴&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;데이터 정렬&lt;/strong&gt;: 비슷한 분기 결과를 가진 thread 를 같은 warp 로 모음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;분기 단순화&lt;/strong&gt;: triangle ops, masked select 등으로 변환&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;branch-free 알고리즘 선호&lt;/strong&gt;: &lt;code&gt;min(a, b)&lt;/code&gt; 대신 조건 없는 수식&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;메모리-접근-패턴&quot;&gt;메모리 접근 패턴&lt;/h2&gt;
&lt;p&gt;SIMT 의 또 다른 성능 결정 요인은 &lt;strong&gt;coalesced memory access&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;한 warp 의 32 thread 가 연속된 메모리 주소를 접근 → 1번의 메모리 트랜잭션으로 처리 (좋음)&lt;/li&gt;
&lt;li&gt;흩어진 주소를 접근 → 32번의 트랜잭션 (나쁨, 32x 메모리 대역폭 소모)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;배열 인덱스를 thread ID 로 만드는 게 정석.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Good: thread 0 → a[0], thread 1 → a[1], ... → coalesced&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data[threadIdx.x]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// Bad: thread 0 → a[0], thread 1 → a[32], ... → scattered&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data[threadIdx.x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;shared-memory-sram-활용&quot;&gt;Shared Memory (SRAM) 활용&lt;/h2&gt;
&lt;p&gt;같은 block 의 thread 들이 공유하는 빠른 SRAM 을 활용하면 전역 메모리 접근을 줄일 수 있다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__global__ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; matrix_mul_shared&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; A, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; B, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; C, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; N) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    __shared__ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tileA[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;][&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    __shared__ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tileB[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;][&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; row &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; blockIdx.y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 32&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; threadIdx.y;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; col &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; blockIdx.x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 32&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; threadIdx.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sum &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; N &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; t&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        // 전역 메모리 → 공유 메모리 (coalesced 로드)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tileA[threadIdx.y][threadIdx.x] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; A[row &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; N &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 32&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; threadIdx.x];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tileB[threadIdx.y][threadIdx.x] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; B[(t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 32&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; threadIdx.y) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; N &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; col];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        __syncthreads&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  // 모든 thread 로드 완료 대기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; k &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; k &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;; k&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            sum &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tileA[threadIdx.y][k] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tileB[k][threadIdx.x];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        __syncthreads&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    C[row &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; N &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; col] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sum;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Shared Memory 에 tile 을 올린 뒤 반복 참조 → 전역 메모리 접근 횟수 크게 감소.&lt;/p&gt;
&lt;h2 id=&quot;nvidia-vs-amd&quot;&gt;NVIDIA vs AMD&lt;/h2&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;NVIDIA (CUDA)&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;AMD (ROCm/HIP)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Warp 단위&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;32 threads (warp)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;32 또는 64 threads (wavefront)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;코어 명칭&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;CUDA Core&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Stream Processor&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;SM 명칭&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SM (Streaming Multiprocessor)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;CU (Compute Unit)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;행렬 가속&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Tensor Core&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Matrix Core&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;언어&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;CUDA C++&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;HIP (CUDA 유사), OpenCL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;이식성&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;낮음 (NVIDIA only)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;HIP 은 CUDA 코드 자동 변환 가능&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;AMD wavefront 크기가 64 인 경우, branch divergence 의 비용이 NVIDIA 대비 2배가 될 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;관련-모델-spmd&quot;&gt;관련 모델: SPMD&lt;/h2&gt;
&lt;p&gt;SIMT 와 비슷하지만 더 일반적인 모델로 &lt;strong&gt;SPMD&lt;/strong&gt; (Single Program Multiple Data) 가 있다. MPI 같은 분산 컴퓨팅에서 모든 노드가 같은 프로그램을 다른 데이터로 실행하는 패턴.&lt;/p&gt;
&lt;p&gt;SIMT 는 SPMD 의 GPU 하드웨어 구현 정도로 보면 맞다.&lt;/p&gt;
&lt;h2 id=&quot;흔한-함정&quot;&gt;흔한 함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Warp divergence 무시&lt;/strong&gt; = 분기 많은 커널에서 활용률 50% 이하로 급락. 데이터 정렬 또는 branch-free 패턴으로 최소화.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Uncoalesced memory access&lt;/strong&gt; = 흩어진 주소 접근은 대역폭 낭비. thread ID 를 연속 인덱스로 매핑.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block 크기가 32 배수 아님&lt;/strong&gt; = 마지막 warp 에 idle thread. block 크기는 항상 32 배수로.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shared memory bank conflict&lt;/strong&gt; = 같은 bank 에 여러 thread 가 동시 접근 시 직렬화. padding 으로 해결.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Occupancy 무조건 최대화&lt;/strong&gt; = 레지스터/SRAM 을 너무 아끼면 오히려 스루풋 감소. profiler 로 최적점 탐색.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[HBM]] - SIMT thread 수만큼 메모리 대역폭이 중요한 이유&lt;/li&gt;
&lt;li&gt;[[Systolic Array]] - SIMT 와 다른 행렬 곱셈 전용 구조&lt;/li&gt;
&lt;li&gt;[[TPU]] - Systolic Array 기반 ML 가속기 (SIMT 와 비교)&lt;/li&gt;
&lt;li&gt;[[SPMD]] - 분산 컴퓨팅에서의 유사 패턴&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>gpu</category><category>parallel-computing</category><category>architecture</category><category>cuda</category><author>koa (김신건)</author></item><item><title>SPMD</title><link>https://shinkeonkim.com/wiki/ml/spmd/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/spmd/</guid><pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;SPMD&lt;/strong&gt; (Single Program, Multiple Data)는 병렬 컴퓨팅의 대표 모델 중 하나. &lt;strong&gt;모든 프로세스(또는 thread)가 같은 프로그램을 실행하되, 각자 다른 데이터를 처리&lt;/strong&gt;한다.&lt;/p&gt;
&lt;p&gt;Frederica Darema 가 1980년대 후반 IBM 에서 정의한 개념. MPI, CUDA, OpenMP 등 거의 모든 병렬 컴퓨팅 프레임워크의 기본 추상화.&lt;/p&gt;
&lt;h2 id=&quot;동작-방식&quot;&gt;동작 방식&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    P[&quot;같은 프로그램 코드&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    P --&gt; R0[&quot;Rank 0\n데이터 슬라이스 0&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    P --&gt; R1[&quot;Rank 1\n데이터 슬라이스 1&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    P --&gt; R2[&quot;Rank 2\n데이터 슬라이스 2&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    P --&gt; RN[&quot;Rank N-1\n데이터 슬라이스 N-1&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    R0 &amp;#x26; R1 &amp;#x26; R2 &amp;#x26; RN --&gt; SYNC[&quot;집합 통신\n(All-Reduce / All-Gather / Barrier)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    SYNC --&gt; OUT[&quot;집계된 결과&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# SPMD 의사 코드 (모든 노드가 같은 코드 실행)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;my_rank &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; get_rank()           &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 0, 1, 2, ..., N-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;my_data &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; load_data(my_rank)   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 노드마다 다른 데이터 슬라이스&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; process(my_data)      &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 같은 처리 로직&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;all_results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; collective_op(result)  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 통신 (all-reduce 등)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;각 노드/프로세스는:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;rank (또는 id)&lt;/strong&gt; 로 자기를 식별&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자기 데이터 슬라이스&lt;/strong&gt;만 처리&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;동기화 지점&lt;/strong&gt; 에서 통신 (barrier, all-reduce, broadcast 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;다른-병렬-모델과의-차이&quot;&gt;다른 병렬 모델과의 차이&lt;/h2&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;모델&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;프로그램&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;데이터&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;동기화&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;대표 사례&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;SIMD&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;여러 vector&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;매 사이클&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;CPU AVX, SSE&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;[[SIMT]]&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;thread 마다&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;warp 단위&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;GPU CUDA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;SPMD&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1 (인스턴스 N개)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;노드 마다&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;명시적&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MPI, 분산 학습&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;MIMD&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;여러&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;여러&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;명시적&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;일반 멀티스레드&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;[[SIMT]] 는 SPMD 의 GPU 하드웨어 구현 정도로 볼 수 있다. CUDA 코드를 작성할 때 각 thread 가 자기 &lt;code&gt;threadIdx.x&lt;/code&gt; 로 자기 데이터를 처리하는 패턴이 정확히 SPMD.&lt;/p&gt;
&lt;h2 id=&quot;spmd-의-매력&quot;&gt;SPMD 의 매력&lt;/h2&gt;
&lt;h3 id=&quot;1-프로그래밍-단순함&quot;&gt;1. 프로그래밍 단순함&lt;/h3&gt;
&lt;p&gt;여러 다른 프로그램을 짜는 게 아니라 하나만 짜면 됨. rank 로 분기.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; my_rank &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    coordinator_logic()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    worker_logic()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-확장-용이&quot;&gt;2. 확장 용이&lt;/h3&gt;
&lt;p&gt;같은 코드를 100 노드든 10,000 노드든 실행 가능. 노드 수만 바꾸면 끝.&lt;/p&gt;
&lt;h3 id=&quot;3-동기화가-명시적&quot;&gt;3. 동기화가 명시적&lt;/h3&gt;
&lt;p&gt;모든 노드가 같은 코드를 실행하므로 &lt;code&gt;collective_op&lt;/code&gt; 같은 동기화 지점이 자연스럽게 일치.&lt;/p&gt;
&lt;h2 id=&quot;실제-예시&quot;&gt;실제 예시&lt;/h2&gt;
&lt;h3 id=&quot;mpi-message-passing-interface&quot;&gt;MPI (Message Passing Interface)&lt;/h3&gt;
&lt;p&gt;전통적인 HPC 의 SPMD 표준.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;MPI_Init&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;argc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;argv&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rank, size;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;MPI_Comm_rank&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(MPI_COMM_WORLD, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;rank&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;MPI_Comm_size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(MPI_COMM_WORLD, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 각 rank 가 자기 데이터 슬라이스 처리&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; local_sum &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; compute_local_sum&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(rank);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 모든 노드의 합 = global_sum 으로 집계&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;double&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; global_sum;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;MPI_Reduce&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;local_sum&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;global_sum&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, MPI_DOUBLE, MPI_SUM, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, MPI_COMM_WORLD);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;MPI_Finalize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;cuda-gpu&quot;&gt;CUDA (GPU)&lt;/h3&gt;
&lt;p&gt;GPU 의 SPMD 구현. 각 thread 가 자기 인덱스로 작업.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cpp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__global__ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; add_vectors&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;float*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  int&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; blockIdx.x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; blockDim.x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; threadIdx.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n) c[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b[i];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;pytorch-ddp--fsdp&quot;&gt;PyTorch DDP / FSDP&lt;/h3&gt;
&lt;p&gt;[[분산 학습]] 의 SPMD 패턴. 모든 GPU 가 같은 모델 코드를 실행, 각자 다른 배치 처리, &lt;code&gt;all_reduce&lt;/code&gt; 로 gradient 동기화.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 모든 rank 가 실행 (DDP)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;dist.init_process_group()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DDP(model)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; batch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; dataloader:  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# rank 마다 다른 배치&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    loss &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model(batch)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    loss.backward()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # DDP 가 자동으로 all-reduce&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    optimizer.step()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;DDP 와 FSDP 의 차이:&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;DDP&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;FSDP&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;모델 복제&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;각 GPU 에 전체 복사&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;파라미터 샤딩&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;메모리&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;GPU 수만큼 중복&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;효율적&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;대상&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;모델이 단일 GPU 에 맞을 때&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;초대형 모델&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;jax-pmap&quot;&gt;JAX &lt;code&gt;pmap&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;함수형 SPMD. XLA 컴파일러가 device 배치를 자동 최적화.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.numpy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jnp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@jax.pmap&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; step&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params, batch):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    loss, grads &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.value_and_grad(compute_loss)(params, batch)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # pmap 이 자동으로 all-reduce&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    grads &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.lax.pmean(grads, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;axis_name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;batch&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    new_params &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; params &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; learning_rate &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; grads&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; new_params, loss&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# pmap 은 모든 device 에 같은 함수를 자동 분배&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;new_params, losses &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; step(replicated_params, sharded_batch)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;jax-shard_map--jit--sharding-최신&quot;&gt;JAX &lt;code&gt;shard_map&lt;/code&gt; / &lt;code&gt;jit&lt;/code&gt; + sharding (최신)&lt;/h3&gt;
&lt;p&gt;JAX 의 최신 권장 패턴. &lt;code&gt;pmap&lt;/code&gt; 보다 더 유연한 샤딩 명세.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.sharding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Mesh, PartitionSpec &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; P&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.experimental &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mesh_utils&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 8 GPU 를 (data, model) 2D 메시로&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;devices &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mesh_utils.create_device_mesh((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mesh &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Mesh(devices, (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 텐서 샤딩 명세&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data_sharding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.sharding.NamedSharding(mesh, P(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;None&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model_sharding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.sharding.NamedSharding(mesh, P(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;None&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;model&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@functools.partial&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(jax.jit, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;in_shardings&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(model_sharding, data_sharding))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; train_step&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(params, batch):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;collective-통신-종류&quot;&gt;Collective 통신 종류&lt;/h2&gt;
&lt;p&gt;SPMD 프로그램의 동기화 지점.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph AR[&quot;All-Reduce&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        AR0[&quot;R0: 3&quot;] &amp;#x26; AR1[&quot;R1: 5&quot;] &amp;#x26; AR2[&quot;R2: 2&quot;] --&gt; SUM[&quot;합: 10&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        SUM --&gt; AR0R[&quot;R0: 10&quot;] &amp;#x26; AR1R[&quot;R1: 10&quot;] &amp;#x26; AR2R[&quot;R2: 10&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;연산&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;설명&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;사용처&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;All-Reduce&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;모든 노드 값 집계 후 전체 배포&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;gradient 합산&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Broadcast&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;한 노드에서 전체로 배포&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;파라미터 초기 동기화&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Scatter&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;한 노드에서 각 노드로 분배&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;배치 분할&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Gather&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;각 노드에서 한 노드로 집결&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;결과 모으기&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;All-Gather&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Scatter 의 역: 분산 배열 전체 복원&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FSDP 파라미터 복원&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Reduce-Scatter&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Reduce + 결과를 노드별로 샤딩&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FSDP gradient 집계&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Barrier&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;모든 노드 도착 대기&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;단순 동기화&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;spmd-의-한계&quot;&gt;SPMD 의 한계&lt;/h2&gt;
&lt;h3 id=&quot;1-heterogeneous-워크로드-어려움&quot;&gt;1. Heterogeneous 워크로드 어려움&lt;/h3&gt;
&lt;p&gt;모든 노드가 같은 일을 한다는 가정. 일부 노드만 다른 작업이 필요한 경우 ([[분산 학습#pipeline-parallelism|Pipeline Parallelism]] 등) MIMD 스타일로 전환 필요.&lt;/p&gt;
&lt;h3 id=&quot;2-load-imbalance&quot;&gt;2. Load imbalance&lt;/h3&gt;
&lt;p&gt;각 노드의 작업량이 다르면 빠른 노드가 느린 노드를 기다림. 균형 분할이 중요.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Rank 0: 배치 크기 1024 (처리 완료: t=1.0s)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Rank 1: 배치 크기 1024 (처리 완료: t=1.0s)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Rank 2: 배치 크기 1024 (처리 완료: t=1.0s)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Rank 3: 배치 크기 1024 이지만 긴 시퀀스 (처리 완료: t=2.5s)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;          ↑ 모든 rank 가 rank 3 을 기다림 (bubble)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-통신-비용&quot;&gt;3. 통신 비용&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;all_reduce&lt;/code&gt;, &lt;code&gt;all_gather&lt;/code&gt; 같은 collective 가 노드 수에 따라 비용 급증. 100 노드 → 10,000 노드 확장 시 통신 패턴 재설계 필요.&lt;/p&gt;
&lt;p&gt;Ring-AllReduce 같은 최적화된 통신 토폴로지가 실제로는 O(N) 이 아닌 O(1) 에 가까운 성능을 낸다.&lt;/p&gt;
&lt;h2 id=&quot;spmd-와-data-parallelism-관계&quot;&gt;SPMD 와 Data Parallelism 관계&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Data Parallelism (데이터 병렬)&lt;/strong&gt; 은 SPMD 의 가장 흔한 구현 패턴이다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Data Parallelism 구조:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  전체 배치 N&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ├── GPU 0: 배치 0 ~ N/k (같은 모델, 다른 배치)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ├── GPU 1: 배치 N/k ~ 2N/k&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  └── GPU k-1: ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → backward: gradient all-reduce&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  → optimizer: 동기화된 weight update&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SPMD 관점에서 각 GPU 는 완전히 동일한 코드를 실행하되 &lt;code&gt;rank&lt;/code&gt; 로 배치 슬라이스를 식별한다. &lt;code&gt;DDP&lt;/code&gt; 와 &lt;code&gt;FSDP&lt;/code&gt; 모두 이 패턴.&lt;/p&gt;
&lt;p&gt;반면 &lt;strong&gt;Tensor Parallelism&lt;/strong&gt; 은 &lt;strong&gt;같은 배치&lt;/strong&gt;를 여러 GPU 에 나눠 처리. 같은 코드이지만 데이터 대신 &lt;strong&gt;연산(행렬 곱)&lt;/strong&gt; 를 분할 → 이것도 SPMD 이지만 데이터 분할 축이 다르다.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;XLA/JAX 에서 동적 shape 주의&lt;/strong&gt;: &lt;code&gt;pmap&lt;/code&gt; 내부 shape 이 rank 마다 달라지면 XLA 재컴파일 트리거. 배치 크기를 rank 수의 배수로 패딩해 shape 고정.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;MPI 프로세스 중 하나만 죽어도 전체 중단&lt;/strong&gt;: SPMD 는 모든 rank 가 같은 코드를 실행하므로 장애 허용이 어렵다. Checkpoint + restart 전략 필수.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[SIMT]] - GPU 하드웨어 SPMD 구현: warp, thread block&lt;/li&gt;
&lt;li&gt;[[분산 학습]] - 대규모 모델 학습의 SPMD 패턴: DDP, FSDP, Megatron&lt;/li&gt;
&lt;li&gt;[[HBM]] - 각 노드의 메모리 대역폭: 통신과 메모리의 trade-off&lt;/li&gt;
&lt;li&gt;[[GPU]] - SPMD 실행 기반: SM, warp scheduler&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>parallel-computing</category><category>programming-model</category><category>distributed</category><author>koa (김신건)</author></item><item><title>GPU: 그래픽/ML 병렬 프로세서</title><link>https://shinkeonkim.com/wiki/ml/gpu/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/gpu/</guid><pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;GPU (Graphics Processing Unit)&lt;/strong&gt; 는 원래 3D 그래픽 렌더링을 위해 설계됐지만, &lt;strong&gt;massively parallel&lt;/strong&gt; 아키텍처가 딥러닝의 행렬 연산과 완벽히 맞아 현재 AI 컴퓨팅의 표준 하드웨어가 됐다. NVIDIA, AMD, Intel 이 3대 제조사.&lt;/p&gt;
&lt;h2 id=&quot;언제-쓰이나&quot;&gt;언제 쓰이나&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;딥러닝 모델 학습 / 추론&lt;/li&gt;
&lt;li&gt;LLM inference serving (vLLM, TGI 등)&lt;/li&gt;
&lt;li&gt;3D 그래픽 렌더링, 영상 처리&lt;/li&gt;
&lt;li&gt;과학 시뮬레이션 (HPC), 암호화폐 채굴&lt;/li&gt;
&lt;li&gt;CUDA 에코시스템이 필요한 모든 병렬 워크로드&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;아키텍처-개요&quot;&gt;아키텍처 개요&lt;/h2&gt;
&lt;h3 id=&quot;전체-계층-구조&quot;&gt;전체 계층 구조&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    GPU[&quot;GPU 칩&quot;] --&gt; GPC[&quot;GPC\n(Graphics Processing Cluster)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    GPC --&gt; SM[&quot;SM (Streaming Multiprocessor)\n× 132개 (H100)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    SM --&gt; CUDA[&quot;CUDA Core × 128\n(FP32 ALU)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    SM --&gt; TC[&quot;Tensor Core × 4\n(행렬곱 전용)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    SM --&gt; Shared[&quot;Shared Memory\n+ L1 Cache (256KB)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    SM --&gt; Reg[&quot;Register File\n(65536 × 32bit)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    GPU --&gt; L2[&quot;L2 Cache (50MB)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    GPU --&gt; HBM[&quot;HBM3 (80GB, 3.35 TB/s)&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;sm-streaming-multiprocessor&quot;&gt;SM (Streaming Multiprocessor)&lt;/h3&gt;
&lt;p&gt;NVIDIA GPU 의 핵심 실행 단위. 각 SM 은 독립적인 연산 블록.&lt;/p&gt;
&lt;p&gt;H100 (Hopper 아키텍처) SM 구성:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;128개 FP32 CUDA 코어&lt;/strong&gt; (일반 연산)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;4개 Tensor Core&lt;/strong&gt; (3세대 Hopper TC: FP8/FP16/BF16/FP32 지원)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;256KB L1 cache + Shared Memory&lt;/strong&gt; (프로그래머 제어 가능)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Register file 65,536 × 32bit&lt;/strong&gt; (스레드 간 공유 없음)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Warp Scheduler 4개&lt;/strong&gt; (32스레드 warp 관리)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;H100 SXM5: 132 SM × (128 FP32 + 4 Tensor Core) = 16,896 CUDA cores&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;simt-gpu-실행-모델&quot;&gt;SIMT: GPU 실행 모델&lt;/h2&gt;
&lt;p&gt;[[simt|SIMT (Single Instruction Multiple Thread)]] 는 GPU 의 병렬 실행 모델.&lt;/p&gt;
&lt;h3 id=&quot;warp-실행&quot;&gt;Warp 실행&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Warp = 32개 스레드의 묶음 (하드웨어 실행 단위)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ┌──────────────────────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; │ Thread 0  Thread 1  ... Thread 31│   ← 동일 명령 동시 실행&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; └──────────────────────────────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;           Warp 0 (32T)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;SM 은 최대 64 warp (2048 스레드) 를 동시에 관리&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;활성 warp 중 하나가 메모리 대기 → 즉시 다른 warp 전환 (zero-cost context switch)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;branch-divergence-분기-발산&quot;&gt;Branch Divergence (분기 발산)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// SIMT 의 함정: if-else 분기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;if (threadIdx.x % 2 == 0) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    do_A();  // 짝수 스레드만&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;} else {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    do_B();  // 홀수 스레드만&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// Warp 내 분기 → 두 경로 순차 실행 (SIMD 효율 50% 낙하)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Warp 내 스레드가 다른 분기를 탈 경우, 두 경로를 순차적으로 실행하고 비활성 스레드는 마스킹. 성능 반감.&lt;/p&gt;
&lt;h2 id=&quot;메모리-계층&quot;&gt;메모리 계층&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;빠름 (작음)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Reg[&quot;Register\n(스레드 전용, ~1 cycle)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Shared[&quot;Shared Memory\n(SM 내 공유, ~1 cycle, 128-256KB)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        L1[&quot;L1 Cache\n(SM 내, ~10 cycle, Shared 와 공유)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;느림 (큼)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        L2[&quot;L2 Cache\n(전체 GPU 공유, ~200 cycle, 50MB)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        HBM[&quot;HBM (Global Memory)\n(~500 cycle, 80GB, 3.35 TB/s H100)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Reg --&gt; Shared --&gt; L1 --&gt; L2 --&gt; HBM&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;계층&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;크기&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;지연&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;대역폭&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;접근&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Register&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;스레드별 64KB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~1 cycle&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;최고&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;스레드 전용&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Shared Memory&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SM당 최대 228KB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~1 cycle&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;매우 높음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SM 내 블록 공유&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;L1 Cache&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SM당 128KB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~28 cycle&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;높음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;자동&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;L2 Cache&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;50MB (H100)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~200 cycle&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;중간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;자동&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;HBM (Global)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;80GB (H100)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~500 cycle&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;3.35 TB/s&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;전체 커널&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
메모리 대역폭이 병목인 커널(bandwidth-bound)을 컴퓨트 집약 커널(compute-bound)로 바꾸는 것이 GPU 최적화의 핵심. Shared Memory 활용과 메모리 coalescing 이 주요 기법.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;tensor-core-딥러닝-특화-유닛&quot;&gt;Tensor Core: 딥러닝 특화 유닛&lt;/h2&gt;
&lt;p&gt;CUDA 코어가 scalar(단일 FP32) 연산을 하는 반면, &lt;strong&gt;Tensor Core 는 4×4 행렬 연산을 1 클럭에 처리&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Tensor Core (Hopper, 3세대):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  D = A × B + C&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  A: [16×16], B: [16×8], C/D: [16×8]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  지원 형식: FP8, FP16, BF16, FP32, INT8, INT4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;CUDA Core (FP32):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  d = a * b + c   (scalar)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  1개 연산/clock&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;tensor-core-성능-h100-sxm5&quot;&gt;Tensor Core 성능 (H100 SXM5)&lt;/h3&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;정밀도&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;피크 TFLOPS&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP64&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;66.9&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP32 (CUDA Core)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;133.8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;TF32 (Tensor Core)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;989&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP16/BF16 (Tensor Core)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1,979&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP8 (Tensor Core)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;3,958&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;INT8 (Tensor Core)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;3,958&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;세대-비교&quot;&gt;세대 비교&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    V100[&quot;V100 (Volta 2017)\nTensor Core 1세대\n125 TFLOPS FP16\n16-32GB HBM2&quot;] --&gt; A100[&quot;A100 (Ampere 2020)\nTensor Core 3세대\nSparse 지원\n312 TFLOPS FP16\n40-80GB HBM2e&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    A100 --&gt; H100[&quot;H100 (Hopper 2022)\nTensor Core 4세대\nFP8 지원\n1,979 TFLOPS BF16\n80GB HBM3&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    H100 --&gt; B200[&quot;B200 (Blackwell 2024)\nFP4 지원\n9 PFLOPS FP8\n192GB HBM3e&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;GPU&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;아키텍처&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;BF16 TFLOPS&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;HBM&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;NVLink&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;V100&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Volta (2017)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;125&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;32GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVLink 2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;A100&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Ampere (2020)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;312&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;80GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVLink 3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;H100&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Hopper (2022)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1,979&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;80GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVLink 4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;H200&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Hopper (2024)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1,979&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;141GB HBM3e&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVLink 4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;B200&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Blackwell (2024)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4,500&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;192GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVLink 5&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;소프트웨어-스택&quot;&gt;소프트웨어 스택&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    App[&quot;PyTorch / TensorFlow / JAX&quot;] --&gt; Lib[&quot;cuDNN / cuBLAS / NCCL&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Lib --&gt; CUDA[&quot;CUDA Runtime / Driver&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    CUDA --&gt; HW[&quot;NVIDIA GPU HW&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    App2[&quot;OpenCL / ROCm (AMD)&quot;] --&gt; HW2[&quot;AMD GPU&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Triton[&quot;OpenAI Triton\n(Python CUDA 커널)&quot;] --&gt; CUDA&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;라이브러리&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;역할&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;CUDA&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA 독점 GPU 프로그래밍 API&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;cuDNN&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;CNN, Transformer 최적화 커널&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;cuBLAS&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;GEMM 최적화&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;NCCL&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;멀티 GPU 통신 (all-reduce 등)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Triton&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Python 에서 CUDA 커널 작성 (OpenAI)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;ROCm&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;AMD GPU 대응 오픈소스 스택&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;실전-cuda--pytorch-최적화&quot;&gt;실전: CUDA / PyTorch 최적화&lt;/h2&gt;
&lt;h3 id=&quot;기본-행렬곱-cuda&quot;&gt;기본 행렬곱 (CUDA)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// naive: global memory 직접 접근 (느림)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;__global__ void matmul_naive(float *A, float *B, float *C, int N) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    int row = blockIdx.y * blockDim.y + threadIdx.y;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    int col = blockIdx.x * blockDim.x + threadIdx.x;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    float sum = 0.0f;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    for (int k = 0; k &amp;#x3C; N; k++) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        sum += A[row * N + k] * B[k * N + col];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    C[row * N + col] = sum;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// shared memory tiling: L1 활용 (빠름)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;__global__ void matmul_tiled(float *A, float *B, float *C, int N) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    __shared__ float As[TILE][TILE];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    __shared__ float Bs[TILE][TILE];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // ... tiling 로직&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;pytorch-에서-tensor-core-활용&quot;&gt;PyTorch 에서 Tensor Core 활용&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Tensor Core 활성화: AMP (Automatic Mixed Precision)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.cuda.amp &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; autocast, GradScaler&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;scaler &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; GradScaler()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; autocast(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;dtype&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;torch.bfloat16):  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# BF16 → Tensor Core 자동 사용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    output &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;input&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    loss &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; criterion(output, target)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;scaler.scale(loss).backward()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;scaler.step(optimizer)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;scaler.update()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;flash-attention-메모리-효율-attention&quot;&gt;Flash Attention: 메모리 효율 Attention&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# standard: O(seq^2) HBM 접근&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# flash attention: HBM 접근 최소화, Shared Memory 활용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.nn.functional &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; F&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# PyTorch 2.0+ 기본 내장 (SDPA)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.backends.cuda.sdp_kernel(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    enable_flash&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    enable_math&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;False&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    enable_mem_efficient&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    output &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; F.scaled_dot_product_attention(q, k, v)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;cpu-와-비교&quot;&gt;CPU 와 비교&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;CPU (Intel Xeon)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        c_core[&quot;8-64 코어\n복잡한 ALU\n분기 예측, OoO 실행&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        c_mem[&quot;DDR5 ~200 GB/s&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        c_core --&gt; c_mem&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;GPU (H100)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        g_sm[&quot;132 SM\n16,896 CUDA Core\n528 Tensor Core&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        g_hbm[&quot;HBM3 3.35 TB/s&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        g_sm --&gt; g_hbm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;CPU (Xeon)&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;GPU (H100)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;코어 수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8-64&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;16,896 CUDA&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;클럭&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;3-5 GHz&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;~1.98 GHz&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;메모리 BW&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;~200 GB/s&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;3.35 TB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;분기 처리&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;최적화 (예측)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;비효율 (warp divergence)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;단일 스레드 성능&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;높음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;낮음&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;병렬 스루풋&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;낮음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;극도로 높음&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;딥러닝 행렬곱&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;낮음 (~2 TFLOPS)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1,979 TFLOPS (BF16)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;다중-gpu-연결&quot;&gt;다중 GPU 연결&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;단일 서버 (DGX H100)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        GPU0 &amp;#x3C;--&gt;|&quot;NVLink 4\n900 GB/s&quot;| GPU1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        GPU1 &amp;#x3C;--&gt;|&quot;NVLink 4&quot;| GPU2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        GPU2 &amp;#x3C;--&gt;|&quot;NVLink 4&quot;| GPU3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        GPU0 &amp;#x3C;--&gt;|&quot;NVLink 4&quot;| GPU3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;서버 간&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Server1 &amp;#x3C;--&gt;|&quot;InfiniBand NDR\n400 Gb/s&quot;| Server2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Server2 &amp;#x3C;--&gt;|&quot;InfiniBand&quot;| Server3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NVLink&lt;/strong&gt;: 노드 내 GPU 간 고속 상호연결 (단방향 900 GB/s, H100)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NVSwitch&lt;/strong&gt;: NVLink 스위치 패브릭, 8-16 GPU 완전 연결&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;InfiniBand&lt;/strong&gt;: 노드 간 연결, NCCL all-reduce 에 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;흔한-함정&quot;&gt;흔한 함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;메모리 coalescing 무시&lt;/strong&gt; = warp 32 스레드가 연속 주소 접근 안 하면 실효 BW 1/32. 메모리 레이아웃 설계 중요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;작은 커널 남발&lt;/strong&gt; = 커널 launch overhead 누적. 여러 op 을 하나로 fusion (torch.compile / Triton).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CPU-GPU 동기화 남발&lt;/strong&gt; = &lt;code&gt;.item()&lt;/code&gt;, &lt;code&gt;print(tensor)&lt;/code&gt; 호출 시 CPU 동기화 발생. 학습 루프에서 최소화.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Host-Device 전송 병목&lt;/strong&gt; = CPU 에서 GPU 로 데이터 복사(PCIe 16-64 GB/s)가 병목. DataLoader 의 &lt;code&gt;pin_memory=True&lt;/code&gt;, &lt;code&gt;num_workers&lt;/code&gt; 활용.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AMP 미사용&lt;/strong&gt; = FP32 로 학습 시 Tensor Core 를 사용하지 못함. &lt;code&gt;torch.autocast(&apos;cuda&apos;)&lt;/code&gt; 로 BF16/FP16 전환.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[TPU]] - Google 의 ML 특화 ASIC 비교&lt;/li&gt;
&lt;li&gt;[[systolic-array]] - TPU 의 MXU 와 Tensor Core 비교&lt;/li&gt;
&lt;li&gt;[[simt]] - SIMT 실행 모델 상세&lt;/li&gt;
&lt;li&gt;[[hbm]] - HBM 고대역폭 메모리&lt;/li&gt;
&lt;li&gt;[[distributed-training]] - 멀티 GPU 분산 학습&lt;/li&gt;
&lt;li&gt;[[양자화]] - FP8/INT8 추론으로 Tensor Core 활용 극대화&lt;/li&gt;
&lt;li&gt;[[llm-serving-vllm]] - GPU 에서의 LLM 서빙&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>hardware</category><category>gpu</category><category>cuda</category><category>tensor-core</category><category>simt</category><author>koa (김신건)</author></item><item><title>NPU (Neural Processing Unit): 엣지 AI 칩</title><link>https://shinkeonkim.com/wiki/ml/npu/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/npu/</guid><pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;NPU (Neural Processing Unit)&lt;/strong&gt; 는 모바일/엣지 디바이스용 저전력 AI 가속기. 스마트폰, 노트북, IoT 에 내장되어 온디바이스 AI 추론을 담당한다.&lt;/p&gt;
&lt;p&gt;[[gpu|GPU]] 는 범용 병렬 연산을, [[tpu|TPU]] 는 데이터센터 규모 학습을 처리하는 데 비해, NPU 는 &lt;strong&gt;배터리 구동 장치에서 수 와트 이하&lt;/strong&gt;로 신경망 추론을 실행하는 데 특화된다.&lt;/p&gt;
&lt;h2 id=&quot;언제-쓰이나&quot;&gt;언제 쓰이나&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;스마트폰 실시간 기능&lt;/strong&gt;: 얼굴 인식 (Face ID), 사진 처리 (Portrait mode, Deep Fusion)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;온디바이스 음성 인식&lt;/strong&gt;: Siri, Google Assistant 오프라인 모드&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;온디바이스 LLM&lt;/strong&gt;: Apple Intelligence (iOS 18+), Copilot+ (Windows 11)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;실시간 번역&lt;/strong&gt;: 오프라인 번역 앱&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;헬스케어 센싱&lt;/strong&gt;: 심박, 혈중 산소 모니터링&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자율주행 엣지 유닛&lt;/strong&gt;: 산업용 IoT, 로봇&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;컴퓨트-계층-구조&quot;&gt;컴퓨트 계층 구조&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;클라우드 / 데이터센터&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        GPU[&quot;GPU (H100, A100)\n학습 + 대규모 추론\n300-700W&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        TPU2[&quot;TPU v4/v5\n대규모 Transformer 학습\n170-250W&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;엣지 서버&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        JET[&quot;NVIDIA Jetson\n엣지 서버급 추론\n10-40W&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;모바일 / 온디바이스&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        ANE[&quot;Apple ANE\niPhone, Mac 내장\n1-5W&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        HEX[&quot;Qualcomm Hexagon\nSnapdragon 내장\n1-5W&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        ETpu[&quot;Google Edge TPU\nCoral USB / M.2\n2W&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        INPU[&quot;Intel NPU\nMeteor Lake+\n5-15W&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    GPU --&gt; JET&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    JET --&gt; ANE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    JET --&gt; HEX&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    JET --&gt; INPU&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;npu-아키텍처-특성&quot;&gt;NPU 아키텍처 특성&lt;/h2&gt;
&lt;p&gt;NPU 는 [[gpu|GPU]] 와 같은 범용 병렬 프로세서가 아닌, &lt;strong&gt;신경망 연산 (행렬 곱, 컨볼루션, 활성화 함수) 에 최적화된 고정 파이프라인&lt;/strong&gt; 을 가진다.&lt;/p&gt;
&lt;h3 id=&quot;핵심-특성&quot;&gt;핵심 특성&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;저전력&lt;/strong&gt;: 배터리 구동 (수 W ~ 수십 W)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;정수 연산 위주&lt;/strong&gt;: INT8, INT4 로 추론 최적화 (학습은 FP32/BF16)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;온디바이스 추론&lt;/strong&gt;: 개인정보 보호, 지연시간 낮음, 인터넷 불필요&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;고정 연산 그래프&lt;/strong&gt;: GPU/CPU 처럼 임의 커널을 실행하는 게 아니라, 컴파일된 모델 그래프를 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;int8-추론&quot;&gt;INT8 추론&lt;/h3&gt;
&lt;p&gt;[[quantization|Quantization]] 을 통해 FP32(32비트) 모델 가중치를 INT8(8비트) 로 변환. 메모리 4배 절약, 연산 4-8배 빠름, 정확도 손실은 일반적으로 1% 이내.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;FP32 가중치: [-0.234, 0.891, -1.23, ...]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                    ↓ Post-Training Quantization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;INT8 가중치:  [-30,   114,  -157, ...]  + scale factor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;NPU 는 INT8 행렬 곱 유닛을 하드웨어에 내장해 FP32 대비 에너지 효율이 10배 이상.&lt;/p&gt;
&lt;h2 id=&quot;gpu--cpu--npu-비교&quot;&gt;GPU / CPU / NPU 비교&lt;/h2&gt;





















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;CPU&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;GPU&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;NPU&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;설계 목적&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;범용 순차 연산&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;범용 병렬 연산&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;신경망 추론 특화&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;코어 수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8-128&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;수천~수만&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;수십~수백 (행렬 유닛)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;정밀도&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FP32/INT&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FP16/FP32&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;INT4/INT8&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;전력 소모&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;15-350W&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;100-700W&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1-20W&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;지연시간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;낮음 (단일)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;배치 지향&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;즉각 처리&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;유연성&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;최고&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;높음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;낮음 (고정 연산)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;프로그래밍&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;직접&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;CUDA / OpenCL&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Core ML / ONNX&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;대표-npu&quot;&gt;대표 NPU&lt;/h2&gt;
&lt;h3 id=&quot;apple-neural-engine-ane&quot;&gt;Apple Neural Engine (ANE)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    CPU[&quot;CPU\n(성능 코어)&quot;] --&gt; Dispatch[&quot;OS 디스패처\n(Core ML)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    GPU2[&quot;GPU\n(Metal)&quot;] --&gt; Dispatch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ANE[&quot;Apple ANE&quot;] --&gt; Dispatch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Dispatch --&gt; App[&quot;앱 추론 요청&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Core ML 프레임워크가 모델의 각 연산 레이어를 CPU / GPU / ANE 중 최적 유닛에 자동 분배한다.&lt;/p&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;칩&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;출시&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;TOPS&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;주요 기능&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;A11 Bionic&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2017&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;0.6&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;최초 ANE, Face ID&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;A14 Bionic&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2020&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;11&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;5nm, Neural Engine 16코어&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;A16 Bionic&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2022&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;15.8&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;iPhone 14 Pro&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;A17 Pro&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2023&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;35&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;3nm, iPhone 15 Pro&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;M2&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2022&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;15.8&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Mac, iPad Pro&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;M4&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2024&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;38&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Apple Intelligence 온디바이스 LLM&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;TOPS&lt;/strong&gt; (Tera Operations Per Second): 초당 1조 연산. NPU 성능 측정 단위.&lt;/p&gt;
&lt;p&gt;ANE 는 Core ML 프레임워크를 통해서만 접근 가능하다 (직접 프로그래밍 불가). Apple Intelligence 의 온디바이스 LLM 추론은 ANE + CPU + GPU 를 동시에 활용한다.&lt;/p&gt;
&lt;h3 id=&quot;qualcomm-hexagon-dspnpu&quot;&gt;Qualcomm Hexagon DSP/NPU&lt;/h3&gt;
&lt;p&gt;Snapdragon 8 Gen 시리즈에 내장. Hexagon DSP 위에 HTP (Hexagon Tensor Processor) 가 추가된 구조.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Android 기기 대부분의 NPU 역할&lt;/li&gt;
&lt;li&gt;Qualcomm AI Engine API, ONNX Runtime (QNN 백엔드) 로 접근&lt;/li&gt;
&lt;li&gt;Snapdragon 8 Gen 3: 98 TOPS&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;google-edge-tpu-coral&quot;&gt;Google Edge TPU (Coral)&lt;/h3&gt;
&lt;p&gt;[[tpu|TPU]] 아키텍처를 엣지용으로 축소한 제품. USB Accelerator (2W) 와 M.2 모듈 형태.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TensorFlow Lite 모델만 지원&lt;/li&gt;
&lt;li&gt;단 8MB 온칩 SRAM 으로 모델이 작아야 함 (MobileNet 급)&lt;/li&gt;
&lt;li&gt;라즈베리파이에 USB 로 연결해 추론 보조&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;intel-npu-meteor-lake&quot;&gt;Intel NPU (Meteor Lake+)&lt;/h3&gt;
&lt;p&gt;2024년 출시된 Intel Core Ultra 칩에 내장. 저전력 AI 워크로드를 CPU, GPU 가 아닌 NPU 에 오프로드.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenVINO, ONNX Runtime (OpenVINO 백엔드) 지원&lt;/li&gt;
&lt;li&gt;Microsoft Copilot+ PC 의 요건 (40 TOPS 이상)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;실전-core-ml-로-ane-활용-iosswift&quot;&gt;실전: Core ML 로 ANE 활용 (iOS/Swift)&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; CoreML&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Vision&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 1. 모델 로드 (ANE 자동 활용)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; config &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; MLModelConfiguration&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;config.computeUnits &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; .cpuAndNeuralEngine  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// ANE 우선, 폴백은 CPU&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;guard&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; try?&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; MyVisionModel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;configuration&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: config) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;// 2. 이미지 분류 요청&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; request &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; VNCoreMLRequest&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;model&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;VNCoreMLModel&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: model.model)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { request, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    guard&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; request.results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [VNClassificationObservation] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; top &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; results.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;first&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;\(top.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;identifier&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;\(top.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;confidence&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; handler &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; VNImageRequestHandler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ciImage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: ciImage)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;try?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; handler.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;perform&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;([request])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;computeUnits = .cpuAndNeuralEngine&lt;/code&gt; 로 ANE 를 명시하면 Core ML 이 지원되는 레이어를 ANE 로 보낸다. &lt;code&gt;.all&lt;/code&gt; 은 GPU 도 포함.&lt;/p&gt;
&lt;h2 id=&quot;실전-onnx-runtime-으로-npu-활용-python&quot;&gt;실전: ONNX Runtime 으로 NPU 활용 (Python)&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; onnxruntime &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ort&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numpy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Qualcomm NPU (QNN) 또는 Intel NPU (OpenVINO) 백엔드&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;providers &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    (&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;QNNExecutionProvider&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;backend_type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;htp&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}),  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Qualcomm Hexagon&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;CPUExecutionProvider&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 폴백&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;session &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ort.InferenceSession(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;model_int8.onnx&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;providers&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;providers)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;input_name &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; session.get_inputs()[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; session.run(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    None&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {input_name: np.random.randn(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;224&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;224&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).astype(np.float32)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(result[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].argmax())&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;INT8 ONNX 모델을 생성하려면 먼저 [[quantization|Post-Training Quantization]] 으로 변환해야 한다:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; onnxruntime.quantization &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; quantize_dynamic, QuantType&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;quantize_dynamic(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    model_input&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;model_fp32.onnx&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    model_output&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;model_int8.onnx&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    weight_type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;QuantType.QInt8,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;tops-비교-2024-2025-대표-기기&quot;&gt;TOPS 비교 (2024-2025 대표 기기)&lt;/h2&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;기기&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;NPU&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;TOPS&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;출시&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;iPhone 15 Pro&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;A17 Pro ANE&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;35&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2023&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;iPhone 16 Pro&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;A18 Pro ANE&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;38&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2024&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;MacBook Pro M4&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;M4 ANE&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;38&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2024&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Galaxy S24 Ultra&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Snapdragon 8 Gen 3 Hexagon&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;98&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2024&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Microsoft Surface Pro 11&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Snapdragon X Elite XDNA&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;45&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2024&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Lenovo ThinkPad X1 Carbon Gen 13&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Intel Core Ultra 7 NPU&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;47&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2025&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
TOPS 수치는 INT8 기준이 일반적이나, 벤더마다 INT4/INT8/FP16 기준이 달라 단순 비교는 어렵다. 실제 추론 속도는 지원하는 op 범위와 모델 구조에 따라 크게 달라진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;모바일-추론-파이프라인&quot;&gt;모바일 추론 파이프라인&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    M[&quot;학습된 모델\n(FP32)&quot;] --&gt; Q[&quot;Quantization\n(INT8/INT4)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Q --&gt; C[&quot;플랫폼 컴파일\n(Core ML / TFLite / ONNX)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    C --&gt; NPU2[&quot;NPU 실행\n(온디바이스)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    NPU2 --&gt; R[&quot;추론 결과\n(저지연, 오프라인)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    style NPU2 fill:#e8f5e9,stroke:#388e3c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;NPU 는 모든 연산을 가속하지 않는다.&lt;/strong&gt; 지원하지 않는 연산자 (op) 가 있으면 자동으로 CPU 로 폴백된다. 폴백이 많으면 NPU 와 CPU 간 데이터 복사 오버헤드가 오히려 성능을 떨어뜨린다. 반드시 프로파일러로 op 지원 여부를 확인해야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;INT8 Quantization 은 calibration 없이 하면 정확도가 급락한다.&lt;/strong&gt; Weight 만 양자화하는 dynamic quantization 과 달리, static quantization 은 대표 데이터셋으로 activation 분포를 측정하는 calibration 이 필수다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
&lt;strong&gt;NPU API 는 플랫폼 종속이 심하다.&lt;/strong&gt; ANE 는 Core ML 만, Hexagon 은 QNN/ONNX, Edge TPU 는 TFLite 만 지원한다. ONNX 를 중간 포맷으로 쓰면 플랫폼 간 이식이 쉬워진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[tpu|TPU]] - 데이터센터 AI 가속기&lt;/li&gt;
&lt;li&gt;[[gpu|GPU]] - 범용 병렬 가속기&lt;/li&gt;
&lt;li&gt;[[quantization|Quantization]] - INT8/INT4 최적화 기법&lt;/li&gt;
&lt;li&gt;[[federated-learning|Federated Learning]] - 엣지 디바이스 분산 학습&lt;/li&gt;
&lt;li&gt;[[distributed-training|Distributed Training]] - 클라우드 규모 학습&lt;/li&gt;
&lt;li&gt;[[transfer-learning|Transfer Learning]] - 엣지 모델 경량화 기반&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>hardware</category><category>npu</category><category>edge</category><category>inference</category><category>quantization</category><author>koa (김신건)</author></item><item><title>Systolic Array</title><link>https://shinkeonkim.com/wiki/ml/systolic-array/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/systolic-array/</guid><pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Systolic Array&lt;/strong&gt; 는 격자 형태로 배치된 다수의 Processing Element (PE) 가, 입력 데이터가 박동(systolic)처럼 격자를 가로질러 흐르는 동안 각 PE 가 곱셈+누적(MAC) 을 수행하는 하드웨어 구조다.&lt;/p&gt;
&lt;p&gt;H.T. Kung 이 1978년 제안한 개념이며, [[TPU]] 의 핵심 컴퓨팅 단위로 부활했다. TPU 에서는 &lt;strong&gt;MXU (Matrix Multiply Unit)&lt;/strong&gt; 으로 불린다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이름의 유래는 심장 박동(systole): 데이터가 규칙적으로 PE 사이를 리드미컬하게 펌핑하며 이동하는 모습에서 온다.&lt;/p&gt;
&lt;h2 id=&quot;언제-쓰이나&quot;&gt;언제 쓰이나&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;대규모 행렬곱(GEMM) 이 반복적으로 필요한 딥러닝 학습/추론&lt;/li&gt;
&lt;li&gt;전통적인 범용 프로세서(CPU/GPU)로는 메모리 대역폭 병목이 발생하는 상황&lt;/li&gt;
&lt;li&gt;Google TPU, 일부 Edge AI 칩(Google Edge TPU, 삼성 Exynos NPU), FPGA 구현 등&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;systolic-pumping-핵심-동작-원리&quot;&gt;Systolic Pumping: 핵심 동작 원리&lt;/h2&gt;
&lt;p&gt;행렬 곱셈 &lt;code&gt;C = A × B&lt;/code&gt; 의 기본 연산:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;C[i][j] += A[i][k] * B[k][j]   (k = 0 ~ K-1)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Systolic Array 에서는 이 연산을 PE 격자가 담당한다:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;A 행렬 (좌에서 우로 이동)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        a0[&quot;a[0][k]&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        a1[&quot;a[1][k]&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;B 행렬 (위에서 아래로 이동)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        b0[&quot;b[k][0]&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        b1[&quot;b[k][1]&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    a0 --&gt; PE00[&quot;PE(0,0)\nMAC&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    a0 --&gt; PE01[&quot;PE(0,1)\nMAC&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    a1 --&gt; PE10[&quot;PE(1,0)\nMAC&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    a1 --&gt; PE11[&quot;PE(1,1)\nMAC&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    b0 --&gt; PE00&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    b0 --&gt; PE10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    b1 --&gt; PE01&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    b1 --&gt; PE11&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    PE00 --&gt; out00[&quot;C[0][0]&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    PE01 --&gt; out01[&quot;C[0][1]&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    PE10 --&gt; out10[&quot;C[1][0]&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    PE11 --&gt; out11[&quot;C[1][1]&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;각 클럭 사이클마다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A 행렬 원소가 왼쪽에서 오른쪽으로 이동&lt;/li&gt;
&lt;li&gt;B 행렬 원소가 위에서 아래로 이동&lt;/li&gt;
&lt;li&gt;각 PE 가 수신한 두 값을 곱해 누적&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;weight-stationary-vs-output-stationary&quot;&gt;Weight Stationary vs Output Stationary&lt;/h3&gt;
&lt;p&gt;[[TPU]] 는 &lt;strong&gt;Weight Stationary&lt;/strong&gt; 방식을 채택한다.&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;방식&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;정주(고정) 데이터&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;흐름 데이터&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;적합한 상황&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Weight Stationary&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가중치 (B)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;활성화 (A)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;추론, 가중치 재사용&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Output Stationary&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;부분합 출력 (C)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가중치 + 활성화&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;작은 필터 합성곱&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Input Stationary&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;활성화 입력 (A)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가중치&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;모바일 NPU&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;추론 시 가중치는 고정, 입력(활성화)만 바뀌므로 Weight Stationary 가 이상적.&lt;/p&gt;
&lt;h2 id=&quot;3가지-우아함&quot;&gt;3가지 우아함&lt;/h2&gt;
&lt;h3 id=&quot;1-메모리-접근-최소화&quot;&gt;1. 메모리 접근 최소화&lt;/h3&gt;
&lt;p&gt;각 가중치(weight)는 PE 에 한 번 적재 후 수많은 활성화 벡터와의 곱셈에 재사용된다. DRAM/HBM 접근 횟수가 극적으로 줄어든다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;전통 방식: C[i][j] 계산 시마다 A[i][k], B[k][j] 메모리 로드 → K 번 * M*N 회 = K*M*N 접근&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Systolic:  B 행렬 한 번 적재 → A 원소마다 재사용 → M*N + K*M 회 접근&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-완벽한-데이터-재사용&quot;&gt;2. 완벽한 데이터 재사용&lt;/h3&gt;
&lt;p&gt;한 활성화 값이 PE 배열을 가로질러 이동하면서 N 개의 PE 와 연산. 단 1번 메모리에서 읽어 N 번 사용.&lt;/p&gt;
&lt;h3 id=&quot;3-단순한-제어-회로&quot;&gt;3. 단순한 제어 회로&lt;/h3&gt;
&lt;p&gt;모든 PE 가 동일한 동작(MAC: Multiply-Accumulate) 반복 실행. CPU 의 분기 예측, OoO 실행 등 복잡한 제어 회로가 불필요 → 동일 면적에 훨씬 많은 연산 유닛 배치 가능.&lt;/p&gt;
&lt;h2 id=&quot;google-tpu-mxu-실제-구현&quot;&gt;Google TPU MXU 실제 구현&lt;/h2&gt;
&lt;h3 id=&quot;tpu-내부-아키텍처&quot;&gt;TPU 내부 아키텍처&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    HBM[&quot;HBM (고대역폭 메모리)&quot;] --&gt; UB[&quot;Unified Buffer (on-chip SRAM)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    UB --&gt; WF[&quot;Weight FIFO&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    WF --&gt; MXU[&quot;MXU (Systolic Array)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    MXU --&gt; ACC[&quot;Accumulators (결과 임시 저장)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ACC --&gt; VU[&quot;Vector Unit (softmax, norm, pool 등)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    VU --&gt; UB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    VU --&gt; HBM&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;









































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;세대&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;MXU 크기&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;피크 성능&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;메모리&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;TPU v1&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;256×256&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;92 TOPS (INT8)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;8 GB LPDDR&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;TPU v2&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;128×128 × 2&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;45 TFLOPS (BF16)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;16 GB HBM&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;TPU v3&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;128×128 × 2&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;123 TFLOPS (BF16)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;32 GB HBM&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;TPU v4&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;128×128 × 4&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;275 TFLOPS (BF16)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;32 GB HBM&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;TPU v5e (Trillium)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;-&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~394 TFLOPS (BF16)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;16 GB HBM&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
TPU MXU 는 &lt;strong&gt;BF16 (bfloat16)&lt;/strong&gt; 형식을 사용한다. BF16 은 FP32 와 같은 exponent(8bit) 범위를 유지하면서 mantissa 를 줄여(7bit), 학습 안정성을 보존하면서 메모리 대역폭을 절반으로 줄인다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;unified-buffer-역할&quot;&gt;Unified Buffer 역할&lt;/h3&gt;
&lt;p&gt;MXU 가 쉬지 않고 연산하려면 데이터 공급이 끊기지 않아야 한다. Unified Buffer (on-chip SRAM, 16-128MB) 가 HBM 과 MXU 사이 버퍼 역할을 맡는다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;재사용 계수(reuse factor) = 행렬 차원 N&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;행렬 N=1024 이면: 각 가중치 원소 1024 번 재사용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;→ 효과적인 메모리 대역폭 = HBM 실제 BW × 1024&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;gemm-과-딥러닝-연산-맵핑&quot;&gt;GEMM 과 딥러닝 연산 맵핑&lt;/h2&gt;
&lt;p&gt;딥러닝의 주요 연산은 대부분 GEMM 으로 표현된다:&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;딥러닝 연산&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;GEMM 형태&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;비고&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;nn.Linear(in, out)&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;[B, in] × [in, out]&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가장 기본&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Attention &lt;code&gt;Q @ K.T&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;[B*H, seq, d] × [B*H, d, seq]&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;배치 GEMM&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Conv2d (im2col)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;[B*OH*OW, IC*KH*KW] × [IC*KH*KW, OC]&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;변환 필요&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;LayerNorm, Softmax&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;GEMM 아님&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Vector Unit 에서 처리&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;tiling-전략&quot;&gt;Tiling 전략&lt;/h3&gt;
&lt;p&gt;MXU 가 128×128 이고 행렬이 1024×1024 라면 &lt;em&gt;타일링&lt;/em&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;A[1024×1024] = 8×8 타일 (각 128×128)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;B[1024×1024] = 8×8 타일&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;C[i][j] = sum over k { A_tile[i][k] × B_tile[k][j] }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;XLA 컴파일러가 타일링 크기를 자동 결정하므로 수동 지정 불필요.&lt;/p&gt;
&lt;h2 id=&quot;cpu--gpu-와-비교&quot;&gt;CPU / GPU 와 비교&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;CPU (범용)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        c1[&quot;DRAM&quot;] --&gt; c2[&quot;L3/L2/L1 Cache&quot;] --&gt; c3[&quot;복잡 ALU\n분기, OoO 실행&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;GPU (SIMT)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        g1[&quot;HBM&quot;] --&gt; g2[&quot;L2/L1 Cache&quot;] --&gt; g3[&quot;CUDA 코어 / Tensor Core\n(Warp 32 스레드)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;TPU (Systolic)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        t1[&quot;HBM&quot;] --&gt; t2[&quot;Unified Buffer\n(on-chip SRAM)&quot;] --&gt; t3[&quot;MXU (PE 격자)\n단순 MAC 반복&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;









































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;CPU&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;GPU (H100)&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;TPU v4&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;피크 컴퓨트 (BF16)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~2 TFLOPS&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1,979 TFLOPS&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;275 TFLOPS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;메모리 대역폭&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~100 GB/s&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;3.35 TB/s&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1.2 TB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;제어 회로 비중&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;매우 높음&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;중간&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;낮음&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;범용성&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;최고&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;높음&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;ML 특화&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;실제 MFU&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~5%&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;30-50%&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;60-70%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;MFU (Model FLOP Utilization): 이론 피크 대비 실제 활용률. TPU MFU 가 GPU 보다 높다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;실전-xla--jax-로-mxu-최대-활용&quot;&gt;실전: XLA + JAX 로 MXU 최대 활용&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.numpy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jnp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; functools &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; partial&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# XLA jit 컴파일: TPU에서 MXU 타일링 자동 최적화&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@partial&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(jax.jit, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;backend&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tpu&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; matmul&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(a: jnp.ndarray, b: jnp.ndarray) -&gt; jnp.ndarray:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jnp.dot(a, b)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 배치 행렬곱 (vmap으로 자동 벡터화)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@jax.jit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; batched_matmul&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(a, b):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.vmap(jnp.dot)(a, b)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Transformer 셀프 어텐션 (MXU 에 최적화된 einsum)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; scaled_dot_product_attention&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(q, k, v, scale):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # q, k, v: [batch, heads, seq, dim]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    scores &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jnp.einsum(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;bhid,bhjd-&gt;bhij&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, q, k) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; scale&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    weights &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.nn.softmax(scores, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;axis&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jnp.einsum(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;bhij,bhjd-&gt;bhid&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, weights, v)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;XLA 가 &lt;code&gt;jnp.dot&lt;/code&gt;, &lt;code&gt;jnp.einsum&lt;/code&gt; 을 HLO (High-Level Optimizer IR) 로 낮추고, MXU 크기에 맞는 타일을 생성한다.&lt;/p&gt;
&lt;h3 id=&quot;배치-크기-권장&quot;&gt;배치 크기 권장&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;MXU 효율 극대화: seq_len, hidden_dim 등이 128(또는 256) 배수여야 함&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;예: hidden_dim=512(ok), 500(비효율), 768(ok)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    batch_size: 8, 16, 32 등 2의 거듭제곱 권장&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;한계&quot;&gt;한계&lt;/h2&gt;
&lt;h3 id=&quot;mxu-크기-미스매치-underutilization&quot;&gt;MXU 크기 미스매치 (Underutilization)&lt;/h3&gt;
&lt;p&gt;MXU 128×128 에 64×64 행렬을 넣으면:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;실제 연산: 64 × 64 = 4,096 MAC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;MXU 최대: 128 × 128 = 16,384 MAC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;활용률: 25%&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;회피 전략&lt;/strong&gt;: 배치 크기 늘리기, 행렬 패딩, 모델 차원을 128(또는 256) 배수로 설계.&lt;/p&gt;
&lt;h3 id=&quot;비행렬-연산-병목&quot;&gt;비행렬 연산 병목&lt;/h3&gt;
&lt;p&gt;Softmax, LayerNorm, ReLU 등은 Vector Unit 에서 처리. MXU 와 VU 가 번갈아 작동하면 파이프라인 낭비. Fused kernel (XLA 가 자동) 으로 경감.&lt;/p&gt;
&lt;h3 id=&quot;희소-행렬-비효율&quot;&gt;희소 행렬 비효율&lt;/h3&gt;
&lt;p&gt;대부분 원소가 0인 sparse matrix 에서도 모든 PE 가 쓸모없는 곱셈을 실행. TPU v4+ 에서 SparseCore 별도 추가로 일부 해소.&lt;/p&gt;
&lt;h2 id=&quot;흔한-함정&quot;&gt;흔한 함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;행렬 차원이 MXU 크기 배수 아님&lt;/strong&gt; = 자동 패딩 낭비, 활용률 급락. 모델 설계 시 128/256 배수 권장.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;작은 배치 크기&lt;/strong&gt; = MXU 활용률 급락. 추론 시 배치 큐잉(dynamic batching)으로 보정.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;jit&lt;/code&gt; 없이 실행&lt;/strong&gt; = 각 연산이 개별 커널 실행, XLA 최적화 불가. 반드시 &lt;code&gt;@jax.jit&lt;/code&gt; 적용.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;element-wise 연산 남발&lt;/strong&gt; = Vector Unit 병목으로 MXU idle. XLA 의 op-fusion 에 맡기고 개별 kernel 실행 최소화.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TPU v1 사용 시 INT8 고정&lt;/strong&gt; = 추론 전용, 학습 불가. v2+ 에서 BF16 학습 가능.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[TPU]] - Systolic Array 를 MXU 로 탑재한 Google ASIC&lt;/li&gt;
&lt;li&gt;[[gpu]] - GPU 의 Tensor Core 와 비교&lt;/li&gt;
&lt;li&gt;[[hbm]] - MXU 에 데이터를 공급하는 고대역폭 메모리&lt;/li&gt;
&lt;li&gt;[[simt]] - GPU 의 병렬 실행 모델 (Systolic 과 대비)&lt;/li&gt;
&lt;li&gt;[[distributed-training]] - MXU 다수를 묶어 수천 TPU 로 확장&lt;/li&gt;
&lt;li&gt;[[SPMD]] - TPU 분산 프로그래밍 모델&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>hardware</category><category>tpu</category><category>architecture</category><category>matrix-multiply</category><category>gemm</category><author>koa (김신건)</author></item><item><title>TPU (Tensor Processing Unit): Google 의 ML ASIC</title><link>https://shinkeonkim.com/wiki/ml/tpu/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/tpu/</guid><pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;TPU (Tensor Processing Unit)&lt;/strong&gt; 는 Google 이 딥러닝 워크로드 전용으로 설계한 &lt;strong&gt;ASIC (Application-Specific Integrated Circuit)&lt;/strong&gt;. 2015년 내부 투입, 2017년 ISCA 발표. GPU 처럼 범용 병렬 프로세서가 아닌 &lt;strong&gt;행렬 곱셈 특화&lt;/strong&gt; 가속기.&lt;/p&gt;
&lt;p&gt;핵심 컴퓨팅 단위는 [[systolic-array|Systolic Array]] 기반 &lt;strong&gt;MXU (Matrix Multiply Unit)&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;언제-쓰이나&quot;&gt;언제 쓰이나&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;대규모 Transformer (LLM, Vision Transformer) 학습/추론&lt;/li&gt;
&lt;li&gt;Google Gemini, PaLM, BERT 등 Google 모델 대부분 TPU 에서 학습&lt;/li&gt;
&lt;li&gt;JAX/XLA 스택으로 분산 학습을 구현할 때&lt;/li&gt;
&lt;li&gt;GPU 에 비해 비용 효율($/TFLOPS) 이 중요한 장기 학습&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;핵심-아키텍처&quot;&gt;핵심 아키텍처&lt;/h2&gt;
&lt;h3 id=&quot;mxu-matrix-multiply-unit&quot;&gt;MXU (Matrix Multiply Unit)&lt;/h3&gt;
&lt;p&gt;[[systolic-array|Systolic Array]] 를 이용한 대규모 병렬 행렬곱. 가중치(weight)가 PE 격자에 정주(stationary)하고 활성화(activation)가 격자를 통과하며 MAC 수행.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    HBM[&quot;HBM (고대역폭 메모리)&quot;] --&gt; UB[&quot;Unified Buffer\n(on-chip SRAM 32-128MB)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    UB --&gt; WF[&quot;Weight FIFO&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    WF --&gt; MXU[&quot;MXU (Systolic Array)\nBF16 행렬곱&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    MXU --&gt; ACC[&quot;Accumulators\n(FP32 누적)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ACC --&gt; VU[&quot;Vector Unit\n(softmax, norm, ReLU 등)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    VU --&gt; UB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    UB --&gt; HBM&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;bfloat16&quot;&gt;bfloat16&lt;/h3&gt;
&lt;p&gt;FP32 exponent(8bit) + 축소된 mantissa(7bit). GPU 의 FP16(5+10) 과 달리 FP32 와 exponent 범위 동일 → 오버플로/언더플로 없이 학습 안정성 유지.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;형식&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;exponent&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;mantissa&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;동적 범위&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP32&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;8bit&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;23bit&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FP32&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP16&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;5bit&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;10bit&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;좁음 (오버플로 위험)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;BF16&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;8bit&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;7bit&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FP32 와 동일&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP8 E4M3&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4bit&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;3bit&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;매우 좁음 (추론용)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;세대별-발전&quot;&gt;세대별 발전&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    V1[&quot;TPU v1\n2015\n추론 전용\nINT8&quot;] --&gt; V2[&quot;TPU v2\n2017\n학습 지원\nBF16 + HBM&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    V2 --&gt; V3[&quot;TPU v3\n2018\n액체 냉각\n2x v2&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    V3 --&gt; V4[&quot;TPU v4\n2021\n4096 칩 pod\nOCS 상호연결&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    V4 --&gt; V5[&quot;TPU v5e/p\n2023\n비용/성능 두 트랙&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    V5 --&gt; V6[&quot;Trillium v6\n2024\n5x vs v5e&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;세대별-상세&quot;&gt;세대별 상세&lt;/h3&gt;





































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;세대&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;출시&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;MXU 크기&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;피크 TFLOPS (BF16)&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;HBM&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;특징&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;v1&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2015&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;256×256&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;92 TOPS (INT8)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;없음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;추론 전용, AlphaGo 사용&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;v2&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2017&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;128×128 × 2&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;45 TFLOPS&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;16 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;최초 BF16 학습, HBM 도입&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;v3&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2018&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;128×128 × 2&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;123 TFLOPS&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;32 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;액체 냉각, v2 2배&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;v4&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2021&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;128×128 × 4&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;275 TFLOPS&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;32 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;OCS 광 상호연결, PaLM 학습&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;v5e&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2023&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;-&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~197 TFLOPS&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;16 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;비용 효율 트랙&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;v5p&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2023&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;-&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~459 TFLOPS&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;95 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;성능 트랙&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Trillium (v6)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2024&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;-&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~918 TFLOPS&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;32 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;v5e 대비 4.7x 컴퓨트&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;tpu-pod-수천-칩-연결&quot;&gt;TPU Pod: 수천 칩 연결&lt;/h2&gt;
&lt;p&gt;개별 TPU 칩을 고속 인터커넥트로 묶은 단위. Pod 안에서 칩들이 &lt;strong&gt;dedicated ICI (Inter-Chip Interconnect)&lt;/strong&gt; 로 연결.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;TPU v4 Pod (최대 4096 칩)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        subgraph &quot;Cube 0&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            T00[&quot;TPU 0&quot;] &amp;#x3C;--&gt;|&quot;ICI&quot;| T01[&quot;TPU 1&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            T01 &amp;#x3C;--&gt;|&quot;ICI&quot;| T02[&quot;TPU 2&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            T02 &amp;#x3C;--&gt;|&quot;ICI&quot;| T03[&quot;TPU 3&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        subgraph &quot;Cube 1&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            T10[&quot;TPU 4&quot;] &amp;#x3C;--&gt;|&quot;ICI&quot;| T11[&quot;TPU 5&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            T11 &amp;#x3C;--&gt;|&quot;ICI&quot;| T12[&quot;TPU 6&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        Cube0[&quot;Cube 0&quot;] &amp;#x3C;--&gt;|&quot;OCS (광 스위치)&quot;| Cube1[&quot;Cube 1&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;TPU v4 Pod 의 혁신: &lt;strong&gt;OCS (Optical Circuit Switch)&lt;/strong&gt; 로 수백~수천 칩을 유연하게 연결. 임의의 topology 구성 가능.&lt;/p&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Pod 크기&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;칩 수&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;피크 성능&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;TPU v4 슬라이스&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;8~512&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;수십 petaFLOPS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;TPU v4 Pod&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4096&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;~1 exaFLOPS&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;xla-컴파일러가-mxu-를-최대한-활용&quot;&gt;XLA: 컴파일러가 MXU 를 최대한 활용&lt;/h2&gt;
&lt;p&gt;TPU 는 &lt;strong&gt;XLA (Accelerated Linear Algebra)&lt;/strong&gt; 컴파일러 없이는 제 성능이 나오지 않는다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    JAX[&quot;JAX / TF / PyTorch/XLA\n(Python 코드)&quot;] --&gt; HLO[&quot;HLO\n(High-Level Optimizer IR)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    HLO --&gt; OPT[&quot;최적화 패스\n(fusion, tiling, layout)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    OPT --&gt; LLO[&quot;LLO\n(Low-Level Optimizer)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    LLO --&gt; TPU[&quot;TPU HW 커널\n(MXU + VU 명령)&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;XLA 가 자동으로 수행하는 최적화:&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;최적화&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;효과&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Op fusion&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;softmax = exp + sum + div → 단일 커널&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Tiling&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;행렬을 MXU 크기에 맞게 분할&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Layout optimization&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;메모리 레이아웃을 MXU 친화적으로 전환&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Rematerialization&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;activation checkpoint (메모리/컴퓨트 트레이드오프)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;SPMD partitioning&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;분산 학습 자동 샤딩&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;실전-jax-로-tpu-활용&quot;&gt;실전: JAX 로 TPU 활용&lt;/h2&gt;
&lt;h3 id=&quot;기본-설정&quot;&gt;기본 설정&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.numpy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jnp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 사용 가능한 TPU 장치 확인&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;devices &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.devices(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;tpu&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;TPU 장치 수: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(devices)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# jit 컴파일: XLA 가 MXU 최적화 적용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@jax.jit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; linear&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(weights, x):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jnp.dot(x, weights)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# BF16 명시 사용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jnp.ones((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1024&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;512&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;dtype&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jnp.bfloat16)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;W &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jnp.ones((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;512&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;256&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;dtype&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jnp.bfloat16)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linear(W, x)  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# [1024, 256] BF16&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;분산-학습-pmap--pjit&quot;&gt;분산 학습 (pmap / pjit)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.experimental &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mesh_utils&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.sharding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Mesh, PartitionSpec, NamedSharding&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# TPU Pod: 64 칩을 8x8 mesh 로 배치&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;devices &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mesh_utils.create_device_mesh((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mesh &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Mesh(devices, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;axis_names&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;data&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;model&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 가중치 모델 병렬, 배치 데이터 병렬 샤딩&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;weight_sharding &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; NamedSharding(mesh, PartitionSpec(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;model&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;None&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data_sharding   &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; NamedSharding(mesh, PartitionSpec(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;data&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;None&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;@jax.jit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; train_step&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(state, batch):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    # pjit 내부에서 자동 collective (all-reduce, all-gather)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    loss, grads &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; jax.value_and_grad(loss_fn)(state.params, batch)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; state.apply_gradients(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;grads&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grads), loss&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;flax-모델-정의&quot;&gt;Flax 모델 정의&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; flax &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linen &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; TransformerBlock&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;nn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Module&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    hidden: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    heads: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    @nn.compact&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; __call__&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, x):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # 모든 dot/matmul 이 XLA 에 의해 MXU 최적화됨&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        attn_out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nn.MultiHeadDotProductAttention(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;            num_heads&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.heads&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        )(x, x)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nn.LayerNorm()(x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; attn_out)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        mlp_out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nn.Dense(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.hidden &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(x)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        mlp_out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nn.gelu(mlp_out)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        mlp_out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nn.Dense(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.hidden)(mlp_out)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nn.LayerNorm()(x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mlp_out)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;gpu-와-비교&quot;&gt;GPU 와 비교&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;GPU (H100)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        g1[&quot;HBM 80GB\n3.35 TB/s&quot;] --&gt; g2[&quot;L2 Cache 50MB&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        g2 --&gt; g3[&quot;132 SM\n각 128 CUDA + 4 Tensor Core&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        g3 --&gt; g4[&quot;CUDA / cuDNN\n광범위한 생태계&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph &quot;TPU (v4)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        t1[&quot;HBM 32GB\n1.2 TB/s&quot;] --&gt; t2[&quot;Unified Buffer 32MB&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        t2 --&gt; t3[&quot;MXU 4개\n(Systolic Array)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        t3 --&gt; t4[&quot;XLA 컴파일\nJAX / TF / PyTorch/XLA&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;항목&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;GPU (H100)&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;TPU v4&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;피크 TFLOPS (BF16)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1,979&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;275 (칩당)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;MFU (실제 활용률)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;30-50%&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;60-70%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;메모리 대역폭&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;3.35 TB/s&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1.2 TB/s&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;소프트웨어&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;CUDA (광범위)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;XLA 중심&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;병렬 실행 모델&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SIMT (warp 32T)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Systolic Array&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;지연시간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;낮음 (스트리밍)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;배치 지향&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;접근성&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;AWS, Azure, GCP, on-prem&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;GCP TPU 만&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;유연성&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;높음 (그래픽, HPC 포함)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;ML 특화&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
H100 의 피크 TFLOPS 가 훨씬 높지만, MFU 를 감안하면 실효 성능 차는 크게 줄어든다. TPU 는 행렬 연산에서 효율이 매우 높고, Pod 로 묶으면 H100 클러스터보다 통신 대역폭이 유리하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;한계&quot;&gt;한계&lt;/h2&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;한계&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;상세&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;GCP 한정&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;AWS, Azure, on-prem 불가. 벤더 종속&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;CUDA 생태계 없음&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PyTorch CUDA 확장 직접 사용 불가. XLA 기반 재작성 필요&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;동적 shape 비효율&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;XLA 는 shape 별 재컴파일. 가변 길이 시퀀스 처리 까다로움&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;디버깅 어려움&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;JIT 컴파일 후 실행 → 스택 트레이스 추적 복잡&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;소형 모델&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;작은 모델/배치에서는 GPU 가 오히려 빠름&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;흔한-함정&quot;&gt;흔한 함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;jax.jit&lt;/code&gt; 없이 실행&lt;/strong&gt; = Python 레벨 eager 실행, MXU 최적화 전혀 없음. 항상 &lt;code&gt;@jax.jit&lt;/code&gt; 필수.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;행렬 차원이 128 배수 아님&lt;/strong&gt; = MXU padding 낭비. hidden_dim, intermediate 크기를 128 배수로.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;동적 shape 남발&lt;/strong&gt; = 매번 재컴파일 발생. 고정 shape 또는 &lt;code&gt;jax.vmap&lt;/code&gt; + padding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HBM 부족 무시&lt;/strong&gt; = TPU v4 HBM 32GB. 큰 모델은 분산 샤딩 (tensor/pipeline parallelism) 필수.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PyTorch 습관 그대로&lt;/strong&gt; = TPU 에서 &lt;code&gt;.cuda()&lt;/code&gt; 대신 &lt;code&gt;jax.device_put(x, devices[0])&lt;/code&gt; 사용.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[systolic-array]] - TPU 의 핵심 컴퓨팅 유닛&lt;/li&gt;
&lt;li&gt;[[gpu]] - GPU 와 비교&lt;/li&gt;
&lt;li&gt;[[hbm]] - HBM 메모리 (TPU/GPU 공통)&lt;/li&gt;
&lt;li&gt;[[distributed-training]] - TPU Pod 를 활용한 분산 학습&lt;/li&gt;
&lt;li&gt;[[SPMD]] - JAX/XLA 분산 학습 모델&lt;/li&gt;
&lt;li&gt;[[양자화]] - FP8/INT8 추론 (TPU v5+ 지원)&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>hardware</category><category>tpu</category><category>google</category><category>asic</category><category>xla</category><author>koa (김신건)</author></item><item><title>[FL] FedAvg (Federated Averaging)</title><link>https://shinkeonkim.com/wiki/ml/fedavg/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/fedavg/</guid><pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;FedAvg (Federated Averaging)&lt;/strong&gt; 는 McMahan et al. (2017) 이 제안한 &lt;strong&gt;연합 학습의 기본 알고리즘&lt;/strong&gt; 입니다. 원본 데이터를 중앙 서버로 보내지 않고 각 클라이언트가 로컬 데이터로 모델을 학습한 뒤 &lt;strong&gt;weight 을 가중 평균&lt;/strong&gt; 하여 글로벌 모델을 갱신합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“local 여러 step, 서버 평균 한 번”&lt;/strong&gt; 이라는 단순 구조로 FedSGD 대비 통신 라운드 수를 10-100 배 줄여, 실용적 연합 학습의 문을 열었습니다.&lt;/p&gt;
&lt;h2 id=&quot;fedsgd-와의-차이&quot;&gt;FedSGD 와의 차이&lt;/h2&gt;
&lt;h3 id=&quot;fedsgd-naive-baseline&quot;&gt;FedSGD (naive baseline)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;각 라운드에서 클라이언트가 &lt;strong&gt;1 step gradient&lt;/strong&gt; 만 계산해 서버로 전송&lt;/li&gt;
&lt;li&gt;서버가 gradient 를 평균해 global weight 갱신&lt;/li&gt;
&lt;li&gt;각 SGD step 마다 통신 -&gt; &lt;strong&gt;매우 비효율&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;fedavg-핵심-개선&quot;&gt;FedAvg (핵심 개선)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;각 클라이언트가 &lt;strong&gt;로컬에서 여러 epoch 을 돌리고&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;최종 weight 를 서버에 전송&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;서버는 &lt;strong&gt;weight 을 가중 평균&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;한 라운드에 로컬 여러 step 이 들어가므로 통신 횟수 대폭 감소&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;핵심 통찰&lt;/strong&gt;: 데이터가 IID 에 가깝다면 로컬 여러 step 이 낭비가 아니라 이득 (서버 라운드 = 통신 = 병목이므로).&lt;/p&gt;
&lt;h2 id=&quot;알고리즘&quot;&gt;알고리즘&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Server&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Initialize w_0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;For each round t = 0, 1, 2, ...:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    S_t = random subset of K clients (fraction C of N clients)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    For each client k in S_t (in parallel):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        w_k^{t+1} = ClientUpdate(k, w_t)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    w_{t+1} = sum over k in S_t of (n_k / n) * w_k^{t+1}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt; (&lt;code&gt;ClientUpdate(k, w)&lt;/code&gt;):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Split D_k into batches of size B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;For each local epoch e = 1..E:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    For each batch b:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        w &amp;#x3C;- w - eta * grad_l(w; b)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Return w&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;하이퍼파라미터&quot;&gt;하이퍼파라미터&lt;/h3&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;기호&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;의미&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;관용 값&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;$N$&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;전체 클라이언트 수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;100 ~ 10^6+ (cross-device)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;$C$&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;라운드당 참여 fraction&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;0.001 ~ 0.1 (cross-device), 1.0 (cross-silo)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;$K$&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;라운드당 실제 참여 클라이언트 수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;$C \cdot N$&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;$E$&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 epoch 수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1 ~ 20&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;$B$&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 minibatch 크기&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;10 ~ 200&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;$\eta$&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 learning rate&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;0.001 ~ 0.1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;$T$&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;총 라운드 수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;수백 ~ 수만&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;서버-집계-공식&quot;&gt;서버 집계 공식&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;가중 평균 (weighted average)&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;$$
w_{t+1} = \sum_{k \in S_t} \frac{n_k}{n} \cdot w_k^{t+1}
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$n_k$: 클라이언트 $k$ 의 데이터 개수&lt;/li&gt;
&lt;li&gt;$n = \sum_{k \in S_t} n_k$: 이번 라운드 참여 클라이언트 총 데이터 개수&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;왜 개수 비율로 가중&lt;/strong&gt;: 데이터가 많은 클라이언트의 로컬 optimum 이 실제 loss 표면에 대해 더 많은 정보를 담고 있다고 가정 (empirical risk minimization 관점의 자연스러운 가중).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;주의&lt;/strong&gt;: 이 가중은 &lt;strong&gt;개수 편향&lt;/strong&gt; 을 유발할 수 있습니다. 대형 클라이언트가 지배적이면 소수 클라이언트의 분포가 무시됩니다. 문제가 있으면 uniform 또는 클래스 균형 가중으로 대체.&lt;/p&gt;
&lt;h2 id=&quot;왜-로컬-여러-epoch-이-통하는가&quot;&gt;왜 로컬 여러 epoch 이 통하는가&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;IID 데이터&lt;/strong&gt; (모든 클라이언트가 같은 분포에서 샘플링) 라면 각 클라이언트의 로컬 optimum 이 글로벌 optimum 과 근접합니다. 여러 step 이 낭비가 아니라 서버 라운드 사이의 진전.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Non-IID&lt;/strong&gt; 라면 각 클라이언트가 자기 로컬 optimum 으로 수렴하려 하고, 서로 다른 방향으로 이동합니다 (client drift). 평균이 잘못된 방향으로 이동해 수렴 속도 저하 또는 성능 하락. 이 문제는 [[fl-non-iid|FL Non-IID]] 위키에서 상세 다룹니다.&lt;/p&gt;
&lt;h2 id=&quot;convergence-이론&quot;&gt;Convergence 이론&lt;/h2&gt;
&lt;p&gt;Li et al. (2019) “On the Convergence of FedAvg on Non-IID Data” 는 convex loss 가정 하에 다음을 보였습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IID + full participation&lt;/strong&gt;: FedSGD 와 유사한 rate 로 수렴&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-IID + partial participation&lt;/strong&gt;: &lt;strong&gt;decay learning rate&lt;/strong&gt; 가 필요, 아니면 수렴하지 않을 수 있음&lt;/li&gt;
&lt;li&gt;통신 라운드 $T$ 관점에서 $O(1/T)$ (strongly convex), $O(1/\sqrt{T})$ (convex)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Non-convex (딥러닝) 는 정확한 이론이 없고 &lt;strong&gt;empirical validation&lt;/strong&gt; 에 의존합니다.&lt;/p&gt;
&lt;h2 id=&quot;fedsgd-로부터의-도출&quot;&gt;FedSGD 로부터의 도출&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;E = 1, B = 무한&lt;/strong&gt; (전체 배치) 이면 FedAvg = FedSGD. 즉 FedSGD 는 FedAvg 의 특수 케이스.&lt;/p&gt;
&lt;p&gt;E 를 늘리면:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;통신 감소 (좋음)&lt;/li&gt;
&lt;li&gt;Client drift 증가 (나쁨, non-IID 에서)&lt;/li&gt;
&lt;li&gt;Batch normalization 통계 로컬 편향 심화&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Sweet spot&lt;/strong&gt;: E = 1-5, B = 클라이언트 데이터의 1/10 정도.&lt;/p&gt;
&lt;h2 id=&quot;통신-비용-분석&quot;&gt;통신 비용 분석&lt;/h2&gt;
&lt;p&gt;한 라운드 통신량:&lt;/p&gt;
&lt;p&gt;$$
\text{총 통신량} = 2 \cdot K \cdot |w|
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;서버 -&gt; 클라이언트: global weight 다운로드&lt;/li&gt;
&lt;li&gt;클라이언트 -&gt; 서버: 로컬 학습 후 weight 업로드&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$|w|$ 는 모델 파라미터 총 크기 (float32 기준 4 bytes/param).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;최적화 방법&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Model compression&lt;/strong&gt;: quantization (8-bit, 4-bit), sparsification (top-k)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Structured updates&lt;/strong&gt;: low-rank, random mask&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FetchSGD&lt;/strong&gt;: Count sketch 로 gradient 압축&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Federated Dropout&lt;/strong&gt;: 부분 모델만 학습/전송&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;배치-정규화의-함정&quot;&gt;배치 정규화의 함정&lt;/h2&gt;
&lt;p&gt;Batch Normalization 은 배치 통계에 의존합니다. 로컬 데이터가 non-IID 이면 로컬 BN 통계가 글로벌 분포를 대표하지 않아 성능 저하.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;해결&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GroupNorm&lt;/strong&gt;: 배치 무관 (BN 대체 자주 사용)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LayerNorm&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FedBN&lt;/strong&gt;: BN 파라미터는 로컬 유지, 다른 파라미터만 aggregate&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;실전-구현-flower&quot;&gt;실전 구현 (Flower)&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; flwr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.utils.data &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DataLoader&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Client&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;client&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NumPyClient&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; __init__&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, model, train_ds, val_ds):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.train_dl &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DataLoader(train_ds, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;batch_size&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;shuffle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.val_dl &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DataLoader(val_ds, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;batch_size&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;64&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; get_parameters&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, config):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [p.detach().cpu().numpy() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.model.parameters()]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; set_parameters&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, parameters):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p, new &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; zip&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.model.parameters(), parameters):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            p.data &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.tensor(new)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, parameters, config):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.set_parameters(parameters)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;        # 로컬 E epoch 학습&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        opt &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.optim.SGD(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.model.parameters(), &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;lr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;config[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;lr&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; epoch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(config[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;local_epochs&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;            for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x, y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.train_dl:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                opt.zero_grad()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                loss &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.model.loss(x, y)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                loss.backward()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                opt.step()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.get_parameters({}),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.train_dl.dataset),  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# n_k, 서버가 가중 평균에 사용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; evaluate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, parameters, config):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.set_parameters(parameters)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        loss, acc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.eval()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(loss), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.val_dl.dataset), {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;acc&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: acc}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 서버&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;strategy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fl.server.strategy.FedAvg(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    fraction_fit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,           &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# C = 0.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    min_fit_clients&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    min_available_clients&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    on_fit_config_fn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=lambda&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rnd: {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;lr&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.01&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;local_epochs&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fl.server.start_server(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    server_address&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0.0.0.0:8080&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    config&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fl.server.ServerConfig(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;num_rounds&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;200&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    strategy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;strategy,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;fedavg-의-개선변형&quot;&gt;FedAvg 의 개선/변형&lt;/h2&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;변형&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;개선점&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedProx&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Non-IID client drift 완화 (proximal term)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;SCAFFOLD&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Control variate 로 drift correction&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedYogi / FedAdam&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;서버측 adaptive optimizer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedNova&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Local step 수 불균형 정규화&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedBN&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Batch Norm 통계 로컬 유지&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Personalized FedAvg&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;클라이언트별 로컬 fine-tuning&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;각 변형은 특정 조건 (non-IID 극심, system heterogeneity 등) 에 특화. 자세한 알고리즘 유도는 원 논문 참조.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;Non-IID 극심&lt;/strong&gt; 하면 FedAvg 자체가 수렴하지 않을 수 있습니다. Learning rate decay + [[fl-non-iid|FedProx/SCAFFOLD]] 등 변형 사용 고려.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;가중 평균의 편향&lt;/strong&gt;. 대형 클라이언트 데이터가 노이즈/편향이면 글로벌 모델이 그 편향을 흡수. Robust aggregation (median, trimmed mean) 을 검토.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;Client dropout&lt;/strong&gt;. 라운드 중 클라이언트가 이탈하면 그 클라이언트의 weight 만 누락 -&gt; 편향. Secure Aggregation 은 dropout 을 threshold secret sharing 으로 처리.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
&lt;strong&gt;BN 통계 문제&lt;/strong&gt;. 딥러닝 모델에 BN 이 있으면 성능 저하 위험. GroupNorm 대체 또는 FedBN 사용.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[federated-learning|Federated Learning]] - 상위 개념&lt;/li&gt;
&lt;li&gt;[[fl-non-iid|Non-IID Data in FL]] - FedAvg 의 주요 한계&lt;/li&gt;
&lt;li&gt;[[secure-aggregation|Secure Aggregation]] - 프라이버시 강화 집계&lt;/li&gt;
&lt;li&gt;[[personalized-fl|Personalized FL]] - Local fine-tuning 결합&lt;/li&gt;
&lt;li&gt;[[fl-frameworks|FL Frameworks]] - Flower/TFF/NVFlare 비교&lt;/li&gt;
&lt;li&gt;[[differential-privacy|Differential Privacy]] - DP-SGD 결합&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>federated-learning</category><category>distributed</category><category>algorithm</category><author>koa (김신건)</author></item><item><title>[FL] Frameworks (Flower, TFF, NVFlare, FATE, PySyft)</title><link>https://shinkeonkim.com/wiki/ml/fl-frameworks/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/fl-frameworks/</guid><pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;연합 학습 프레임워크&lt;/strong&gt; 는 서버-클라이언트 통신, 집계 알고리즘, 프라이버시 도구, 시뮬레이션 환경, 실 배포 인프라를 제공하는 라이브러리/플랫폼입니다. 알고리즘을 직접 구현하지 않고 &lt;strong&gt;자기 모델 학습 로직만 작성&lt;/strong&gt; 하면 프레임워크가 나머지를 담당합니다.&lt;/p&gt;
&lt;p&gt;주요 프레임워크 5개 (Flower, TFF, NVFlare, FATE, PySyft) 와 신진 (FedML, OpenFL) 을 비교합니다.&lt;/p&gt;
&lt;h2 id=&quot;프레임워크-요약-비교&quot;&gt;프레임워크 요약 비교&lt;/h2&gt;




































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;프레임워크&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;개발/유지&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;언어&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;프레임워크 애그노스틱&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;실 배포&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;시뮬레이션&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;프라이버시 도구&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Flower&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Adap (스타트업) + 커뮤니티&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Python&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;✓ (PyTorch/TF/JAX/HF)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SecAgg, DP 통합&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;TFF&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Google&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Python&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;X (TF 위주)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;시뮬레이션 위주&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;매우 강함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함 (Google TFF Analytics)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;NVFlare&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Python&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함 (Clara)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;HE, DP, PSI&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FATE&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;WeBank&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Python + Scala&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;부분&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;매우 강함 (프로덕션)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;HE, MPC 강함&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;PySyft&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;OpenMined&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Python&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;✓ (PyTorch/TF)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;중간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;HE, MPC, DP 통합&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedML&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FedML Inc.&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Python&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;✓&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;통합&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;flower-권장-진입점&quot;&gt;Flower (권장 진입점)&lt;/h2&gt;
&lt;h3 id=&quot;특징&quot;&gt;특징&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;가벼운 API&lt;/strong&gt;, “가장 사용하기 쉬운 FL 프레임워크” 평판&lt;/li&gt;
&lt;li&gt;완전 &lt;strong&gt;프레임워크 애그노스틱&lt;/strong&gt;: PyTorch, TensorFlow, JAX, scikit-learn, HuggingFace 다 붙음&lt;/li&gt;
&lt;li&gt;시뮬레이션과 실 배포가 &lt;strong&gt;같은 코드&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;200+ 학술 논문에 채택, 산업 사례 증가&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;코드-뼈대&quot;&gt;코드 뼈대&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; flwr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; MyClient&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;client&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NumPyClient&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; get_parameters&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, config):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [p.detach().cpu().numpy() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model.parameters()]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; set_parameters&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, parameters):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p, new &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; zip&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(model.parameters(), parameters):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            p.data &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.tensor(new)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, parameters, config):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.set_parameters(parameters)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        train(model, train_loader, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;epochs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;config[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;local_epochs&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.get_parameters({}), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(train_dataset), {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; evaluate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, parameters, config):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.set_parameters(parameters)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        loss, acc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; evaluate(model, val_loader)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(loss), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(val_dataset), {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;accuracy&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: acc}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fl.client.start_numpy_client(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;server_address&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;server:8080&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;client&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;MyClient())&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Server&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;strategy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fl.server.strategy.FedAvg(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    fraction_fit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    min_fit_clients&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    min_available_clients&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    on_fit_config_fn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=lambda&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rnd: {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;local_epochs&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fl.server.start_server(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    server_address&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0.0.0.0:8080&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    config&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fl.server.ServerConfig(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;num_rounds&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;200&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    strategy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;strategy,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;지원-전략&quot;&gt;지원 전략&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;FedAvg&lt;/code&gt;, &lt;code&gt;FedProx&lt;/code&gt;, &lt;code&gt;FedYogi&lt;/code&gt;, &lt;code&gt;FedAdam&lt;/code&gt;, &lt;code&gt;FedAdagrad&lt;/code&gt;, &lt;code&gt;SCAFFOLD&lt;/code&gt;, &lt;code&gt;FedMedian&lt;/code&gt;, &lt;code&gt;Krum&lt;/code&gt;, &lt;code&gt;FaultTolerantFedAvg&lt;/code&gt;, custom strategy 상속.&lt;/p&gt;
&lt;h3 id=&quot;시뮬레이션&quot;&gt;시뮬레이션&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;flwr.simulation.start_simulation&lt;/code&gt; 으로 단일 프로세스에서 수백 클라이언트 병렬 시뮬레이션 (Ray backend). 대규모 시뮬레이션에도 강함.&lt;/p&gt;
&lt;h3 id=&quot;강점&quot;&gt;강점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;진입 장벽 낮음&lt;/li&gt;
&lt;li&gt;프로덕션 배포 (mobile SDK, edge) 사례 다수&lt;/li&gt;
&lt;li&gt;활발한 커뮤니티, 문서 우수&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;약점&quot;&gt;약점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;HE / MPC 는 자체 제공 X, 다른 라이브러리 (CrypTen, TenSEAL) 와 통합 필요&lt;/li&gt;
&lt;li&gt;시각화/모니터링 UI 는 별도 (외부 tool 필요)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tensorflow-federated-tff&quot;&gt;TensorFlow Federated (TFF)&lt;/h2&gt;
&lt;h3 id=&quot;특징-1&quot;&gt;특징&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Google 개발&lt;/strong&gt;, 학술 연구 및 시뮬레이션의 사실상 표준&lt;/li&gt;
&lt;li&gt;두 계층 API: &lt;strong&gt;Federated Core (저수준)&lt;/strong&gt; + &lt;strong&gt;Federated Learning API (고수준)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;TF eager mode + XLA 컴파일, 매우 빠른 시뮬레이션&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Federated Analytics&lt;/strong&gt; (평균, 히스토그램 등 통계 연산도 연합) 강력&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;코드-예시&quot;&gt;코드 예시&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorflow_federated &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tff&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; create_model&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tf.keras.Sequential([&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tf.keras.layers.Dense(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;128&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;activation&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;relu&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        tf.keras.layers.Dense(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; model_fn&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tff.learning.models.from_keras_model(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        create_model(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;        input_spec&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;input_spec,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;        loss&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tf.keras.losses.SparseCategoricalCrossentropy(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;from_logits&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;        metrics&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[tf.keras.metrics.SparseCategoricalAccuracy()],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;trainer &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tff.learning.algorithms.build_weighted_fed_avg(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    model_fn,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    client_optimizer_fn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=lambda&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: tf.keras.optimizers.SGD(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;learning_rate&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.02&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    server_optimizer_fn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=lambda&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: tf.keras.optimizers.SGD(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;learning_rate&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;state &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; trainer.initialize()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; round_num &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NUM_ROUNDS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; trainer.next(state, sampled_client_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    state &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; result.state&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Round &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;round_num&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;result.metrics&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;강점-1&quot;&gt;강점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;시뮬레이션 성능 최상급&lt;/li&gt;
&lt;li&gt;Google Analytics DP 도구 성숙&lt;/li&gt;
&lt;li&gt;TFF Analytics 는 다른 프레임워크에 없는 강점&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;약점-1&quot;&gt;약점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;실 배포 지원 약함&lt;/strong&gt;. 시뮬레이션 편중.&lt;/li&gt;
&lt;li&gt;TF-heavy: PyTorch 사용자에겐 접근성 낮음&lt;/li&gt;
&lt;li&gt;API 학습 곡선 있음 (federated computation, TFF type system)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;결론&lt;/strong&gt;: Google 스타일 연구용. 배포는 다른 프레임워크 병행.&lt;/p&gt;
&lt;h2 id=&quot;nvidia-flare-nvflare&quot;&gt;NVIDIA FLARE (NVFlare)&lt;/h2&gt;
&lt;h3 id=&quot;특징-2&quot;&gt;특징&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cross-silo 프로덕션 지향&lt;/strong&gt;. NVIDIA Clara (의료) 에서 검증&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;워크플로 지향&lt;/strong&gt;: SAG (Scatter and Gather), CyclicController 등 orchestration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;강한 프라이버시 툴&lt;/strong&gt;: HE (TenSEAL), DP, PSI (Private Set Intersection)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;모니터링&lt;/strong&gt; (TensorBoard, MLflow) 통합&lt;/li&gt;
&lt;li&gt;Multi-org deployment (여러 회사가 협력)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;강점-2&quot;&gt;강점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;의료/금융 실 배포 사례 (병원간, 은행간)&lt;/li&gt;
&lt;li&gt;프라이버시 도구 통합 최상급&lt;/li&gt;
&lt;li&gt;Job / workflow 관리 성숙&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;약점-2&quot;&gt;약점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Cross-device (수백만 모바일) 시나리오는 아님&lt;/li&gt;
&lt;li&gt;진입 장벽 (연구자에게는 복잡)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;대표 사용처&lt;/strong&gt;: 다기관 의료 학습, 금융 컨소시엄.&lt;/p&gt;
&lt;h2 id=&quot;fate-federated-ai-technology-enabler&quot;&gt;FATE (Federated AI Technology Enabler)&lt;/h2&gt;
&lt;h3 id=&quot;특징-3&quot;&gt;특징&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;WeBank (중국)&lt;/strong&gt; 주도, cross-silo 산업 배포에서 압도적&lt;/li&gt;
&lt;li&gt;Multi-Party Computation (MPC), Homomorphic Encryption 이 first-class&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FederatedML&lt;/strong&gt;: FL 알고리즘 대규모 라이브러리&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FATEFlow&lt;/strong&gt;: workflow, &lt;strong&gt;FATEBoard&lt;/strong&gt;: 시각화, &lt;strong&gt;FATE-Serving&lt;/strong&gt;: 배포&lt;/li&gt;
&lt;li&gt;스칼라 + 파이썬 + Spark 백엔드로 대규모 데이터에 강함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;강점-3&quot;&gt;강점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MPC/HE 통합이 가장 완성도 높음&lt;/li&gt;
&lt;li&gt;대규모 데이터 (수백 GB+) 처리&lt;/li&gt;
&lt;li&gt;배포 도구 (dashboard, monitoring) 완비&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;약점-3&quot;&gt;약점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;학습 곡선 가파름&lt;/li&gt;
&lt;li&gt;문서 대부분 중국어 (영어 자료 상대적으로 부족)&lt;/li&gt;
&lt;li&gt;스타트업 규모에는 무거움&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;대표 사용처&lt;/strong&gt;: 금융 컨소시엄, 대형 헬스케어.&lt;/p&gt;
&lt;h2 id=&quot;pysyft-openmined&quot;&gt;PySyft (OpenMined)&lt;/h2&gt;
&lt;h3 id=&quot;특징-4&quot;&gt;특징&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;오픈소스 커뮤니티 (OpenMined)&lt;/strong&gt; 주도&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;프라이버시 우선&lt;/strong&gt;: HE, MPC, DP 통합&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PySyft + PyGrid&lt;/strong&gt; 구조: SDK + 서버&lt;/li&gt;
&lt;li&gt;PyTorch, TensorFlow 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;강점-4&quot;&gt;강점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;프라이버시 도구 종합&lt;/li&gt;
&lt;li&gt;활발한 오픈소스 커뮤니티&lt;/li&gt;
&lt;li&gt;교육 리소스 풍부 (강좌, 튜토리얼)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;약점-4&quot;&gt;약점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;아키텍처 변경이 잦아 프로덕션 사용에는 신중 필요&lt;/li&gt;
&lt;li&gt;성능 최적화가 후순위 (연구/교육 편중)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;대표 사용처&lt;/strong&gt;: 프라이버시 연구, 교육.&lt;/p&gt;
&lt;h2 id=&quot;fedml&quot;&gt;FedML&lt;/h2&gt;
&lt;h3 id=&quot;특징-5&quot;&gt;특징&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;FedML Inc.&lt;/strong&gt; 학술 + 산업 겸용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FedML-Nexus AI&lt;/strong&gt;: 학술 실험 + 산업 배포 통합 플랫폼&lt;/li&gt;
&lt;li&gt;다양한 topology (star, ring, hierarchical) 지원&lt;/li&gt;
&lt;li&gt;Cross-silo + cross-device + IoT 모두&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;강점-5&quot;&gt;강점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;다양한 시나리오 커버&lt;/li&gt;
&lt;li&gt;LLM/멀티모달 FL 초기 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;약점-5&quot;&gt;약점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;상대적으로 신생 (2021~), 성숙도 아직&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;프레임워크-선택-가이드&quot;&gt;프레임워크 선택 가이드&lt;/h2&gt;





































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;상황&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;권장&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;학습/연구, 빠른 프로토타입&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Flower&lt;/strong&gt; or &lt;strong&gt;TFF&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;PyTorch 워크로드, 실 배포 계획&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Flower&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Google 스타일 연구, 시뮬레이션 극대화&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;TFF&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;다기관 의료/금융, 프라이버시 필수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;NVFlare&lt;/strong&gt; or &lt;strong&gt;FATE&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;프라이버시 도구 강력&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;PySyft&lt;/strong&gt; or &lt;strong&gt;FATE&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;모바일 SDK, edge&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Flower&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;대규모 산업 배포 (수 GB+ 데이터)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FATE&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;aggregation-알고리즘-지원-공통&quot;&gt;Aggregation 알고리즘 지원 (공통)&lt;/h2&gt;
&lt;p&gt;대부분 프레임워크가 &lt;code&gt;FedAvg&lt;/code&gt;, &lt;code&gt;FedProx&lt;/code&gt;, &lt;code&gt;FedYogi/Adam&lt;/code&gt;, &lt;code&gt;SCAFFOLD&lt;/code&gt;, robust aggregation (Median, Trimmed Mean, Krum) 은 built-in. Personalized FL (pFedMe, Ditto) 은 프레임워크별 지원 편차. Custom strategy 상속으로 대체 가능.&lt;/p&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;시뮬레이션과 실 배포는 다릅니다&lt;/strong&gt;. 시뮬레이션에서 좋은 알고리즘이 실 환경 (네트워크 불안정, 클라이언트 dropout) 에서는 실패할 수 있음. 반드시 실 배포 시나리오 테스트.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;프라이버시 툴은 사용법을 잘못 쓰면 프라이버시가 없습니다&lt;/strong&gt;. DP epsilon, HE parameter 를 이해하지 않고 default 만 쓰면 정량 보장 없음.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;성능 튜닝&lt;/strong&gt;. 프레임워크마다 통신 프로토콜, 직렬화, 배치 처리가 다름. 실 부하 벤치마크 필수.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
&lt;strong&gt;버전 호환성&lt;/strong&gt;. Flower 는 stable API 이지만 TFF/PySyft 는 breaking change 잦음. 프로덕션은 pin 필수.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[federated-learning|Federated Learning]] - 상위 개념&lt;/li&gt;
&lt;li&gt;[[fedavg|FedAvg]] - 대부분 프레임워크의 기본 전략&lt;/li&gt;
&lt;li&gt;[[fl-non-iid|Non-IID Data in FL]] - 알고리즘 선택 배경&lt;/li&gt;
&lt;li&gt;[[secure-aggregation|Secure Aggregation]] - 프레임워크 통합&lt;/li&gt;
&lt;li&gt;[[personalized-fl|Personalized FL]] - 프레임워크별 지원 편차&lt;/li&gt;
&lt;li&gt;[[differential-privacy|Differential Privacy]] - DP 통합&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>federated-learning</category><category>framework</category><category>tooling</category><author>koa (김신건)</author></item><item><title>[FL] Non-IID Data &amp; Client Drift</title><link>https://shinkeonkim.com/wiki/ml/fl-non-iid/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/fl-non-iid/</guid><pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Non-IID data&lt;/strong&gt; 는 연합 학습에서 각 클라이언트의 데이터가 서로 다른 분포에서 추출되는 상황을 말합니다. FedAvg 를 비롯한 대부분 FL 알고리즘의 최대 난관이며, &lt;strong&gt;client drift&lt;/strong&gt; (각 클라이언트가 자기 로컬 optimum 으로 이탈해 평균이 잘못된 방향으로 이동) 를 유발합니다.&lt;/p&gt;
&lt;h2 id=&quot;non-iid-의-유형&quot;&gt;Non-IID 의 유형&lt;/h2&gt;
&lt;p&gt;Kairouz et al. (2021) 서베이 분류:&lt;/p&gt;
&lt;h3 id=&quot;1-feature-distribution-skew-covariate-shift&quot;&gt;1. Feature distribution skew (covariate shift)&lt;/h3&gt;
&lt;p&gt;$P_k(x) \ne P_{k’}(x)$, but $P_k(y|x)$ 는 동일.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;예: 여러 병원의 X-ray 데이터. 라벨 (질병) 규칙은 같지만 촬영 장비/환자군이 달라 이미지 통계가 다름.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-label-distribution-skew-prior-probability-shift&quot;&gt;2. Label distribution skew (prior probability shift)&lt;/h3&gt;
&lt;p&gt;$P_k(y) \ne P_{k’}(y)$, but $P_k(x|y)$ 는 동일.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;예: MNIST 를 100명에게 나눠주되 각자는 특정 숫자 3-4개만 받음. 클래스 사전 분포가 극단적으로 다름.&lt;/li&gt;
&lt;li&gt;실전에서 흔한 유형. 사용자별 관심사 편중.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-same-label-different-features-concept-shift&quot;&gt;3. Same label, different features (concept shift)&lt;/h3&gt;
&lt;p&gt;$P_k(x|y) \ne P_{k’}(x|y)$.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;예: 여러 나라의 “긴급 상황” 라벨 데이터. 라벨은 같지만 특성 분포가 다름.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-same-features-different-label-concept-drift&quot;&gt;4. Same features, different label (concept drift)&lt;/h3&gt;
&lt;p&gt;$P_k(y|x) \ne P_{k’}(y|x)$.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;예: 다국어 감정 분석. 같은 단어가 나라마다 다른 감정.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;5-quantity-skew-unbalancedness&quot;&gt;5. Quantity skew (unbalancedness)&lt;/h3&gt;
&lt;p&gt;$|D_k|$ 가 클라이언트별로 크게 다름. 대형 클라이언트 몇 개가 지배.&lt;/p&gt;
&lt;p&gt;실무에서는 이 유형들이 &lt;strong&gt;혼합&lt;/strong&gt; 되어 나타납니다.&lt;/p&gt;
&lt;h2 id=&quot;non-iid-상황-시각화&quot;&gt;Non-IID 상황 시각화&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph IID[&quot;IID (이상적 분포)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        C1[&quot;클라이언트 A\n클래스 0~9 균등&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        C2[&quot;클라이언트 B\n클래스 0~9 균등&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        C3[&quot;클라이언트 C\n클래스 0~9 균등&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    subgraph NonIID[&quot;Non-IID (Label Skew)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        D1[&quot;클라이언트 A\n클래스 0,1,2 만&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        D2[&quot;클라이언트 B\n클래스 5,6,7 만&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        D3[&quot;클라이언트 C\n클래스 8,9 만&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    IID --&gt;|&quot;FedAvg 잘 수렴&quot;| GoodGlobal[&quot;좋은 글로벌 모델&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    NonIID --&gt;|&quot;client drift 발생&quot;| BadGlobal[&quot;편향된 글로벌 모델&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;client-drift-의-수학적-원인&quot;&gt;Client Drift 의 수학적 원인&lt;/h2&gt;
&lt;p&gt;로컬 objective $F_k(w)$ 는 클라이언트 $k$ 의 로컬 데이터에 대한 손실. 글로벌 objective 는:&lt;/p&gt;
&lt;p&gt;$$
F(w) = \sum_k \frac{n_k}{n} F_k(w)
$$&lt;/p&gt;
&lt;p&gt;로컬 SGD 를 $E$ epoch 돌리면 클라이언트 $k$ 는 $F_k$ 의 로컬 minimum $w_k^*$ 에 접근합니다.&lt;/p&gt;
&lt;p&gt;$$
w_k^{t+1} \approx w_k^* = \arg\min_w F_k(w)
$$&lt;/p&gt;
&lt;p&gt;Non-IID 상황에서 ${w_k^&lt;em&gt;}$ 들은 서로 멀리 흩어져 있고, 그들의 평균은 &lt;em&gt;&lt;em&gt;글로벌 minimum $w^&lt;/em&gt; = \arg\min_w F(w)$ 와 무관&lt;/em&gt;&lt;/em&gt; 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;$$
\sum_k \frac{n_k}{n} w_k^* \not\approx w^*
$$&lt;/p&gt;
&lt;p&gt;이것이 client drift. E 가 클수록 더 심해집니다.&lt;/p&gt;
&lt;h2 id=&quot;완화-전략&quot;&gt;완화 전략&lt;/h2&gt;
&lt;h3 id=&quot;a-reduce-local-computation&quot;&gt;A. Reduce local computation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;E 축소&lt;/strong&gt; (극단적으로는 E=1, 즉 FedSGD): drift 감소, 대신 통신 폭증&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;B 확대&lt;/strong&gt;: 배치를 크게 (분산 감소, 하지만 GPU 메모리 요구 증가)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Trade-off&lt;/strong&gt;: 통신 vs drift.&lt;/p&gt;
&lt;h3 id=&quot;b-proximal-regularization-fedprox&quot;&gt;B. Proximal Regularization (FedProx)&lt;/h3&gt;
&lt;p&gt;Li et al. (2020) 의 &lt;strong&gt;FedProx&lt;/strong&gt; 는 로컬 objective 에 &lt;strong&gt;proximal term&lt;/strong&gt; 을 추가:&lt;/p&gt;
&lt;p&gt;$$
\min_w F_k(w) + \frac{\mu}{2} | w - w_t |^2
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\mu$: 하이퍼파라미터 (0.001 ~ 1)&lt;/li&gt;
&lt;li&gt;로컬 update 가 글로벌 모델에서 멀리 벗어나지 못하도록 제약&lt;/li&gt;
&lt;li&gt;Straggler (느린 클라이언트) 가 partial work 만 해도 안전&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;: 구현 간단 (loss 에 term 하나 추가), FedAvg 대비 안정성 향상.
&lt;strong&gt;Cons&lt;/strong&gt;: $\mu$ 튜닝 필요, drift 를 완전히 없애진 못함.&lt;/p&gt;
&lt;h3 id=&quot;c-control-variate-scaffold&quot;&gt;C. Control Variate (SCAFFOLD)&lt;/h3&gt;
&lt;p&gt;Karimireddy et al. (2020) 의 &lt;strong&gt;SCAFFOLD&lt;/strong&gt; 는 각 클라이언트의 drift 방향을 &lt;strong&gt;control variate&lt;/strong&gt; $c_k$ 로 추적하고 로컬 gradient 에서 빼줍니다.&lt;/p&gt;
&lt;p&gt;로컬 SGD update:&lt;/p&gt;
&lt;p&gt;$$
w \leftarrow w - \eta \left( \nabla F_k(w) - c_k + c \right)
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$c_k$: 클라이언트 $k$ 의 로컬 correction (drift 방향)&lt;/li&gt;
&lt;li&gt;$c$: 서버 correction (모든 클라이언트 평균)&lt;/li&gt;
&lt;li&gt;$c_k - c$: “이 클라이언트가 평균보다 얼마나 편향된가”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;라운드 종료 시 $c_k$ 를 업데이트하고 서버가 $c$ 를 재집계.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;: 이론적으로 IID 급 수렴 rate 회복.
&lt;strong&gt;Cons&lt;/strong&gt;: 통신량 2배 (weight + control variate 모두 전송), 메모리 2배.&lt;/p&gt;
&lt;h3 id=&quot;d-objective-consistency-fednova&quot;&gt;D. Objective Consistency (FedNova)&lt;/h3&gt;
&lt;p&gt;Wang et al. (2020) 의 &lt;strong&gt;FedNova&lt;/strong&gt; 는 각 클라이언트의 로컬 step 수 $\tau_k$ 가 다를 때 정규화. FedAvg 는 클라이언트별로 step 수가 달라도 그냥 평균하지만, 이는 objective inconsistency 를 야기.&lt;/p&gt;
&lt;p&gt;FedNova 는 normalized gradient 를 집계:&lt;/p&gt;
&lt;p&gt;$$
w_{t+1} = w_t - \tau_{\text{eff}} \cdot \sum_k \frac{n_k}{n} \cdot \frac{d_k}{\tau_k}
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$d_k = w_t - w_k^{t+1}$: 클라이언트 $k$ 의 delta&lt;/li&gt;
&lt;li&gt;$\tau_k$: 클라이언트 $k$ 의 로컬 step 수&lt;/li&gt;
&lt;li&gt;$\tau_{\text{eff}}$: 유효 step 수 (스케일 조정)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;특히 system heterogeneity (느린/빠른 클라이언트 혼재) 상황에 강함.&lt;/p&gt;
&lt;h3 id=&quot;e-server-side-adaptive-optimizer&quot;&gt;E. Server-side adaptive optimizer&lt;/h3&gt;
&lt;p&gt;Reddi et al. (2020) 의 &lt;strong&gt;FedAdam, FedYogi, FedAdagrad&lt;/strong&gt;. 서버에서 pseudo-gradient $\Delta_t = w_t - w_{t+1}^{\text{avg}}$ 를 Adam/Yogi/Adagrad 로 적용.&lt;/p&gt;
&lt;p&gt;$$
w_{t+1} = w_t - \eta \cdot \text{AdamUpdate}(\Delta_t)
$$&lt;/p&gt;
&lt;p&gt;Non-IID 하에서 학습 안정성 향상.&lt;/p&gt;
&lt;h3 id=&quot;f-data-augmentation--mixup&quot;&gt;F. Data augmentation / Mixup&lt;/h3&gt;
&lt;p&gt;클라이언트가 로컬에서 data augmentation 을 강하게 하면 로컬 분포가 완화되어 drift 감소. Mixup, CutMix, RandAugment 등이 흔히 결합.&lt;/p&gt;
&lt;h3 id=&quot;g-personalization-개인화&quot;&gt;G. Personalization (개인화)&lt;/h3&gt;
&lt;p&gt;Non-IID 를 &lt;strong&gt;없애려 하지 말고&lt;/strong&gt; 각 클라이언트가 자기 분포에 맞게 개인화 모델을 갖도록 함. 자세한 것은 [[personalized-fl|Personalized FL]] 참조.&lt;/p&gt;
&lt;h2 id=&quot;벤치마크-데이터셋&quot;&gt;벤치마크 데이터셋&lt;/h2&gt;
&lt;p&gt;Non-IID FL 연구에 자주 쓰이는:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Federated MNIST / FEMNIST&lt;/strong&gt;: 필기 데이터를 작가별로 자연 분할&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Federated CIFAR-10 (Dirichlet split)&lt;/strong&gt;: Dirichlet 파라미터 $\alpha$ 로 non-IID 정도 조절&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shakespeare&lt;/strong&gt;: 극중 인물별 대사, 언어 모델링&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;StackOverflow&lt;/strong&gt;: 사용자별 질문/답변&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;iNaturalist&lt;/strong&gt;: 지역별 야생동물 이미지&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reddit&lt;/strong&gt;: user별 댓글&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Dirichlet split&lt;/strong&gt;: 라벨 $y$ 의 클라이언트 분포를 $\text{Dir}(\alpha)$ 로 샘플. $\alpha$ 가 작을수록 극단적 non-IID.&lt;/p&gt;
&lt;h2 id=&quot;batchnorm-특별-주의-fedbn&quot;&gt;BatchNorm 특별 주의 (FedBN)&lt;/h2&gt;
&lt;p&gt;Non-IID 에서 Batch Normalization 은 특히 취약합니다. 각 클라이언트의 배치 통계 (mean, variance) 가 달라서 글로벌 집계 후 BN 레이어가 “틀린 통계” 로 추론합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;해결책&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;FedBN&lt;/strong&gt; (Li et al., 2021): BN 레이어는 집계하지 않고 각 클라이언트에서 로컬 통계를 유지&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GroupNorm / LayerNorm 대체&lt;/strong&gt;: 배치 통계에 의존하지 않아 Non-IID 에 강함&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;InstanceNorm&lt;/strong&gt;: 각 샘플마다 정규화, 배치 크기에 무관&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;모델 설계 단계에서 FL 을 고려하면 처음부터 GroupNorm 을 쓰는 것이 좋습니다.&lt;/p&gt;
&lt;h2 id=&quot;알고리즘-선택-가이드&quot;&gt;알고리즘 선택 가이드&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Start[&quot;Non-IID 문제 진단&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Start --&gt; Q1{&quot;극심한 label skew?&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Q1 --&gt;|&quot;Yes&quot;| Q2{&quot;통신량 허용 2배?&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Q1 --&gt;|&quot;No&quot;| Q3{&quot;system heterogeneity?&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Q2 --&gt;|&quot;Yes&quot;| SCAFFOLD[&quot;SCAFFOLD&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Q2 --&gt;|&quot;No&quot;| FedProx[&quot;FedProx (mu=0.01~0.1)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Q3 --&gt;|&quot;Yes&quot;| FedNova[&quot;FedNova&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Q3 --&gt;|&quot;No&quot;| Q4{&quot;서버 optimizer 도입?&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Q4 --&gt;|&quot;Yes&quot;| FedAdam[&quot;FedAdam / FedYogi&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Q4 --&gt;|&quot;No&quot;| FedAvg[&quot;FedAvg (E 줄이기)&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    FedProx --&gt; Eval{&quot;클라이언트별 accuracy 편차?&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    FedAvg --&gt; Eval&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Eval --&gt;|&quot;크다&quot;| Personalized[&quot;Personalized FL 검토&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Eval --&gt;|&quot;OK&quot;| Done[&quot;배포&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;





































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;상황&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;권장&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Mild non-IID + IID 근접&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedAvg&lt;/strong&gt; (그대로)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;표준 non-IID (label skew)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedProx&lt;/strong&gt; ($\mu$ = 0.01)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;극심한 drift, 클라이언트 다수&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;SCAFFOLD&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;System heterogeneity (다양한 로컬 step)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedNova&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;서버 최적화 여지&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedAdam / FedYogi&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;BatchNorm 통계 문제&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedBN&lt;/strong&gt; or &lt;strong&gt;GroupNorm&lt;/strong&gt; 대체&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;개인화가 목적&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Personalized FL&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;실험-체크리스트&quot;&gt;실험 체크리스트&lt;/h2&gt;
&lt;p&gt;Non-IID FL 논문/프로젝트에서 반드시 보고해야 하는 항목:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Non-IID 정도 정량화&lt;/strong&gt;: Dirichlet $\alpha$, 클라이언트당 클래스 수, Earth Mover’s Distance 등&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;클라이언트 참여율&lt;/strong&gt;: 라운드당 샘플링 비율 (full participation vs partial participation)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;로컬 epoch E&lt;/strong&gt;: drift 의 직접 파라미터&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;글로벌 accuracy 뿐 아니라 per-client accuracy 분포&lt;/strong&gt;: worst-10% 클라이언트 성능 필수&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;통신 라운드 수 vs 성능&lt;/strong&gt;: 총 통신량 비교 (알고리즘마다 라운드당 비용 다름)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SCAFFOLD 는 통신 2배 반영&lt;/strong&gt;: 단순 accuracy 비교는 불공평&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;Non-IID 를 IID 처럼 다루면 수렴 실패&lt;/strong&gt;. 처음부터 데이터 분포를 EDA 로 파악.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;BN 은 non-IID 에서 특히 취약&lt;/strong&gt;. 로컬 통계가 글로벌 분포를 대표하지 않아 성능 저하. GroupNorm 또는 FedBN 을 첫 손에 검토.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;극심한 non-IID + partial participation 은 이론적 수렴 보장이 약함&lt;/strong&gt;. 실전에서 learning rate decay + warm-up 이 필수.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
&lt;strong&gt;개인화 지표를 평가&lt;/strong&gt;. 글로벌 모델의 accuracy 뿐 아니라 클라이언트별 accuracy 분포도 함께 리포트. 평균은 좋지만 최악의 클라이언트가 안 되면 UX 실패.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;Fairness 함정&lt;/strong&gt;. Non-IID FL 은 소수 그룹 (소량 데이터 클라이언트) 이 대형 클라이언트에 종속될 수 있음. 가중 평균 외에도 min-max fairness (q-FFL 등) 검토.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[federated-learning|Federated Learning]] - 상위 개념&lt;/li&gt;
&lt;li&gt;[[fedavg|FedAvg]] - 기본 알고리즘 (drift 의 배경)&lt;/li&gt;
&lt;li&gt;[[personalized-fl|Personalized FL]] - Drift 대신 개인화&lt;/li&gt;
&lt;li&gt;[[secure-aggregation|Secure Aggregation]] - 프라이버시 강화&lt;/li&gt;
&lt;li&gt;[[differential-privacy|Differential Privacy]] - Non-IID 상 DP 는 특히 어려움&lt;/li&gt;
&lt;li&gt;[[fl-frameworks|FL Frameworks]] - 구현 도구&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>federated-learning</category><category>distributed</category><category>non-iid</category><author>koa (김신건)</author></item><item><title>[FL] Personalized Federated Learning</title><link>https://shinkeonkim.com/wiki/ml/personalized-fl/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/personalized-fl/</guid><pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Personalized FL&lt;/strong&gt; 은 모든 클라이언트가 동일한 글로벌 모델을 쓰지 않고, &lt;strong&gt;각 클라이언트가 자신의 데이터 분포에 맞춰 조정된 모델&lt;/strong&gt; 을 학습하는 연합 학습 계열입니다. Non-IID 극심한 환경에서 글로벌 모델을 억지로 수렴시키는 대신, &lt;strong&gt;자연스러운 이질성을 받아들이고 개인화 성능&lt;/strong&gt; 을 최적화합니다.&lt;/p&gt;
&lt;p&gt;McMahan et al. 의 FedAvg 는 단일 글로벌 모델이 목표였지만, 실전에서 &lt;strong&gt;키보드 (다국어), 추천, 헬스&lt;/strong&gt; 등 사용자별 특성이 강한 도메인에서는 개인화가 필수임을 깨닫게 되었습니다.&lt;/p&gt;
&lt;h2 id=&quot;왜-필요한가&quot;&gt;왜 필요한가&lt;/h2&gt;
&lt;h3 id=&quot;non-iid-의-근본-딜레마&quot;&gt;Non-IID 의 근본 딜레마&lt;/h3&gt;
&lt;p&gt;극심한 non-IID 에서 FedAvg 는 두 가지 문제:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;글로벌 모델 수렴 실패&lt;/strong&gt;: [[fl-non-iid|Client drift]] 로 정확도 저하&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;클라이언트별 fit 부족&lt;/strong&gt;: 수렴해도 각 클라이언트 로컬 분포에는 잘 안 맞음&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Personalized FL 은 문제 2 를 정면 공략. 글로벌 모델을 완전히 포기하지 않고, 각 클라이언트가 그 위에 로컬 조정을 얹습니다.&lt;/p&gt;
&lt;h3 id=&quot;실전-사례&quot;&gt;실전 사례&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Gboard&lt;/strong&gt;: 사용자별 이모지 추천, 단어 예측&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Siri / Google Assistant&lt;/strong&gt;: 음성 명령 개인화&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Netflix / Amazon 추천&lt;/strong&gt;: 사용자별 성향&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;의료 wearable&lt;/strong&gt;: 개인별 정상 baseline&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;헬스케어 fedeated&lt;/strong&gt;: 환자군 특성 반영&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;주요-접근법&quot;&gt;주요 접근법&lt;/h2&gt;
&lt;h3 id=&quot;1-local-fine-tuning-가장-단순&quot;&gt;1. Local Fine-tuning (가장 단순)&lt;/h3&gt;
&lt;p&gt;Global model 학습 후 클라이언트가 &lt;strong&gt;로컬 데이터로 몇 step fine-tune&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;w_local &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w_global.copy()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; step &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(local_steps):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    x, y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; local_batch()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w_local &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w_local &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; eta &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; grad(loss(w_local, x, y))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Trade-off:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;간단, 파라미터 추가 없음&lt;/li&gt;
&lt;li&gt;하지만 언제 stop 할지 (overfit vs underfit) 결정 어려움&lt;/li&gt;
&lt;li&gt;각 클라이언트가 개별 모델 저장 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-personalization-layers-fedper-lg-fedavg&quot;&gt;2. Personalization Layers (FedPer, LG-FedAvg)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;공유 부분&lt;/strong&gt; (representation extractor) + &lt;strong&gt;개인 부분&lt;/strong&gt; (classifier head) 로 분리:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;서버가 학습하는 부분: representation (conv/transformer body)&lt;/li&gt;
&lt;li&gt;클라이언트가 로컬에 유지: personalization head (fully connected + softmax)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Global: [Body: shared conv/transformer]  → aggregated&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Local:  [Head: personal FC + softmax]    → kept per client&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;FedPer&lt;/strong&gt; (Arivazhagan et al., 2019): head 만 로컬. &lt;strong&gt;LG-FedAvg&lt;/strong&gt;: 반대로 body 로컬 + head 공유.&lt;/p&gt;
&lt;p&gt;Trade-off:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;명확한 구조 분리, 통신량 감소 (head 안 전송)&lt;/li&gt;
&lt;li&gt;어느 layer 를 로컬로 할지 도메인 지식 필요&lt;/li&gt;
&lt;li&gt;Head 규모가 크면 로컬 학습 데이터 부족 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-meta-learning-per-fedavg&quot;&gt;3. Meta-Learning (Per-FedAvg)&lt;/h3&gt;
&lt;p&gt;Fallah et al. (2020) 은 &lt;strong&gt;MAML (Model-Agnostic Meta-Learning)&lt;/strong&gt; 스타일로 접근. 글로벌 모델이 “&lt;strong&gt;한 step 만 로컬 SGD 를 돌리면 잘 맞도록&lt;/strong&gt;” 학습.&lt;/p&gt;
&lt;p&gt;$$
\min_w F(w) = \sum_k F_k(w - \alpha \nabla F_k(w))
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$w$: meta-parameter (글로벌)&lt;/li&gt;
&lt;li&gt;$w - \alpha \nabla F_k(w)$: 클라이언트 $k$ 가 한 step 학습 후의 로컬 파라미터&lt;/li&gt;
&lt;li&gt;이 로컬 파라미터가 잘 맞도록 $w$ 를 최적화&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;배포 시: 각 클라이언트가 $w$ 를 받아 자기 데이터로 한 step 파인튜닝하면 즉시 개인화.&lt;/p&gt;
&lt;p&gt;Trade-off:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이론적으로 매우 우아&lt;/li&gt;
&lt;li&gt;Second-order gradient (Hessian) 필요 -&gt; 계산 비용&lt;/li&gt;
&lt;li&gt;FOMAML (first-order approximation) 로 완화 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-regularized-local-model-pfedme-ditto&quot;&gt;4. Regularized Local Model (pFedMe, Ditto)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;pFedMe&lt;/strong&gt; (T. Dinh et al., 2020): 각 클라이언트가 로컬 모델 $\theta_k$ 를 유지하되 글로벌 $w$ 근처에 있도록 정규화.&lt;/p&gt;
&lt;p&gt;$$
\min_{\theta_k} F_k(\theta_k) + \frac{\lambda}{2} | \theta_k - w |^2
$$&lt;/p&gt;
&lt;p&gt;$w$ 는 서버에서 aggregated 로컬 모델들. $\lambda$ 큰 -&gt; 글로벌에 가까움 (드리프트 방지). $\lambda$ 작은 -&gt; 개인화 자유.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ditto&lt;/strong&gt; (Li et al., 2021): 유사하지만 &lt;strong&gt;강건성 + 공정성&lt;/strong&gt; 초점. Global + local 이중 objective:&lt;/p&gt;
&lt;p&gt;$$
\text{Global: } \min_w \sum_k F_k(w) \quad
\text{Local: } \min_{\theta_k} F_k(\theta_k) + \frac{\lambda}{2} | \theta_k - w^* |^2
$$&lt;/p&gt;
&lt;p&gt;Byzantine 공격에도 robust. Fair FL 계열의 대표.&lt;/p&gt;
&lt;h3 id=&quot;5-multi-task-learning-mtl&quot;&gt;5. Multi-Task Learning (MTL)&lt;/h3&gt;
&lt;p&gt;각 클라이언트 = 하나의 task. 클라이언트 간 관계 (task graph) 를 학습하며 관련 task 간 정보 공유.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MOCHA&lt;/strong&gt; (Smith et al., 2017): dual formulation, 관계 행렬 학습&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FedMTL&lt;/strong&gt;: 최근 확장&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;6-clustered-fl&quot;&gt;6. Clustered FL&lt;/h3&gt;
&lt;p&gt;극심한 non-IID 에서는 하나의 글로벌 대신 &lt;strong&gt;여러 클러스터 별 모델&lt;/strong&gt;. 유사 클라이언트끼리 같은 클러스터에 배정.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IFCA&lt;/strong&gt; (Ghosh et al., 2020): Iterative Federated Clustering&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HypCluster&lt;/strong&gt;: Hypothesis-based 그룹핑&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Trade-off: 클러스터 수 하이퍼파라미터, 클라이언트가 어느 클러스터 소속인지 privacy 함의.&lt;/p&gt;
&lt;h3 id=&quot;7-mixture-of-experts--adapter&quot;&gt;7. Mixture of Experts / Adapter&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Adapter layer&lt;/strong&gt; 를 로컬로 유지 (LoRA 스타일). 글로벌은 base + shared params. 대형 모델 시대에 자연스러운 확장.&lt;/p&gt;
&lt;h2 id=&quot;알고리즘-비교&quot;&gt;알고리즘 비교&lt;/h2&gt;






















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;방법&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;로컬 저장&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;통신&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;이론&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;대표 논문&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Local Fine-tune&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 모델&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;표준 FedAvg&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;약함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;(Baseline)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedPer&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Head&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Body 만&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;중간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Arivazhagan 2019&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Per-FedAvg (MAML)&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;없음 (배포 시 1-step)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;표준 FedAvg&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함 (meta)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Fallah 2020&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;pFedMe&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 모델&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;표준&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함 (Moreau)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;T. Dinh 2020&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Ditto&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 모델&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;표준 + robust&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함 (fair/robust)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Li 2021&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Clustered&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;클러스터 모델&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;클러스터별&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;중간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Ghosh 2020&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;시각화-개인화-접근법-구조&quot;&gt;시각화: 개인화 접근법 구조&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    G[&quot;글로벌 서버&quot;] --&gt; FA[&quot;FedAvg&amp;#x3C;br/&gt;단일 글로벌&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    G --&gt; FP[&quot;FedPer&amp;#x3C;br/&gt;레이어 분리&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    G --&gt; PF[&quot;Per-FedAvg&amp;#x3C;br/&gt;메타 초기화&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    G --&gt; PM[&quot;pFedMe&amp;#x3C;br/&gt;Moreau 정규화&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    G --&gt; DT[&quot;Ditto&amp;#x3C;br/&gt;공정성 강조&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    FA --&gt; CA[&quot;클라이언트: 동일 모델&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    FP --&gt; CB[&quot;클라이언트: Head 개인화&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    PF --&gt; CC[&quot;클라이언트: 1-step 적응&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    PM --&gt; CD[&quot;클라이언트: 로컬 모델 유지&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    DT --&gt; CD&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;접근법-선택-기준&quot;&gt;접근법 선택 기준&lt;/h2&gt;
&lt;p&gt;데이터, 인프라, 목표에 따라 적합한 방법이 달라진다:&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;조건&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;권장 방법&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;이유&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;신규 프로젝트, 빠른 실험&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Local Fine-tune&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;설정 최소, 기준점 수립&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;모바일 배포, 통신 절약&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedPer&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Head 만 로컬, Body 공유&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;즉시 개인화, MAML 경험 있음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Per-FedAvg&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;배포 후 1-step 으로 즉시 맞춤&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Non-IID 심하고 수렴이 목적&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;pFedMe&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;λ 로 글로벌/개인화 균형 조절&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;공정성, 악의적 클라이언트 우려&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Ditto&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Robust + Fair FL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;클러스터 구조 의심&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Clustered FL&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;분포 유사 그룹끼리 집계&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;대형 모델 기반&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;LoRA / Adapter&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;파라미터 효율 개인화&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;λ-하이퍼파라미터-선택-pfedme-ditto&quot;&gt;λ 하이퍼파라미터 선택 (pFedMe, Ditto)&lt;/h3&gt;
&lt;p&gt;λ 는 글로벌 모델에 얼마나 당겨올지를 결정한다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;λ → ∞&lt;/strong&gt;: 로컬 모델이 글로벌 모델로 수렴. FedAvg 와 동일 효과.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;λ → 0&lt;/strong&gt;: 완전 로컬 학습. 과적합 위험.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;실전 탐색 범위&lt;/strong&gt;: λ ∈ {0.001, 0.01, 0.1, 1, 10} 에서 cross-validation.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# pFedMe 로컬 학습 (단순화)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; local_train&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(w_global, local_data, lam, lr, steps):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    theta &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w_global.clone()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; _ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(steps):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        x, y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sample(local_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        grad &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; compute_grad(theta, x, y)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        reg &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lam &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (theta &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w_global)  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Moreau 정규화 항&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        theta &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; theta &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (grad &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; reg)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; theta&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;fine-tune-step-수-선택-per-fedavg&quot;&gt;Fine-tune step 수 선택 (Per-FedAvg)&lt;/h3&gt;
&lt;p&gt;배포 시 몇 step 을 돌릴지 결정 기준:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1 step&lt;/strong&gt;: 논문 기본값. 계산 빠름. 데이터 적은 클라이언트에 안정적.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;5~10 step&lt;/strong&gt;: 데이터 충분한 클라이언트는 더 많이 적응 가능.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;조기 종료&lt;/strong&gt;: validation loss 모니터링으로 over-adaptation 방지.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;실전&lt;/strong&gt;: 클라이언트별 데이터 크기에 비례한 step 수 적용.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;평가-프로토콜-표준화&quot;&gt;평가 프로토콜 표준화&lt;/h3&gt;
&lt;p&gt;같은 방법도 평가 방식에 따라 숫자가 크게 달라진다. 논문 비교 시 주의:&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;방법&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;평가 시점&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;평가 데이터&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedAvg&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;글로벌 모델로&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;IID test set&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;FedPer&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;개인화 Head 적용 후&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 test set&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Per-FedAvg&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1-step fine-tune 후&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 test set&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;pFedMe / Ditto&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 모델로&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;로컬 test set&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;비교할 때 &lt;strong&gt;항상 동일 프로토콜&lt;/strong&gt; 을 사용해야 한다. 평균 accuracy 만 보면 개인화 이득을 놓친다. per-client 분포 (min, max, std) 도 함께 보고해야 한다.&lt;/p&gt;
&lt;h2 id=&quot;평가-지표&quot;&gt;평가 지표&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;중요&lt;/strong&gt;: Personalized FL 은 글로벌 accuracy 만 보면 오독합니다. 반드시:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Per-client accuracy 분포&lt;/strong&gt;: 평균 + std + 최악 (min)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fairness metric&lt;/strong&gt;: q-FFL, EFL 등&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personalization gain&lt;/strong&gt;: 로컬 fine-tune 후 vs 전&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Communication cost&lt;/strong&gt;: 개인화 부분 저장/전송 비용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;실전-팁&quot;&gt;실전 팁&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;단순부터 시작&lt;/strong&gt;: FedAvg + Local fine-tune 부터. Meta / pFedMe 는 튜닝 부담 큼.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;개인화 부분 크기 신중히&lt;/strong&gt;: Head 만인지 여러 layer 인지가 성능/저장 크게 좌우.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;cold-start client&lt;/strong&gt;: 새 클라이언트는 데이터가 없어 개인화 어려움. Global 만으로 시작 후 시간 지나 개인화.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;개인화 모델 크기&lt;/strong&gt;: 모바일 배포는 로컬 모델 저장 공간 제약. Adapter/LoRA 가 유리.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;평가 데이터&lt;/strong&gt; 도 non-IID 하게: 학습과 동일 분포의 로컬 val set 사용.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;개인화가 항상 이득은 아닙니다.&lt;/strong&gt; Non-IID 가 mild 하면 FedAvg 만으로도 충분. 개인화가 오히려 overfitting 유발 가능.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;개인화 모델의 privacy 함의&lt;/strong&gt;. 개인 모델을 로컬에 저장하면 device 손실 시 개인 정보 유출 위험. 모델 자체가 학습 데이터의 정보를 포함.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;Cold client&lt;/strong&gt;. 데이터가 매우 적은 신규 클라이언트는 개인화가 오히려 성능 저하. Threshold 를 두고 데이터 축적 후 개인화 전환.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
&lt;strong&gt;평가 프로토콜&lt;/strong&gt; 명확히. Meta-learning 계열은 “1-step 후” 평가하고, pFedMe 는 “로컬 학습 완료 후” 평가. 논문 비교 시 프로토콜 통일 필수.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;서버 저장 필요&lt;/strong&gt;: FedPer 등은 서버가 global body 만 저장, but pFedMe 는 사실상 클라이언트 개별 상태 관리. Cross-device 대규모에서는 클라이언트 side 상태 관리가 부담.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[federated-learning|Federated Learning]] - 상위 개념&lt;/li&gt;
&lt;li&gt;[[fedavg|FedAvg]] - 기본 알고리즘 (개인화 대비)&lt;/li&gt;
&lt;li&gt;[[fl-non-iid|Non-IID Data in FL]] - 개인화 동기&lt;/li&gt;
&lt;li&gt;[[transfer-learning|Transfer Learning]] - 파운데이션 모델 + 로컬 fine-tune 개인화의 큰 그림&lt;/li&gt;
&lt;li&gt;[[secure-aggregation|Secure Aggregation]] - 프라이버시 결합&lt;/li&gt;
&lt;li&gt;[[differential-privacy|Differential Privacy]] - 개인화와 DP 는 tension 가짐&lt;/li&gt;
&lt;li&gt;[[fl-frameworks|FL Frameworks]] - 개인화 지원 프레임워크&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>federated-learning</category><category>personalization</category><category>meta-learning</category><author>koa (김신건)</author></item><item><title>[FL] Secure Aggregation</title><link>https://shinkeonkim.com/wiki/ml/secure-aggregation/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/secure-aggregation/</guid><pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Secure Aggregation&lt;/strong&gt; 은 연합 학습 서버가 &lt;strong&gt;개별 클라이언트 업데이트&lt;/strong&gt; 를 보지 못하고 &lt;strong&gt;오직 합 (또는 평균)&lt;/strong&gt; 만 볼 수 있도록 보장하는 암호학 프로토콜입니다. 서버가 honest-but-curious 라도 (프로토콜은 따르지만 학습 데이터를 캐내려 함) 개별 gradient 를 복원할 수 없습니다.&lt;/p&gt;
&lt;p&gt;Bonawitz et al. (2017) 의 논문 “Practical Secure Aggregation” 이 사실상 표준이며, Google 이 실제 Gboard 학습에 배포하면서 실용성이 입증되었습니다.&lt;/p&gt;
&lt;h2 id=&quot;왜-필요한가&quot;&gt;왜 필요한가&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raw 데이터 미공개&lt;/strong&gt; 만으로는 부족합니다. gradient 자체에서 원본이 복원될 수 있습니다 (gradient inversion attack).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Differential Privacy 만으로는&lt;/strong&gt; 개별 값에 노이즈를 크게 넣어야 하고 유용성이 크게 손상됩니다.&lt;/li&gt;
&lt;li&gt;서버가 실제 관측하는 것을 &lt;strong&gt;집계 값&lt;/strong&gt; 으로만 제한하면, 개별 편향 없이 학습 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;위협-모델&quot;&gt;위협 모델&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Honest-but-curious server&lt;/strong&gt;: 프로토콜은 따르지만 로그를 뒤져 개별 값 복원 시도&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Malicious 최대 $t$ 클라이언트&lt;/strong&gt;: 담합 (collusion) 가능. 프로토콜은 이 $t$ 이하 담합 아래 안전&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client dropout&lt;/strong&gt;: 프로토콜 실행 중 이탈 (배터리, 네트워크). 필수 대응&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network eavesdropper&lt;/strong&gt;: 전송 도청. TLS 로 방어 가정&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Non-goals&lt;/strong&gt; (Secure Aggregation 이 해결하지 않는 것):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;집계 결과 자체의 프라이버시: 이는 [[differential-privacy|DP]] 로 별도 처리&lt;/li&gt;
&lt;li&gt;Byzantine robustness (악성 값 주입): 이는 robust aggregation 으로 별도&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;기본-아이디어&quot;&gt;기본 아이디어&lt;/h2&gt;
&lt;p&gt;각 클라이언트 $i$ 의 업데이트 $x_i$ 를 서로 다른 &lt;strong&gt;랜덤 마스크 $m_{ij}$&lt;/strong&gt; 로 감춥니다. 마스크는 &lt;strong&gt;쌍 (i, j) 에 대해 상쇄&lt;/strong&gt; 되도록 설계:&lt;/p&gt;
&lt;p&gt;$$
y_i = x_i + \sum_{j &gt; i} m_{ij} - \sum_{j &amp;#x3C; i} m_{ji} \pmod{R}
$$&lt;/p&gt;
&lt;p&gt;여기서 $m_{ij} = -m_{ji}$ (반대 부호로 상쇄되는 쌍별 마스크).&lt;/p&gt;
&lt;p&gt;서버가 모든 $y_i$ 를 더하면:&lt;/p&gt;
&lt;p&gt;$$
\sum_i y_i = \sum_i x_i + \underbrace{\sum_i \sum_{j &gt; i} m_{ij} - \sum_i \sum_{j &amp;#x3C; i} m_{ji}}_{= 0} = \sum_i x_i
$$&lt;/p&gt;
&lt;p&gt;마스크가 서로 상쇄되어 &lt;strong&gt;합만&lt;/strong&gt; 남습니다. 개별 $x_i$ 는 마스크로 감춰져 있어 서버가 볼 수 없습니다.&lt;/p&gt;
&lt;h2 id=&quot;프로토콜-단계&quot;&gt;프로토콜 단계&lt;/h2&gt;
&lt;p&gt;Bonawitz et al. 의 실제 프로토콜은 4 라운드 구성:&lt;/p&gt;
&lt;h3 id=&quot;round-0-advertise-keys&quot;&gt;Round 0: Advertise Keys&lt;/h3&gt;
&lt;p&gt;각 클라이언트가 &lt;strong&gt;Diffie-Hellman public key&lt;/strong&gt; 두 쌍을 생성해 서버에 전송.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$c_i^{PK}, c_i^{SK}$: 마스크용 shared secret 유도 키&lt;/li&gt;
&lt;li&gt;$s_i^{PK}, s_i^{SK}$: 자기 secret 백업 키&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;round-1-share-keys&quot;&gt;Round 1: Share Keys&lt;/h3&gt;
&lt;p&gt;각 클라이언트가 자기 &lt;strong&gt;secret key&lt;/strong&gt; 를 Shamir’s Secret Sharing 으로 $n$ 조각으로 나눠 다른 $n-1$ 클라이언트에게 분배. 임계값 $t$ 이하 담합으로는 복원 불가.&lt;/p&gt;
&lt;h3 id=&quot;round-2-masked-input-collection&quot;&gt;Round 2: Masked Input Collection&lt;/h3&gt;
&lt;p&gt;각 클라이언트 $i$:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;다른 클라이언트 $j$ 와의 shared secret $s_{ij} = KDF(c_i^{SK} \cdot c_j^{PK})$ 로 pairwise mask $m_{ij}$ 유도 (PRG)&lt;/li&gt;
&lt;li&gt;자기 개인 mask $b_i$ 생성 (자기 secret 로부터)&lt;/li&gt;
&lt;li&gt;마스크된 업데이트 전송:
$$y_i = x_i + \sum_{j &gt; i} m_{ij} - \sum_{j &amp;#x3C; i} m_{ji} + b_i \pmod{R}$$&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;$b_i$ 는 자기 자신만 아는 additional mask, dropout 대응용.&lt;/p&gt;
&lt;h3 id=&quot;round-3-unmasking&quot;&gt;Round 3: Unmasking&lt;/h3&gt;
&lt;p&gt;서버는 살아남은 클라이언트 집합 $U$ 를 확정. 살아남은 클라이언트는:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$j \in U$ 라면: $b_j$ 를 자기 secret 로 복원 후 서버에 전송&lt;/li&gt;
&lt;li&gt;$j \notin U$ (dropout) 라면: $j$ 의 secret share 를 다른 클라이언트들이 서버에 전송해 $s_j$ 복원, 이로부터 ${m_{ij}}$ 재생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;서버가 &lt;strong&gt;살아남은 클라이언트의 $b_j$ 합&lt;/strong&gt; 을 계산해 빼고, &lt;strong&gt;dropout 클라이언트의 pairwise mask 합&lt;/strong&gt; 도 계산해 빼면:&lt;/p&gt;
&lt;p&gt;$$
\sum_{i \in U} y_i - \sum_{i \in U} b_i - \sum_{\text{dropped}} \text{recovered masks} = \sum_{i \in U} x_i
$$&lt;/p&gt;
&lt;p&gt;깨끗한 합이 도출됩니다.&lt;/p&gt;
&lt;h2 id=&quot;왜-두-개의-마스크가-필요한가&quot;&gt;왜 두 개의 마스크가 필요한가&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pairwise mask&lt;/strong&gt; ($m_{ij}$): 모든 클라이언트가 살아있다면 상쇄, 서버가 개별 값 못 봄&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self mask&lt;/strong&gt; ($b_i$): dropout 이 발생해도 $x_i$ 노출 방지&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;만약 self mask 없이 pairwise 만 있다면, dropout 클라이언트의 pairwise 를 복원할 때 &lt;strong&gt;살아있는 클라이언트의 $x_i$ 가 잠깐 노출&lt;/strong&gt; 될 수 있습니다. Self mask 로 이 constraint 를 해소.&lt;/p&gt;
&lt;h2 id=&quot;통신-복잡도&quot;&gt;통신 복잡도&lt;/h2&gt;
&lt;p&gt;Bonawitz 원 프로토콜:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트당 $O(n)$ 통신 (모든 다른 클라이언트와 key exchange)&lt;/li&gt;
&lt;li&gt;$n$ = 1000 정도면 감내 가능하지만 $n = 10^6$ 은 불가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;SecAgg+ (Bell et al., 2022)&lt;/strong&gt;: 통신을 $O(\log n)$ 으로 줄임. 각 클라이언트는 로그 스케일의 이웃과만 통신. 대규모 cross-device FL 에서 실용화.&lt;/p&gt;
&lt;h2 id=&quot;대안-접근&quot;&gt;대안 접근&lt;/h2&gt;
&lt;h3 id=&quot;1-homomorphic-encryption-he&quot;&gt;1. Homomorphic Encryption (HE)&lt;/h3&gt;
&lt;p&gt;각 클라이언트가 업데이트를 &lt;strong&gt;HE 로 암호화&lt;/strong&gt; 하여 서버에 전송. 서버는 암호화된 상태로 덧셈 수행, 결과만 신뢰된 aggregator 가 복호화.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros&lt;/strong&gt;: 담합 우려 없음, 단순한 데이터 흐름&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cons&lt;/strong&gt;: 연산 비용이 매우 큼 (수십~수백 배), gradient 크기 큰 딥러닝에 부담&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;대표 스킴&lt;/strong&gt;: BFV, CKKS (approximate arithmetic)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-trusted-execution-environment-tee&quot;&gt;2. Trusted Execution Environment (TEE)&lt;/h3&gt;
&lt;p&gt;서버측 &lt;strong&gt;SGX/TDX enclave&lt;/strong&gt; 에서 raw 업데이트를 받아 집계. Enclave 코드가 서명되어 외부에서 검증 가능.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros&lt;/strong&gt;: 성능 오버헤드 작음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cons&lt;/strong&gt;: 하드웨어 신뢰 필요, side-channel 공격 사례 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-multi-party-computation-mpc&quot;&gt;3. Multi-Party Computation (MPC)&lt;/h3&gt;
&lt;p&gt;여러 non-colluding 서버가 집계 계산을 분산 수행. 어느 한 서버도 완전한 정보를 갖지 않음.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pros&lt;/strong&gt;: 강한 이론 보장&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cons&lt;/strong&gt;: 여러 서버 인프라 필요, 통신 라운드 증가&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;differential-privacy-와의-결합&quot;&gt;Differential Privacy 와의 결합&lt;/h2&gt;
&lt;p&gt;Secure Aggregation 은 &lt;strong&gt;집계의 은닉&lt;/strong&gt; 을 보장하지만, &lt;strong&gt;집계 결과 자체&lt;/strong&gt; 에는 정보가 남습니다. 서버가 집계된 gradient 를 여러 라운드 관찰하면 개별 정보를 추정할 수 있음.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;해결&lt;/strong&gt;: 각 클라이언트가 자기 gradient 에 [[differential-privacy|DP noise]] 를 추가하고 그 결과를 Secure Aggregation.&lt;/p&gt;
&lt;p&gt;$$
\tilde{x}_i = x_i + \mathcal{N}(0, \sigma^2 I)
$$&lt;/p&gt;
&lt;p&gt;또는 &lt;strong&gt;central DP&lt;/strong&gt;: 신뢰된 aggregator 가 집계 후에 노이즈 추가. 필요 노이즈 양이 client-level DP 대비 작음.&lt;/p&gt;
&lt;h2 id=&quot;실전-프레임워크-지원&quot;&gt;실전 프레임워크 지원&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TensorFlow Federated&lt;/strong&gt;: &lt;code&gt;tff.aggregators.secure_aggregation&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flower&lt;/strong&gt;: &lt;code&gt;FedAvg&lt;/code&gt; 에 secure aggregation strategy plugin&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NVFlare&lt;/strong&gt;: SAG (Scatter and Gather) 워크플로에 통합&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CrypTen&lt;/strong&gt; (Meta): PyTorch 기반 MPC&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PySyft&lt;/strong&gt; (OpenMined): HE + MPC 통합&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;함정&quot;&gt;함정&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;DP 없는 Secure Aggregation 은 완전한 프라이버시가 아닙니다.&lt;/strong&gt; 집계된 gradient 로부터도 정보가 새므로, DP 와 반드시 결합.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;Dropout 관리가 까다롭습니다.&lt;/strong&gt; 임계값 $t$ 를 잘못 잡으면 프로토콜이 실패하거나 (너무 많이 dropout) 프라이버시가 훼손 (담합 임계값 낮음).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;Byzantine 클라이언트가 임의의 큰 값을 넣으면 결과가 오염&lt;/strong&gt; 됩니다. Secure Aggregation 은 담합/도청은 방어하지만 값 검증은 안 함. Robust aggregation (Krum, Median) 이 별도 필요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!IMPORTANT]
&lt;strong&gt;모듈러 산술 (mod R) 오버플로 관리&lt;/strong&gt;. 실수를 정수로 quantize 하고 R 을 충분히 크게 잡아야 합계가 wrap-around 안 함.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[!CAUTION]
&lt;strong&gt;암호학적 primitive 를 직접 구현하지 마세요&lt;/strong&gt;. 검증된 라이브러리 (TFF, Flower, OpenMined) 를 사용. Side-channel 공격은 다이렉트 구현에서 흔한 위험.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;프로토콜-흐름-시각화&quot;&gt;프로토콜 흐름 시각화&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart TD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    R0[&quot;Round 0: 키 광고&amp;#x3C;br/&gt;각 클라이언트, DH 공개키 서버 전송&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    R1[&quot;Round 1: 키 분배&amp;#x3C;br/&gt;Shamir Secret Sharing, 임계값 t&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    R2[&quot;Round 2: 마스크된 업데이트&amp;#x3C;br/&gt;pairwise mask + self mask 적용&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    R3[&quot;Round 3: 마스크 제거&amp;#x3C;br/&gt;살아남은 클라이언트 b_j 공개, dropout 복원&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Done[&quot;집계 완료: gradient 합만 노출&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    R0 --&gt; R1 --&gt; R2 --&gt; R3 --&gt; Done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;dropout-처리-흐름&quot;&gt;Dropout 처리 흐름&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;mermaid&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Alive[&quot;살아남은 클라이언트 U&quot;] --&gt;|&quot;b_j 제출&quot;| Server[서버]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Dropped[&quot;Dropout 클라이언트&quot;] --&gt;|&quot;Shamir 복원&quot;| MaskRec[&quot;mask 재생성&quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    MaskRec --&gt; Server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    Server --&gt; Sum[&quot;sum(x_i for i in U)&quot;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;secagg-통신-복잡도&quot;&gt;SecAgg+ 통신 복잡도&lt;/h2&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;프로토콜&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;클라이언트당 통신&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;n=10^6 적합&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Bonawitz SecAgg&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;O(n)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;불가&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;SecAgg+ (Bell 2022)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;O(log n)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가능&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;TEE 방식&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;O(1)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;가능 (하드웨어 신뢰 필요)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;SecAgg+ 는 각 클라이언트를 $k$-정규 그래프 이웃과만 연결. 이웃 수 $k = O(\log n)$ 로 전체 통신량이 대폭 감소.&lt;/p&gt;
&lt;h2 id=&quot;공격-방어-매핑&quot;&gt;공격 방어 매핑&lt;/h2&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;공격 유형&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Secure Aggregation 대응&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;추가 방어 필요&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Gradient inversion&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;개별 gradient 미노출&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;DP noise 병행 권장&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Honest-but-curious server&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;집계 값만 노출&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Collusion (t 이하)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Shamir threshold 로 차단&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Byzantine (값 오염)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;미대응&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Robust aggregation (Krum, Median)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Model poisoning&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;미대응&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;이상값 탐지&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Dropout 공격&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;t 이하 dropout 허용&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;임계값 조정&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Secure Aggregation 은 &lt;strong&gt;누가 무엇을 보는가&lt;/strong&gt; 를 제어. &lt;strong&gt;무엇을 넣는가&lt;/strong&gt; 는 별도 방어 레이어가 필요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;실전-구현-고려사항&quot;&gt;실전 구현 고려사항&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# TensorFlow Federated&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tensorflow_federated &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tff&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;secure_sum &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tff.aggregators.SecureModularSumFactory(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    modulus&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,   &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# R: wrap-around 방지. gradient 합이 R 을 넘지 않도록 설정&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Flower: strategy 플러그인 방식으로 SecAgg 적용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# from flwr.server.strategy import FedAvg + SecureAggregation adapter&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;클라이언트 수 $n$, 임계값 $t$, gradient 차원 $d$ 에 따라 통신 오버헤드 추정:&lt;/p&gt;
&lt;p&gt;$$
\text{총 통신량} \approx n \cdot k \cdot d \cdot \text{element_size}
$$&lt;/p&gt;
&lt;p&gt;대규모 배포 전 $d \times n$ 통신량 계산 필수. 7B 모델 ($d \approx 10^7$) 에서 클라이언트당 수백 MB 발생.&lt;/p&gt;
&lt;h2 id=&quot;관련-위키&quot;&gt;관련 위키&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[federated-learning|Federated Learning]] - 상위 개념&lt;/li&gt;
&lt;li&gt;[[fedavg|FedAvg]] - 집계 대상 기본 알고리즘&lt;/li&gt;
&lt;li&gt;[[differential-privacy|Differential Privacy]] - Secure Aggregation 과 반드시 결합&lt;/li&gt;
&lt;li&gt;[[fl-non-iid|Non-IID Data in FL]] - 프라이버시와 무관한 다른 도전&lt;/li&gt;
&lt;li&gt;[[personalized-fl|Personalized FL]]&lt;/li&gt;
&lt;li&gt;[[fl-frameworks|FL Frameworks]] - 프레임워크의 SecAgg 지원&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>federated-learning</category><category>privacy</category><category>cryptography</category><category>security</category><author>koa (김신건)</author></item><item><title>[AWS SageMaker] Model Monitor: 모델 및 데이터 드리프트 감지</title><link>https://shinkeonkim.com/wiki/ml/sagemaker-model-monitor/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/sagemaker-model-monitor/</guid><pubDate>Mon, 29 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;[!WARNING]
&lt;strong&gt;AWS 공식 발표 (2026)&lt;/strong&gt;: &lt;strong&gt;2026-07-30 부터 SageMaker Model Monitor 는 신규 고객 사용이 중단됩니다.&lt;/strong&gt; 기존 사용 고객은 계속 이용 가능하며 보안/가용성 개선은 유지되지만, &lt;strong&gt;신규 기능 추가는 없습니다.&lt;/strong&gt; 대안으로 &lt;a href=&quot;https://docs.aws.amazon.com/sagemaker/latest/dg/model-monitor-availability-change.html&quot;&gt;Amazon SageMaker AI 통합 모니터링&lt;/a&gt;, 또는 서드파티 (EvidentlyAI, WhyLabs, Arize, Fiddler 등) 를 고려하세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Amazon SageMaker Model Monitor&lt;/strong&gt; 는 SageMaker AI 로 프로덕션 배포된 ML 모델의 &lt;strong&gt;데이터 및 모델 품질을 지속 모니터링&lt;/strong&gt; 하고, 드리프트가 발생하면 알림을 보내는 관리형 서비스입니다. 실시간 endpoint 와 배치 transform 작업 양쪽 모두를 지원합니다.&lt;/p&gt;
&lt;p&gt;핵심 아이디어: &lt;strong&gt;학습 데이터로 baseline 통계&lt;/strong&gt; 를 만들어 두고, 프로덕션 요청/응답을 캡처하여 &lt;strong&gt;주기적으로 baseline 과 비교&lt;/strong&gt;, 위반 (violation) 을 감지합니다.&lt;/p&gt;
&lt;h2 id=&quot;4-가지-모니터-타입&quot;&gt;4 가지 모니터 타입&lt;/h2&gt;
&lt;p&gt;Model Monitor 가 제공하는 네 가지 감시 유형입니다.&lt;/p&gt;
&lt;h3 id=&quot;1-data-quality-monitor&quot;&gt;1. Data Quality Monitor&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;입력 데이터 통계 변화 감지&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;학습 데이터의 통계 (feature 별 평균, 분산, 결측 비율, distinct 개수, 데이터 타입 등) 를 baseline 으로 삼음&lt;/li&gt;
&lt;li&gt;프로덕션 입력이 이 통계에서 크게 벗어나면 위반&lt;/li&gt;
&lt;li&gt;Data drift 라고도 부름&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-model-quality-monitor&quot;&gt;2. Model Quality Monitor&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;예측 성능 지표 자체를 모니터링&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Accuracy, F1, precision, recall, MSE, MAE 등 (참고: [[classification-metrics|분류 모델 지표]])&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;정답 라벨 (ground truth)&lt;/strong&gt; 이 나중에 제공되어야 하므로, 프로덕션 예측과 라벨을 매칭하는 파이프라인이 필요&lt;/li&gt;
&lt;li&gt;Concept drift 감지 목적&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-bias-drift-monitor&quot;&gt;3. Bias Drift Monitor&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;인구통계 집단 간 예측 편향 변화&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;SageMaker Clarify 와 통합&lt;/li&gt;
&lt;li&gt;지표: DPPL (Difference in Positive Proportions in Predicted Labels), DI (Disparate Impact) 등&lt;/li&gt;
&lt;li&gt;학습 시점 대비 특정 집단에 대한 편향이 커졌는지 감시&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-feature-attribution-drift-monitor&quot;&gt;4. Feature Attribution Drift Monitor&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;feature importance 분포 변화&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;SHAP 값 기반, 각 feature 가 예측에 기여하는 정도가 학습 시점과 달라졌는지&lt;/li&gt;
&lt;li&gt;입력 통계는 안 변했는데 feature 의 역할이 바뀐 미묘한 shift 를 잡음&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;아키텍처&quot;&gt;아키텍처&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;┌──────────────┐    inference    ┌───────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;│   Client     │ ─────────────&gt;  │  SageMaker        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└──────────────┘   request +     │  Endpoint         │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       ▲          response       │  (with            │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                         │   DataCapture)    │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                         └────────┬──────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                                  │ capture&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                                  ▼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          ┌────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          │   S3 bucket    │  ◀── training data baseline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          │   captured/    │      (statistics.json,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          └────────┬───────┘       constraints.json)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                                   │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                                   ▼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          ┌────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          │  Monitoring    │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          │  Schedule      │  (hourly / daily)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          │  (Processing   │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          │   Job)         │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          └────────┬───────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                                   │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                                   ▼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │                          ┌────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       │  alert  ┌────────────┐   │  CloudWatch    │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;       └────────┤ SNS/Lambda  ├───┤  Metrics +     │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                └────────────┘    │  Alarms        │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                                  └────────────────┘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;단계별-컴포넌트&quot;&gt;단계별 컴포넌트&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Data Capture&lt;/strong&gt;: 엔드포인트에 &lt;code&gt;DataCaptureConfig&lt;/code&gt; 활성화, 입력/출력을 S3 에 저장&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Baseline&lt;/strong&gt;: 학습 데이터에서 &lt;code&gt;suggest_baseline()&lt;/code&gt; 실행 → &lt;code&gt;statistics.json&lt;/code&gt; + &lt;code&gt;constraints.json&lt;/code&gt; 생성&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitoring Schedule&lt;/strong&gt;: cron 또는 hourly 로 Processing Job 자동 실행&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Processing Job&lt;/strong&gt;: 컨테이너에서 캡처 데이터 vs baseline 비교, 위반 리포트 생성&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CloudWatch&lt;/strong&gt;: 위반 개수, 지표를 CloudWatch 메트릭으로 발행. 알람 → SNS → Lambda / Slack / PagerDuty&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;python-sdk-클래스&quot;&gt;Python SDK 클래스&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;sagemaker&lt;/code&gt; Python SDK 의 각 모니터 클래스:&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;클래스&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;모니터 타입&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;sagemaker.model_monitor.DefaultModelMonitor&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Data Quality&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;sagemaker.model_monitor.ModelQualityMonitor&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Model Quality&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;sagemaker.model_monitor.ModelBiasMonitor&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Bias Drift&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;sagemaker.model_monitor.ModelExplainabilityMonitor&lt;/code&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Feature Attribution Drift&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;공통 인터페이스:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;suggest_baseline(...)&lt;/code&gt;: baseline 통계 생성&lt;/li&gt;
&lt;li&gt;&lt;code&gt;create_monitoring_schedule(...)&lt;/code&gt;: 스케줄 등록&lt;/li&gt;
&lt;li&gt;&lt;code&gt;describe_schedule()&lt;/code&gt;, &lt;code&gt;list_executions()&lt;/code&gt;, &lt;code&gt;stop_monitoring_schedule()&lt;/code&gt;, &lt;code&gt;delete_monitoring_schedule()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;실전-코드-data-quality&quot;&gt;실전 코드 (Data Quality)&lt;/h2&gt;
&lt;h3 id=&quot;1-endpoint-에-data-capture-활성화&quot;&gt;1. Endpoint 에 Data Capture 활성화&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sagemaker.model_monitor &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DataCaptureConfig&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data_capture_config &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DataCaptureConfig(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    enable_capture&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    sampling_percentage&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    destination_s3_uri&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;s3://&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bucket&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/captured/&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    capture_options&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;REQUEST&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RESPONSE&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    csv_content_types&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;text/csv&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    json_content_types&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;predictor &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model.deploy(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    initial_instance_count&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    instance_type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ml.m5.xlarge&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    data_capture_config&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data_capture_config,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-baseline-생성&quot;&gt;2. Baseline 생성&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sagemaker.model_monitor &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DefaultModelMonitor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sagemaker.model_monitor.dataset_format &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DatasetFormat&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;monitor &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; DefaultModelMonitor(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    role&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;role,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    instance_count&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    instance_type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ml.m5.xlarge&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    volume_size_in_gb&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    max_runtime_in_seconds&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3600&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;monitor.suggest_baseline(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    baseline_dataset&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;s3://&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bucket&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/training-data.csv&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    dataset_format&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;DatasetFormat.csv(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;header&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    output_s3_uri&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;s3://&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bucket&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/baselines/&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    wait&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;결과로 &lt;code&gt;statistics.json&lt;/code&gt; (feature 별 mean, std, min, max, distinct_count 등) 과 &lt;code&gt;constraints.json&lt;/code&gt; (허용 범위) 이 생깁니다.&lt;/p&gt;
&lt;h3 id=&quot;3-monitoring-schedule-등록&quot;&gt;3. Monitoring Schedule 등록&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sagemaker.model_monitor &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; CronExpressionGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;monitor.create_monitoring_schedule(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    monitor_schedule_name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;my-daily-monitor&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    endpoint_input&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;predictor.endpoint_name,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    output_s3_uri&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;s3://&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bucket&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;/monitor-reports/&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    statistics&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;monitor.baseline_statistics(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    constraints&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;monitor.suggested_constraints(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    schedule_cron_expression&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;CronExpressionGenerator.hourly(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    enable_cloudwatch_metrics&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;4-cloudwatch-알람-연결&quot;&gt;4. CloudWatch 알람 연결&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; boto3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cw &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; boto3.client(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;cloudwatch&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cw.put_metric_alarm(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    AlarmName&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;ModelMonitor-FeatureBaselineDrift&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    MetricName&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;feature_baseline_drift_check_violations&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    Namespace&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;aws/sagemaker/Endpoints/data-metrics&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    Statistic&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Sum&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    Period&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3600&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    EvaluationPeriods&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    Threshold&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    ComparisonOperator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;GreaterThanOrEqualToThreshold&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    AlarmActions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;arn:aws:sns:us-east-1:123:model-alerts&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    Dimensions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Endpoint&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Value&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: predictor.endpoint_name},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;MonitoringSchedule&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Value&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;my-daily-monitor&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;model-quality-의-ground-truth-연결&quot;&gt;Model Quality 의 ground truth 연결&lt;/h2&gt;
&lt;p&gt;Model Quality Monitor 는 &lt;strong&gt;예측 결과와 실제 정답을 매칭&lt;/strong&gt; 해야 하는 게 특별합니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;예측 시 각 요청에 &lt;code&gt;inference_id&lt;/code&gt; 부여 (헤더 또는 payload 필드)&lt;/li&gt;
&lt;li&gt;나중에 정답 라벨이 확정되면 &lt;code&gt;s3://.../ground_truth/YYYY/MM/DD/HH/data.json&lt;/code&gt; 에 저장&lt;/li&gt;
&lt;li&gt;Model Quality Monitor 가 이 두 소스를 조인해서 accuracy/F1 등 계산&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;라벨 지연이 큰 서비스 (예: 이탈 예측은 30 일 후 결과 확인) 에는 스케줄을 그에 맞게 설정합니다.&lt;/p&gt;
&lt;h2 id=&quot;baseline-파일-형식&quot;&gt;Baseline 파일 형식&lt;/h2&gt;
&lt;h3 id=&quot;statisticsjson-예&quot;&gt;statistics.json (예)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;version&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;dataset&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;item_count&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;features&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;inferred_type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Fractional&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;numerical_statistics&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        &quot;common&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;num_present&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;9980&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;num_missing&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        &quot;mean&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;34.5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;sum&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;344310&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;std_dev&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12.3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        &quot;min&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;18&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;max&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;88&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        &quot;distribution&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;kll&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#FDAEB7;font-style:italic&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; } }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;constraintsjson-예&quot;&gt;constraints.json (예)&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;version&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;features&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;inferred_type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Fractional&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;completeness&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.998&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;num_constraints&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: { &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;&quot;is_non_negative&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &quot;monitoring_config&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;evaluate_constraints&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Enabled&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;datatype_check_threshold&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;domain_content_threshold&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    &quot;distribution_constraints&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;perform_comparison&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Enabled&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;comparison_threshold&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &quot;comparison_method&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Robust&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;comparison_method&lt;/code&gt; 는 &lt;code&gt;Simple&lt;/code&gt; / &lt;code&gt;Robust&lt;/code&gt; / &lt;code&gt;LInfty&lt;/code&gt; 등이 있으며, 통계 비교 방식을 정의합니다.&lt;/p&gt;
&lt;h2 id=&quot;지원-데이터-타입-제한&quot;&gt;지원 데이터 타입 제한&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;tabular 입력만&lt;/strong&gt; 자동 통계 지원. 이미지 분류 모델의 이미지 입력은 통계 계산 불가, 하지만 &lt;strong&gt;출력 라벨은 모니터링 가능&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Multi-model endpoint 미지원&lt;/li&gt;
&lt;li&gt;Data Capture 저장소 disk 사용률 75% 이상이면 캡처 중단 → 정기 정리 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;다른-도구와-비교&quot;&gt;다른 도구와 비교&lt;/h2&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;도구&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;관리 방식&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;강점&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;약점&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;SageMaker Model Monitor&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;AWS 관리형&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SageMaker 통합 편함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;2026-07-30 신규 종료&lt;/strong&gt;, 커스터마이징 제한&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://www.evidentlyai.com/&quot;&gt;EvidentlyAI&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;오픈소스 + 클라우드&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;시각화 강함, 프레임워크 애그노스틱&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;셀프 호스팅 부담&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://whylabs.ai/&quot;&gt;WhyLabs&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SaaS&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;whylogs 프로파일링 라이브러리 좋음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;유료&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://arize.com/&quot;&gt;Arize AI&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SaaS&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;LLM 모니터링 강점 (Phoenix)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;유료&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://www.fiddler.ai/&quot;&gt;Fiddler&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;SaaS&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;대기업 규제 산업 대응&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;무거움&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Prometheus + Grafana + 자체 스크립트&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;셀프&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;완전 제어&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;초기 구현 부담&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;비용&quot;&gt;비용&lt;/h2&gt;
&lt;p&gt;Model Monitor 는 &lt;strong&gt;처리 작업 (Processing Job) 실행 비용&lt;/strong&gt; 을 청구합니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;인스턴스 타입 (&lt;code&gt;ml.m5.xlarge&lt;/code&gt; 등) × 실행 시간&lt;/li&gt;
&lt;li&gt;하루 24 회 (매 시간) × 30 분씩 실행이면 대략 12 시간분 비용&lt;/li&gt;
&lt;li&gt;S3 저장 (capture, baseline, report), CloudWatch 메트릭 별도&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;프로덕션에서는 하루 1~2 회 스케줄로 충분한 경우가 많습니다.&lt;/p&gt;
&lt;h2 id=&quot;best-practice&quot;&gt;Best Practice&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Baseline 은 학습 데이터가 아니라 최근 검증 데이터&lt;/strong&gt; 로 만들면 편차가 작습니다&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alert threshold 를 여러 심각도로&lt;/strong&gt; (warning: violations&gt;=1, critical: violations&gt;=5)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CloudWatch 대신 EventBridge → Lambda → 슬랙&lt;/strong&gt; 을 자주 사용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;비용 통제&lt;/strong&gt;: 트래픽 크면 &lt;code&gt;sampling_percentage=10&lt;/code&gt; 정도로 낮춰서 캡처&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model Quality 는 라벨 지연을 감안&lt;/strong&gt; 하여 스케줄 늦춤&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;위반이 나면 자동 재학습 트리거&lt;/strong&gt; 하는 파이프라인 (SageMaker Pipelines + Step Functions)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;드리프트가 아니라 데이터 파이프라인 문제일 가능성&lt;/strong&gt; 을 먼저 검토 (매핑 코드 변경, 스키마 변경 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;model-drift-개념-정리&quot;&gt;Model Drift 개념 정리&lt;/h2&gt;
&lt;p&gt;Model Monitor 가 감지하려는 것들:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data Drift&lt;/strong&gt; (Covariate Shift): 입력 $P(X)$ 분포 변화. 데이터 자체가 달라진 경우&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Concept Drift&lt;/strong&gt;: 입력-출력 관계 $P(Y|X)$ 변화. 예측 대상 자체의 성질 변화 (예: 사기 패턴이 진화)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Label Drift&lt;/strong&gt;: $P(Y)$ 변화. 실제 정답 분포가 달라진 경우&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prediction Drift&lt;/strong&gt;: 모델 예측 $P(\hat{Y})$ 변화. 위 셋 중 하나 이상의 결과&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;각각 다른 시그널이며, 4 가지 모니터가 이 시그널들을 부분적으로 커버합니다.&lt;/p&gt;
&lt;h2 id=&quot;대안-2026-신규-종료-이후&quot;&gt;대안 (2026 신규 종료 이후)&lt;/h2&gt;
&lt;p&gt;신규 프로젝트라면 다음을 고려:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Evidently + SageMaker Pipelines&lt;/strong&gt;: 오픈소스, SageMaker 안에서 처리 작업으로 실행&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;whylogs + WhyLabs&lt;/strong&gt;: 데이터 프로파일링 라이브러리, WhyLabs SaaS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자체 구축&lt;/strong&gt;: Great Expectations 로 데이터 품질, MLflow 로 모델 성능 트래킹&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AWS 대체&lt;/strong&gt;: 앞으로 나올 SageMaker AI 의 통합 모니터링 (공지 참고)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;참고&quot;&gt;참고&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;관련 [[classification-metrics|분류 모델 지표]] 는 Model Quality Monitor 의 근간&lt;/li&gt;
&lt;li&gt;관련 [[transfer-learning|Transfer Learning]] fine-tuned 모델도 동일하게 모니터링 대상&lt;/li&gt;
&lt;li&gt;AWS 공식: &lt;a href=&quot;https://docs.aws.amazon.com/sagemaker/latest/dg/model-monitor.html&quot;&gt;Model Monitor&lt;/a&gt;, &lt;a href=&quot;https://docs.aws.amazon.com/sagemaker/latest/dg/model-monitor-availability-change.html&quot;&gt;Availability change&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;참고 아티클: &lt;a href=&quot;https://www.evidentlyai.com/ml-in-production/data-drift&quot;&gt;Model drift 관련 개념&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>aws</category><category>sagemaker</category><category>mlops</category><category>monitoring</category><category>drift</category><author>koa (김신건)</author></item><item><title>Differential Privacy: (ε, δ) 로 정량화하는 프라이버시 보장</title><link>https://shinkeonkim.com/wiki/ml/differential-privacy/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/differential-privacy/</guid><pubDate>Mon, 29 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Differential Privacy (DP, 차분 프라이버시)&lt;/strong&gt; 는 데이터셋에 대한 질의 (query) 결과에 &lt;strong&gt;calibrated noise&lt;/strong&gt; 를 추가함으로써, &lt;strong&gt;한 개인의 데이터가 포함되었는지 여부&lt;/strong&gt; 를 결과만 보고서는 알 수 없게 만드는 수학적 프라이버시 프레임워크입니다. Cynthia Dwork 등이 2006 년에 정의했습니다.&lt;/p&gt;
&lt;p&gt;핵심 아이디어: “당신이 데이터셋에 있든 없든, 통계 결과는 거의 같게 보이도록 만든다.”&lt;/p&gt;
&lt;h2 id=&quot;왜-등장했는가&quot;&gt;왜 등장했는가&lt;/h2&gt;
&lt;p&gt;전통적 익명화 (identifier 제거, k-anonymity, l-diversity 등) 는 &lt;strong&gt;linkage attack&lt;/strong&gt; 에 취약합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Netflix Prize (2007)&lt;/strong&gt;: 익명화된 시청 기록이 IMDb 공개 리뷰와 결합되어 사용자 재식별&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AOL 검색 로그 (2006)&lt;/strong&gt;: 사용자 ID 만 익명화했지만 검색 쿼리 자체가 지문 역할&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Massachusetts governor 재식별 (Sweeney, 1997)&lt;/strong&gt;: ZIP + 생년월일 + 성별 3 축만으로 87% 재식별 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;문제의 본질: &lt;strong&gt;관측 가능한 결과가 특정 개인의 데이터에 크게 의존&lt;/strong&gt; 하면, 아무리 이름을 지워도 그 개인이 데이터에 있었다는 사실 자체가 새어 나갑니다. DP 는 이 의존성을 &lt;strong&gt;정량적 상한&lt;/strong&gt; 으로 제어합니다.&lt;/p&gt;
&lt;h2 id=&quot;형식-정의&quot;&gt;형식 정의&lt;/h2&gt;
&lt;h3 id=&quot;인접-데이터셋-adjacent-datasets&quot;&gt;인접 데이터셋 (Adjacent Datasets)&lt;/h3&gt;
&lt;p&gt;두 데이터셋 $D$ 와 $D’$ 이 &lt;strong&gt;정확히 한 레코드만 다를 때&lt;/strong&gt; 인접 (adjacent) 이라고 합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add/Remove 인접: $D’ = D \cup {x}$ 또는 $D’ = D \setminus {x}$&lt;/li&gt;
&lt;li&gt;Replace 인접: $D’$ 이 $D$ 의 한 레코드를 다른 값으로 바꾼 결과&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;정의에 따라 프라이버시 보장 강도가 조금씩 달라지지만, 실용적으로는 큰 차이 없습니다.&lt;/p&gt;
&lt;h3 id=&quot;ε-differential-privacy-pure-dp&quot;&gt;ε-Differential Privacy (pure DP)&lt;/h3&gt;
&lt;p&gt;무작위 알고리즘 $\mathcal{M}$ 이 $\epsilon$-DP 를 만족한다는 것은, 임의의 인접 데이터셋 $D, D’$ 과 임의의 출력 집합 $S$ 에 대해:&lt;/p&gt;
&lt;p&gt;$$
\Pr[\mathcal{M}(D) \in S] \leq e^{\epsilon} \cdot \Pr[\mathcal{M}(D’) \in S]
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\epsilon$ (epsilon): 프라이버시 손실의 상한. 작을수록 강력한 보장.&lt;/li&gt;
&lt;li&gt;$e^\epsilon \approx 1 + \epsilon$ (작은 $\epsilon$ 일 때), 즉 두 확률 분포가 매우 유사.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ε-δ-differential-privacy-approximate-dp&quot;&gt;(ε, δ)-Differential Privacy (approximate DP)&lt;/h3&gt;
&lt;p&gt;$$
\Pr[\mathcal{M}(D) \in S] \leq e^{\epsilon} \cdot \Pr[\mathcal{M}(D’) \in S] + \delta
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\delta$: 위 부등식이 실패할 확률의 상한. 보통 $\delta \ll 1/n$ (데이터 크기의 역수보다 작게)&lt;/li&gt;
&lt;li&gt;Gaussian mechanism 등은 pure DP 를 만족할 수 없어 approximate DP 를 씀&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Rule of thumb&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\epsilon \leq 1$: 강한 보장&lt;/li&gt;
&lt;li&gt;$1 &amp;#x3C; \epsilon \leq 3$: 중간&lt;/li&gt;
&lt;li&gt;$\epsilon &gt; 10$: 실질적 보장 미미 (경고 신호)&lt;/li&gt;
&lt;li&gt;$\delta &amp;#x3C; 1/n^2$ 정도 권장 (Dwork 의 조언)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;왜-이-정의인가&quot;&gt;왜 이 정의인가&lt;/h2&gt;
&lt;p&gt;DP 의 강력한 점:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;개인 데이터의 존재/부재를 감출 수 있음&lt;/strong&gt;: 공격자가 사전에 알고 있는 정보가 아무리 많아도 (어떤 auxiliary data 를 가지고 있어도) 새 정보를 얻기 어려움&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Composition 가능&lt;/strong&gt;: 여러 DP 쿼리를 합쳐도 여전히 DP 성질 유지 (예산 합산)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Post-processing immunity&lt;/strong&gt;: DP 결과에 어떤 계산을 추가로 해도 여전히 DP 유지&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;미래 공격에 대비&lt;/strong&gt;: 특정 공격을 상정하지 않고 최악 케이스를 다룸&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;핵심-개념-sensitivity&quot;&gt;핵심 개념: Sensitivity&lt;/h2&gt;
&lt;p&gt;함수 $f: \text{Data} \to \mathbb{R}^d$ 의 &lt;strong&gt;global sensitivity&lt;/strong&gt; 는 인접 데이터셋에 대한 함수 값 변화의 상한:&lt;/p&gt;
&lt;p&gt;$$
\Delta f = \max_{D, D’ \text{ adjacent}} | f(D) - f(D’) |_1
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;개수 세기 (count): $\Delta f = 1$ (한 명 추가/제거하면 결과 1 변함)&lt;/li&gt;
&lt;li&gt;평균 (mean) with bounded values in $[0, M]$: $\Delta f = M/n$&lt;/li&gt;
&lt;li&gt;합 (sum) with bounded values in $[0, M]$: $\Delta f = M$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sensitivity 가 클수록 더 많은 노이즈가 필요합니다. &lt;strong&gt;값을 미리 clip 해서 sensitivity 를 제어&lt;/strong&gt; 하는 게 실전에서 매우 흔한 패턴입니다.&lt;/p&gt;
&lt;h2 id=&quot;핵심-메커니즘&quot;&gt;핵심 메커니즘&lt;/h2&gt;
&lt;h3 id=&quot;laplace-mechanism&quot;&gt;Laplace Mechanism&lt;/h3&gt;
&lt;p&gt;$\epsilon$-DP 를 만족하는 가장 단순한 방법. Laplace 분포에서 노이즈 샘플:&lt;/p&gt;
&lt;p&gt;$$
\mathcal{M}(D) = f(D) + \text{Lap}\left( \frac{\Delta f}{\epsilon} \right)
$$&lt;/p&gt;
&lt;p&gt;Laplace 분포는 라플라스 확률 밀도 $\text{Lap}(b): p(x) = \frac{1}{2b} e^{-|x|/b}$.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numpy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; laplace_mechanism&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(true_value, sensitivity, epsilon):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    noise &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np.random.laplace(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;loc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;scale&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sensitivity&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;epsilon)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; true_value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; noise&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 예: 데이터셋에서 특정 조건 만족하는 사용자 수 세기&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;true_count &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 4321&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;noisy_count &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; laplace_mechanism(true_count, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;sensitivity&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;epsilon&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;gaussian-mechanism&quot;&gt;Gaussian Mechanism&lt;/h3&gt;
&lt;p&gt;$(\epsilon, \delta)$-DP 를 만족. L2 sensitivity 사용:&lt;/p&gt;
&lt;p&gt;$$
\mathcal{M}(D) = f(D) + \mathcal{N}\left(0, \left(\frac{\Delta_2 f \cdot \sqrt{2 \ln(1.25/\delta)}}{\epsilon}\right)^2 \right)
$$&lt;/p&gt;
&lt;p&gt;Gaussian 은 여러 차원의 합성에서 유리하며, DP-SGD 등에서 표준입니다.&lt;/p&gt;
&lt;h3 id=&quot;exponential-mechanism&quot;&gt;Exponential Mechanism&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;범주형/불연속 출력&lt;/strong&gt; 에 사용. Utility 함수 $u(D, r)$ 을 정의하고:&lt;/p&gt;
&lt;p&gt;$$
\Pr[\mathcal{M}(D) = r] \propto \exp\left( \frac{\epsilon \cdot u(D, r)}{2 \Delta u} \right)
$$&lt;/p&gt;
&lt;p&gt;Utility 가 높은 후보를 확률적으로 우선 선택합니다. 경매, 후보 선택 문제에 씀.&lt;/p&gt;
&lt;h2 id=&quot;composition&quot;&gt;Composition&lt;/h2&gt;
&lt;p&gt;여러 DP 쿼리를 순차적으로 하면 프라이버시가 누적됩니다.&lt;/p&gt;
&lt;h3 id=&quot;basic-composition&quot;&gt;Basic Composition&lt;/h3&gt;
&lt;p&gt;$k$ 개의 $(\epsilon_i, \delta_i)$-DP 메커니즘의 순차 합성은:&lt;/p&gt;
&lt;p&gt;$$
\left(\sum \epsilon_i, \sum \delta_i\right)\text{-DP}
$$&lt;/p&gt;
&lt;p&gt;간단하지만 상당히 loose 합니다.&lt;/p&gt;
&lt;h3 id=&quot;advanced-composition-dwork-et-al-2010&quot;&gt;Advanced Composition (Dwork et al., 2010)&lt;/h3&gt;
&lt;p&gt;$k$ 개의 $(\epsilon, \delta)$-DP 메커니즘의 합성은 다음과 같이 tighter:&lt;/p&gt;
&lt;p&gt;$$
\left(\epsilon’ = \epsilon \sqrt{2k \ln(1/\delta’)} + k \epsilon (e^\epsilon - 1), ; k\delta + \delta’\right)\text{-DP}
$$&lt;/p&gt;
&lt;p&gt;Basic 대비 $\sqrt{k}$ 배 정도로 개선됩니다.&lt;/p&gt;
&lt;h3 id=&quot;rényi-dp-를-통한-tighter-composition&quot;&gt;Rényi DP 를 통한 tighter composition&lt;/h3&gt;
&lt;p&gt;Mironov (2017) 의 &lt;strong&gt;Rényi DP&lt;/strong&gt; 는 Rényi divergence 로 프라이버시를 정의합니다. 합성이 매우 tight 하며 최종적으로 $(\epsilon, \delta)$-DP 로 변환합니다. &lt;strong&gt;DP-SGD 의 privacy accounting 은 사실상 Rényi DP + Moments Accountant&lt;/strong&gt; 방식입니다.&lt;/p&gt;
&lt;h2 id=&quot;privacy-budget&quot;&gt;Privacy Budget&lt;/h2&gt;
&lt;p&gt;한 데이터셋에 대해 여러 분석을 하고 싶다면, 각 분석마다 $\epsilon_i$ 를 배분해야 합니다.&lt;/p&gt;
&lt;p&gt;$$
\sum_i \epsilon_i \leq \epsilon_{\text{total}}
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;총 예산 소진 후에는 더 이상 어떤 쿼리도 하면 안 됨&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;프로덕션에서는 accountant 로 남은 예산을 실시간 추적&lt;/li&gt;
&lt;li&gt;예산이 부족하면: 데이터셋 refresh, 사용자 그룹 세분화, 더 세밀한 clipping 으로 sensitivity 감소&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;central-dp-vs-local-dp&quot;&gt;Central DP vs Local DP&lt;/h2&gt;
&lt;h3 id=&quot;central-dp-trusted-curator&quot;&gt;Central DP (Trusted Curator)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;신뢰할 수 있는 데이터 큐레이터 존재&lt;/li&gt;
&lt;li&gt;큐레이터가 원본 데이터를 보고 노이즈 추가 후 결과 공개&lt;/li&gt;
&lt;li&gt;Utility 높음, 프라이버시 보장은 큐레이터를 신뢰한다는 전제&lt;/li&gt;
&lt;li&gt;예: 미국 인구조사국, 대부분의 학술 통계&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;local-dp-ldp&quot;&gt;Local DP (LDP)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;신뢰할 수 있는 큐레이터가 없음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;각 개인이 자기 데이터에 노이즈를 추가하고 서버에 전송&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;서버는 노이즈가 낀 데이터만 받으므로 원본을 알 수 없음&lt;/li&gt;
&lt;li&gt;Utility 매우 낮음 (같은 $\epsilon$ 이면 노이즈가 훨씬 커야 함)&lt;/li&gt;
&lt;li&gt;Apple, Google 이 자주 배포&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;rappor-google-2014&quot;&gt;RAPPOR (Google, 2014)&lt;/h3&gt;
&lt;p&gt;LDP 의 대표 배포. Chrome 사용자의 홈페이지 URL 통계를 수집할 때 각 사용자가 자기 URL 을 Bloom filter 로 인코딩한 뒤 각 비트를 &lt;strong&gt;randomized response&lt;/strong&gt; 로 뒤집어 전송. 서버는 통계만 복원 가능, 개인 URL 은 알 수 없음.&lt;/p&gt;
&lt;h3 id=&quot;비교&quot;&gt;비교&lt;/h3&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;구분&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Central DP&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Local DP&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;신뢰 모델&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;큐레이터 신뢰 필요&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Trustless&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;노이즈 위치&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;서버 (집계 후)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;클라이언트 (개별 데이터)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;같은 ε 에서 utility&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;높음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;낮음&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;배포 사례&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;미국 인구조사, 학술&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Apple 이모지, Google RAPPOR&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;dp-sgd-딥러닝-학습의-dp&quot;&gt;DP-SGD, 딥러닝 학습의 DP&lt;/h2&gt;
&lt;p&gt;Abadi et al. (2016) 이 제안한 &lt;strong&gt;DP-SGD (Differentially Private SGD)&lt;/strong&gt; 는 딥러닝 학습에 DP 를 적용하는 표준 방법입니다.&lt;/p&gt;
&lt;p&gt;알고리즘:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Sample&lt;/strong&gt;: 각 step 에서 mini-batch 를 Poisson sampling (각 샘플이 확률 $q = B/N$ 로 포함)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compute per-sample gradients&lt;/strong&gt;: 각 샘플에 대한 gradient 를 개별 계산&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clip&lt;/strong&gt;: 각 gradient 를 L2 norm 상한 $C$ 로 클립
$$
\bar{g}_i = g_i / \max\left(1, \frac{|g_i|_2}{C}\right)
$$&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aggregate + noise&lt;/strong&gt;: 클립된 gradient 를 합산하고 Gaussian noise 추가
$$
\tilde{g} = \frac{1}{B}\left( \sum_i \bar{g}_i + \mathcal{N}(0, \sigma^2 C^2 I) \right)
$$&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Update&lt;/strong&gt;: $\theta \leftarrow \theta - \eta \tilde{g}$&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;노이즈 배율 $\sigma$ 와 sampling 확률 $q$, 총 step 수 $T$ 로부터 최종 $(\epsilon, \delta)$ 를 계산합니다 (Moments Accountant 또는 Rényi DP accountant).&lt;/p&gt;
&lt;h3 id=&quot;opacus-pytorch&quot;&gt;Opacus (PyTorch)&lt;/h3&gt;
&lt;p&gt;Facebook Research 의 PyTorch DP 라이브러리:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; opacus &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PrivacyEngine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; MyModel()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;optimizer &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.optim.SGD(model.parameters(), &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;lr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.05&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data_loader &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.utils.data.DataLoader(dataset, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;batch_size&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;256&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;privacy_engine &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; PrivacyEngine()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model, optimizer, data_loader &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; privacy_engine.make_private(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    module&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    optimizer&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;optimizer,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    data_loader&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data_loader,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    noise_multiplier&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,       &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# σ&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    max_grad_norm&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# C&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; epoch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(N):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; batch, labels &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data_loader:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        optimizer.zero_grad()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        loss &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; criterion(model(batch), labels)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        loss.backward()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        optimizer.step()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    epsilon &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; privacy_engine.get_epsilon(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;delta&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1e-5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;epoch &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;epoch&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;: (ε=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;epsilon&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:.2f&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;, δ=1e-5)&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;dp-sgd-의-utility-손실&quot;&gt;DP-SGD 의 utility 손실&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;이미지 분류에서 clean 대비 5~15%p accuracy 손실이 흔함&lt;/li&gt;
&lt;li&gt;LLM 파인튜닝에서는 더 심각할 수 있음&lt;/li&gt;
&lt;li&gt;완화: PEFT 와 결합 (파라미터 수가 적으면 노이즈 영향 감소), 사전 학습 모델 재사용, 더 큰 batch&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;실배포-사례&quot;&gt;실배포 사례&lt;/h2&gt;
&lt;h3 id=&quot;apple-2016&quot;&gt;Apple (2016~)&lt;/h3&gt;
&lt;p&gt;iOS 10 부터 emoji 추천, QuickType 같은 기능에 LDP. Randomized response 계열, ε 는 일당 수 단위. WWDC 2016 발표.&lt;/p&gt;
&lt;h3 id=&quot;google&quot;&gt;Google&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RAPPOR&lt;/strong&gt; (Chrome, 2014)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Federated Learning + DP&lt;/strong&gt; (Gboard 다음 단어 예측)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google Health&lt;/strong&gt; 데이터 집계&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;us-census-2020&quot;&gt;US Census (2020)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;2020 년 미국 인구조사가 DP 를 공식 채택.&lt;/strong&gt; 발표된 통계에 Gaussian noise 를 추가한 것이 정치적 논란도 있었지만 역사적 이정표입니다. Epsilon 은 여러 통계별로 배분 (총 예산 약 $\epsilon = 19.6$).&lt;/p&gt;
&lt;h3 id=&quot;microsoft&quot;&gt;Microsoft&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Windows telemetry 에 LDP 적용&lt;/li&gt;
&lt;li&gt;SmartNoise 오픈소스 릴리스&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;학술-데이터셋&quot;&gt;학술 데이터셋&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;OpenDP 프로젝트 (Harvard) 가 공공 데이터셋 릴리스에 DP 도구 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;프레임워크&quot;&gt;프레임워크&lt;/h2&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;도구&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;특징&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://opacus.ai/&quot;&gt;Opacus&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;PyTorch, DP-SGD, Facebook&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/tensorflow/privacy&quot;&gt;TensorFlow Privacy&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;TF, DP-SGD, Google&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://opendp.org/&quot;&gt;OpenDP&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Harvard, rigorous verification, Rust core + Python binding&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/IBM/differential-privacy-library&quot;&gt;Diffprivlib&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;IBM, sklearn-호환 인터페이스&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://smartnoise.org/&quot;&gt;SmartNoise&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Microsoft + OpenDP, 통계 쿼리 지향&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/OpenMined/PyDP&quot;&gt;PyDP&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;OpenMined, Google DP C++ 라이브러리 wrapper&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;한계와-유의점&quot;&gt;한계와 유의점&lt;/h2&gt;
&lt;h3 id=&quot;utility-privacy-trade-off&quot;&gt;Utility-Privacy Trade-off&lt;/h3&gt;
&lt;p&gt;강력한 프라이버시 ($\epsilon$ 작게) 는 노이즈 증가 → 정확도 하락. &lt;strong&gt;“공짜 프라이버시” 는 없습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;ε-해석의-어려움&quot;&gt;ε 해석의 어려움&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;실무자에게 ε=1 이 “얼마나 안전한지” 직관 어려움&lt;/li&gt;
&lt;li&gt;$e^\epsilon$ 배 정도의 확률 차이라고 설명해도 감이 안 오는 경우 많음&lt;/li&gt;
&lt;li&gt;최근에는 &lt;strong&gt;Bayesian re-interpretation&lt;/strong&gt; 이나 &lt;strong&gt;membership inference attack&lt;/strong&gt; 성공률로 환산해 설명하려는 시도&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;데이터-카탈로그-문제&quot;&gt;데이터 카탈로그 문제&lt;/h3&gt;
&lt;p&gt;DP 는 &lt;strong&gt;각 쿼리&lt;/strong&gt; 에 대해 보장하는 것이지, 데이터셋 자체를 “완전히 익명” 만드는 것이 아닙니다. 여러 릴리스가 쌓이면 예산이 소진됩니다.&lt;/p&gt;
&lt;h3 id=&quot;결측치와-outlier&quot;&gt;결측치와 outlier&lt;/h3&gt;
&lt;p&gt;극단값이 sensitivity 를 크게 만들어 노이즈가 급증합니다. Clipping 을 잘 설계해야 함.&lt;/p&gt;
&lt;h3 id=&quot;group-privacy-는-다름&quot;&gt;Group Privacy 는 다름&lt;/h3&gt;
&lt;p&gt;DP 는 “한 개인” 을 보호합니다. 가족처럼 상관관계 있는 그룹은 별도 분석 필요.&lt;/p&gt;
&lt;h3 id=&quot;정확한-구현이-어려움&quot;&gt;정확한 구현이 어려움&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Floating-point 구현이 이론과 미묘하게 어긋나 실제로 DP 를 위반하는 사례 보고 (Mironov, 2012)&lt;/li&gt;
&lt;li&gt;Random number generator 품질 중요&lt;/li&gt;
&lt;li&gt;이 때문에 검증된 라이브러리 (Opacus, OpenDP) 사용 강력 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;관련-개념-비교&quot;&gt;관련 개념 비교&lt;/h2&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;방법&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;보장 강도&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;특징&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Identifier 제거&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;매우 약함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Netflix, AOL 사건으로 실패 증명&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;k-anonymity&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;약함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Quasi-identifier 지정 필요, 조합 attack 취약&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;l-diversity, t-closeness&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;약함~중간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;k-anonymity 개선판, 실전 여전히 어려움&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Differential Privacy&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함, 정량&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Composition 성질, 미래 공격에 대비&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Secure Multi-Party Computation (MPC)&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;계산 자체는 정확, 프로토콜 비용 큼&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Homomorphic Encryption (HE)&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;강함&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;암호화 상태 계산, 매우 느림&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Federated Learning&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;자체 보장 없음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Gradient inversion 취약, DP 와 결합 필요&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;DP + FL + Secure Aggregation&lt;/strong&gt; 조합이 실무의 표준 강화 스택입니다.&lt;/p&gt;
&lt;h2 id=&quot;참고&quot;&gt;참고&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;관련 [[federated-learning|Federated Learning]] 에 DP 를 결합한 학습&lt;/li&gt;
&lt;li&gt;관련 [[transfer-learning|Transfer Learning]] 파인튜닝 시 DP-SGD 로 개인정보 보호&lt;/li&gt;
&lt;li&gt;관련 [[classification-metrics|분류 모델 지표]] DP 학습 모델도 동일 지표로 평가&lt;/li&gt;
&lt;li&gt;정본 교과서: &lt;a href=&quot;https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf&quot;&gt;Dwork &amp;#x26; Roth 2014, The Algorithmic Foundations of Differential Privacy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Wikipedia: &lt;a href=&quot;https://en.wikipedia.org/wiki/Differential_privacy&quot;&gt;Differential privacy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;강의 자료: &lt;a href=&quot;https://cs-people.bu.edu/ads22/pubs/lecture-notes-dp.pdf&quot;&gt;Boston University CS 591&lt;/a&gt;, &lt;a href=&quot;https://opendp.org/learning&quot;&gt;Harvard OpenDP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>privacy</category><category>security</category><category>cryptography</category><category>dp</category><author>koa (김신건)</author></item><item><title>Federated Learning: 분산 학습 without central data</title><link>https://shinkeonkim.com/wiki/ml/federated-learning/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/federated-learning/</guid><pubDate>Mon, 29 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Federated Learning (FL)&lt;/strong&gt; 은 데이터를 &lt;strong&gt;중앙에 모으지 않고&lt;/strong&gt; 각 클라이언트 (edge device, 병원, 은행 등) 가 로컬 데이터로 모델을 학습한 뒤 &lt;strong&gt;모델 파라미터의 업데이트 (gradient 또는 weight)&lt;/strong&gt; 만 서버에 전송하여 집계하는 분산 학습 패러다임입니다. 서버는 원본 데이터를 절대 보지 않습니다.&lt;/p&gt;
&lt;p&gt;Google 이 2016~2017년경 Gboard (Android 키보드) 의 다음 단어 예측 학습을 위해 이 패러다임을 대중화했습니다.&lt;/p&gt;
&lt;h2 id=&quot;왜-필요한가&quot;&gt;왜 필요한가&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;개인정보 보호 규정&lt;/strong&gt;: GDPR (EU), HIPAA (US 의료), 국내 개인정보보호법 등이 원시 데이터의 외부 반출을 제한합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데이터 주권&lt;/strong&gt;: 병원 / 금융사 등 규제 산업의 데이터는 기관 내부에 머물러야 하는 경우가 많습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;엣지 컴퓨팅&lt;/strong&gt;: 모바일/IoT 에서 데이터를 서버로 계속 전송하기엔 대역폭이 부담입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;콜드 데이터&lt;/strong&gt;: 사용자 로컬에만 존재하는 데이터 (키보드 입력, 사진) 는 애초에 서버로 가지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;fedavg-기본-알고리즘&quot;&gt;FedAvg, 기본 알고리즘&lt;/h2&gt;
&lt;p&gt;McMahan et al. (2017) 의 &lt;strong&gt;FedAvg (Federated Averaging)&lt;/strong&gt; 는 FL 의 원형입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;서버 라운드 $t$&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;서버는 현재 글로벌 모델 $w_t$ 를 가지고 있습니다.&lt;/li&gt;
&lt;li&gt;서버가 $K$ 개 클라이언트를 샘플링 (전체 $N$ 개 중 일부만) 하고 $w_t$ 를 전송합니다.&lt;/li&gt;
&lt;li&gt;각 클라이언트 $k$ 는 로컬 데이터 $D_k$ 에서 $E$ epoch 만큼 SGD 를 돌려 $w_k^{t+1}$ 을 얻습니다.&lt;/li&gt;
&lt;li&gt;클라이언트가 $w_k^{t+1}$ 을 서버에 전송합니다.&lt;/li&gt;
&lt;li&gt;서버가 &lt;strong&gt;가중 평균&lt;/strong&gt;:
$$
w_{t+1} = \sum_{k=1}^{K} \frac{n_k}{n} \cdot w_k^{t+1}
$$
여기서 $n_k$ 는 클라이언트 $k$ 의 데이터 개수, $n = \sum n_k$ 입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;수백 라운드를 반복하며 글로벌 모델이 수렴합니다.&lt;/p&gt;
&lt;h3 id=&quot;왜-그냥-gradient-를-보내지-않는가&quot;&gt;왜 그냥 gradient 를 보내지 않는가&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;FedSGD&lt;/strong&gt; (1 step gradient 만 보내는 방식) 도 가능하지만 통신량이 많아집니다. FedAvg 는 &lt;strong&gt;로컬에서 여러 epoch 을 돌리고 나서 weight 을 보내므로 통신 횟수를 크게 줄입니다&lt;/strong&gt; (핵심 통찰).&lt;/p&gt;
&lt;h2 id=&quot;배포-유형&quot;&gt;배포 유형&lt;/h2&gt;
&lt;h3 id=&quot;cross-device-fl&quot;&gt;Cross-device FL&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;수백만 ~ 수억 대의 모바일/IoT 기기&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;각 기기의 데이터는 소량 (수~수백 샘플)&lt;/li&gt;
&lt;li&gt;기기의 가용성은 불안정 (배터리, 네트워크)&lt;/li&gt;
&lt;li&gt;실제 예: &lt;strong&gt;Google Gboard&lt;/strong&gt;, &lt;strong&gt;Apple Siri&lt;/strong&gt;, &lt;strong&gt;Meta Ranking&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Sampling 이 필수 (한 라운드에 전체 클라이언트 대상 불가능)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cross-silo-fl&quot;&gt;Cross-silo FL&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;소수 (2~100 개) 의 신뢰할 수 있는 기관&lt;/strong&gt; (병원, 은행)&lt;/li&gt;
&lt;li&gt;각 사일로의 데이터는 대량&lt;/li&gt;
&lt;li&gt;통신 인프라 안정적&lt;/li&gt;
&lt;li&gt;실제 예: &lt;strong&gt;NVIDIA Clara&lt;/strong&gt; (병원간 의료 영상), &lt;strong&gt;WeBank FATE&lt;/strong&gt; (금융 컨소시엄)&lt;/li&gt;
&lt;li&gt;모든 사일로가 매 라운드 참여 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;주요-도전-과제&quot;&gt;주요 도전 과제&lt;/h2&gt;
&lt;h3 id=&quot;1-non-iid-데이터-statistical-heterogeneity&quot;&gt;1. Non-IID 데이터 (Statistical Heterogeneity)&lt;/h3&gt;
&lt;p&gt;클라이언트마다 데이터 분포가 다릅니다. 예: 어떤 사용자는 영어로만, 어떤 사용자는 한국어로만 타이핑. 이 경우:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;각 클라이언트의 local update 가 서로 다른 방향을 가리킴 (&lt;strong&gt;client drift&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;단순 평균이 잘못된 방향으로 이동&lt;/li&gt;
&lt;li&gt;수렴 속도 저하, 최종 성능 하락&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-system-heterogeneity&quot;&gt;2. System Heterogeneity&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트마다 컴퓨팅 성능 다름 (고사양 폰 vs 저사양 폰)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Straggler&lt;/strong&gt;: 느린 클라이언트 때문에 라운드가 지연됨&lt;/li&gt;
&lt;li&gt;배터리, 네트워크 상태로 라운드 중 이탈 (&lt;strong&gt;client dropout&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-communication-cost&quot;&gt;3. Communication Cost&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;대형 모델 (수 GB) 을 매 라운드 수백만 클라이언트가 다운로드/업로드&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model compression&lt;/strong&gt;, &lt;strong&gt;quantization&lt;/strong&gt;, &lt;strong&gt;sparsification&lt;/strong&gt; 으로 완화&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FetchSGD&lt;/strong&gt;, &lt;strong&gt;top-K sparsification&lt;/strong&gt; 등 통신 최적화 알고리즘&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-privacy-공격&quot;&gt;4. Privacy 공격&lt;/h3&gt;
&lt;p&gt;Raw 데이터를 보내지 않아도 gradient 자체에서 정보가 새어 나올 수 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Gradient inversion&lt;/strong&gt;: gradient 로부터 원본 이미지 복원 (Zhu et al., 2019 “Deep Leakage from Gradients”)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Membership inference&lt;/strong&gt;: 특정 샘플이 학습에 쓰였는지 추론&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;FL 만으로는 프라이버시가 보장되지 않으며, DP 나 Secure Aggregation 을 함께 써야 합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;주요-변형&quot;&gt;주요 변형&lt;/h2&gt;
&lt;h3 id=&quot;fedprox-li-et-al-2020&quot;&gt;FedProx (Li et al., 2020)&lt;/h3&gt;
&lt;p&gt;Non-IID 대응. 로컬 objective 에 &lt;strong&gt;proximal term&lt;/strong&gt; 추가:&lt;/p&gt;
&lt;p&gt;$$
\min_{w} F_k(w) + \frac{\mu}{2} | w - w_t |^2
$$&lt;/p&gt;
&lt;p&gt;$\mu$ 는 하이퍼파라미터. 로컬 업데이트가 글로벌 모델에서 너무 멀리 벗어나지 못하도록 제약. Client drift 완화.&lt;/p&gt;
&lt;h3 id=&quot;fedyogi--fedadam-reddi-et-al-2020&quot;&gt;FedYogi / FedAdam (Reddi et al., 2020)&lt;/h3&gt;
&lt;p&gt;서버에서 &lt;strong&gt;adaptive optimizer&lt;/strong&gt; 사용. FedAvg 는 서버측에서 단순 평균이지만, FedYogi 는 Yogi (Adam 변형) 를 서버에 적용해 수렴을 안정화합니다.&lt;/p&gt;
&lt;h3 id=&quot;scaffold-karimireddy-et-al-2020&quot;&gt;SCAFFOLD (Karimireddy et al., 2020)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Control variate&lt;/strong&gt; 를 도입하여 client drift 를 correction. 클라이언트가 로컬 gradient 방향을 조정하는 벡터 $c_k$ 를 관리:&lt;/p&gt;
&lt;p&gt;$$
w_k \leftarrow w_k - \eta (g_k - c_k + c)
$$&lt;/p&gt;
&lt;p&gt;Non-IID 에서 FedAvg 보다 훨씬 빨리 수렴.&lt;/p&gt;
&lt;h3 id=&quot;개인화-fl-personalized-fl&quot;&gt;개인화 FL (Personalized FL)&lt;/h3&gt;
&lt;p&gt;모든 클라이언트가 같은 글로벌 모델을 쓰는 대신, &lt;strong&gt;글로벌 모델 + 로컬 튜닝&lt;/strong&gt; 형태:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Per-FedAvg&lt;/strong&gt;: MAML 계열, 글로벌 모델을 각 클라이언트가 한 step 파인튜닝&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pFedMe&lt;/strong&gt;: 클라이언트가 자기 모델 + 정규화 (글로벌 근처)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ditto&lt;/strong&gt;: 글로벌 + 개인 모델 병존, 두 목적을 함께 최적화&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;privacy-enhancing-techniques&quot;&gt;Privacy-Enhancing Techniques&lt;/h2&gt;
&lt;h3 id=&quot;differential-privacy-dp&quot;&gt;Differential Privacy (DP)&lt;/h3&gt;
&lt;p&gt;Gradient/weight 에 &lt;strong&gt;calibrated noise&lt;/strong&gt; 를 추가하여, 특정 개인의 데이터가 있었는지 확률적으로 알 수 없게 만듭니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DP-SGD&lt;/strong&gt; (Abadi et al., 2016):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Gradient 를 클립 (norm 상한 $C$)&lt;/li&gt;
&lt;li&gt;Gaussian noise $\mathcal{N}(0, \sigma^2 C^2)$ 추가&lt;/li&gt;
&lt;li&gt;Privacy budget $(\epsilon, \delta)$ 로 정량 관리&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;FL 에서는 &lt;strong&gt;client-level DP&lt;/strong&gt; (한 클라이언트 전체가 있었는지 감추기) 와 &lt;strong&gt;sample-level DP&lt;/strong&gt; (한 샘플이 있었는지 감추기) 두 가지 granularity 가 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;secure-aggregation&quot;&gt;Secure Aggregation&lt;/h3&gt;
&lt;p&gt;Bonawitz et al. (2017) 의 프로토콜. 클라이언트들이 자기 업데이트를 &lt;strong&gt;cryptographic masking&lt;/strong&gt; 으로 감춰서 서버가 볼 때는 &lt;strong&gt;합만&lt;/strong&gt; 보이고 개별 값은 못 봅니다.&lt;/p&gt;
&lt;p&gt;핵심 아이디어: 클라이언트 쌍 사이에 secret share 를 교환하여 서로의 mask 가 합쳐지면 상쇄되도록 설계. Dropout 이 발생해도 threshold secret sharing 으로 복구 가능합니다.&lt;/p&gt;
&lt;h3 id=&quot;homomorphic-encryption-he&quot;&gt;Homomorphic Encryption (HE)&lt;/h3&gt;
&lt;p&gt;암호화된 상태로 덧셈/곱셈 연산 가능. Gradient 를 암호화한 채로 서버가 집계, 클라이언트만 복호화. 계산 비용이 매우 크지만 강력한 프라이버시 보장.&lt;/p&gt;
&lt;h2 id=&quot;프레임워크&quot;&gt;프레임워크&lt;/h2&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;프레임워크&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;개발/유지&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;특징&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://flower.dev/&quot;&gt;Flower&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;오픈소스 (Adap)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;프레임워크 애그노스틱 (PyTorch, TF, JAX), 실전 배포 지향&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://www.tensorflow.org/federated&quot;&gt;TensorFlow Federated (TFF)&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Google&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;시뮬레이션 중심, Federated Analytics 강점&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/OpenMined/PySyft&quot;&gt;PySyft&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;OpenMined&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;프라이버시 도구 통합 (HE, MPC, DP)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://fate.fedai.org/&quot;&gt;FATE&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;WeBank&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Cross-silo 산업용, Chinese fintech 배포 사례 다수&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/NVIDIA/NVFlare&quot;&gt;NVFlare&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Clara/의료 도메인, 프로덕션 지향&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://fedml.ai/&quot;&gt;FedML&lt;/a&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FedML Inc.&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;학술 + 산업 겸용 플랫폼&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;실전-코드-flower-예시&quot;&gt;실전 코드 (Flower 예시)&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; flwr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 클라이언트 정의&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; MyClient&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;client&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;NumPyClient&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; get_parameters&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, config):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [p.detach().cpu().numpy() &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model.parameters()]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; set_parameters&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, parameters):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p, new &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; zip&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(model.parameters(), parameters):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            p.data &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.tensor(new)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; fit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, parameters, config):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.set_parameters(parameters)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        train(model, local_dataloader, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;epochs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;config[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;local_epochs&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.get_parameters({}), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(local_dataset), {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; evaluate&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(self, parameters, config):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.set_parameters(parameters)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        loss, acc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; test(model, val_dataloader)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; float&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(loss), &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(val_dataset), {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;accuracy&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: acc}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fl.client.start_numpy_client(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;server_address&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;server:8080&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;client&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;MyClient())&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 서버 정의&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;strategy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fl.server.strategy.FedAvg(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    fraction_fit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 매 라운드 10% 샘플링&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    min_fit_clients&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    min_available_clients&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    on_fit_config_fn&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=lambda&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rnd: {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;local_epochs&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fl.server.start_server(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    server_address&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0.0.0.0:8080&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    config&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fl.server.ServerConfig(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;num_rounds&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    strategy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;strategy,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;실전-배포-사례&quot;&gt;실전 배포 사례&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Google Gboard&lt;/strong&gt;: 다음 단어 예측, 이모지 추천 모두 FL 로 학습 (2017~)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apple&lt;/strong&gt;: Differential Privacy 기반 Emoji 추천, Siri 개선&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NVIDIA Clara&lt;/strong&gt;: COVID-19 흉부 CT 진단 모델을 30 개 병원 협업 학습 (2020)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WeBank FATE&lt;/strong&gt;: 은행간 신용평가 모델&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Meta&lt;/strong&gt;: 광고 랭킹 모델의 프라이버시 강화 학습&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;한계와-유의점&quot;&gt;한계와 유의점&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;극심한 non-IID&lt;/strong&gt; 에서는 개인화 FL 을 쓰거나 centralized 로 회귀하는 것이 낫습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;모델 성능&lt;/strong&gt; 은 대개 centralized 대비 몇% 낮습니다. 프라이버시 규제 만족이 목적일 때 받아들일 만한 트레이드오프입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;디버깅이 어렵습니다&lt;/strong&gt;. 클라이언트 데이터를 볼 수 없으므로 로컬 이슈 진단이 힘듭니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;공격 모델을 명시&lt;/strong&gt; 해야 합니다. Honest-but-curious 서버 vs malicious 서버, 개별 클라이언트 vs 담합 공격 등.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;참고&quot;&gt;참고&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;관련 [[differential-privacy|Differential Privacy]] 를 결합하면 client-level / sample-level 프라이버시가 정량 보장됩니다&lt;/li&gt;
&lt;li&gt;관련 [[transfer-learning|Transfer Learning]] 을 클라이언트별 개인화에 결합하기도 합니다&lt;/li&gt;
&lt;li&gt;관련 [[classification-metrics|분류 모델 지표]] 로 각 라운드 성능 평가&lt;/li&gt;
&lt;li&gt;Google AI Blog: &lt;a href=&quot;https://ai.googleblog.com/2017/04/federated-learning-collaborative.html&quot;&gt;Federated Learning: Collaborative Machine Learning without Centralized Training Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Kairouz et al. 2021, &lt;a href=&quot;https://arxiv.org/abs/1912.04977&quot;&gt;Advances and Open Problems in Federated Learning&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>distributed</category><category>privacy</category><category>federated-learning</category><category>edge</category><author>koa (김신건)</author></item><item><title>Transfer Learning: pre-training, fine-tuning, domain adaptation</title><link>https://shinkeonkim.com/wiki/ml/transfer-learning/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/transfer-learning/</guid><pubDate>Mon, 29 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Transfer Learning&lt;/strong&gt; 은 &lt;strong&gt;source task/domain 에서 학습한 지식을 target task/domain 에 재사용&lt;/strong&gt; 하여 학습 효율을 높이는 패러다임입니다. 대규모 데이터로 사전 학습한 모델을 소량의 태스크 특화 데이터로 미세 조정하는 것이 대표적입니다.&lt;/p&gt;
&lt;p&gt;핵심 가정: &lt;strong&gt;저수준 특징 (edge, syllable, phoneme) 은 대체로 도메인/태스크에 관계없이 유용하다.&lt;/strong&gt; 이 가정이 성립할 때 처음부터 학습하는 것보다 훨씬 적은 데이터와 시간으로 좋은 성능을 얻을 수 있습니다.&lt;/p&gt;
&lt;h2 id=&quot;왜-필요한가&quot;&gt;왜 필요한가&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;데이터 부족&lt;/strong&gt;: target task 데이터가 수천 개인데 처음부터 CNN/Transformer 를 학습하면 과적합 심함&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;계산 비용&lt;/strong&gt;: LLM 을 처음부터 학습하는 것은 조 단위 예산이 필요, 사전 학습 모델 재사용이 현실적&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;범용 표현 학습&lt;/strong&gt;: ImageNet 이나 대규모 웹 코퍼스로 학습한 표현은 이후 대부분의 downstream 태스크에 유용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;고전-분류-pan--yang-2010&quot;&gt;고전 분류 (Pan &amp;#x26; Yang, 2010)&lt;/h2&gt;
&lt;p&gt;Source 와 target 의 &lt;strong&gt;도메인 (input 분포)&lt;/strong&gt; 과 &lt;strong&gt;태스크 (output/label)&lt;/strong&gt; 차이 여부에 따라:&lt;/p&gt;





































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;유형&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Source 도메인&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Source 태스크&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Target 도메인&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;Target 태스크&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;예&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Inductive Transfer&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;같음/유사&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;다름&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;같음&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;다름 (라벨 있음)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;ImageNet 분류 → 의료 영상 분류&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Transductive Transfer (Domain Adaptation)&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;다름&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;같음&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;다름&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;같음&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;서구인 얼굴 인식 → 아시아인 얼굴 인식&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Unsupervised Transfer&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;다름&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;다름&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;다름&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;다름 (라벨 없음)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;클러스터링 지식 전이&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;딥러닝 시대에는 이 구분이 흐려지고 있으며, 실질적으로는 &lt;strong&gt;“대규모 사전 학습 + downstream 파인튜닝”&lt;/strong&gt; 이라는 한 가지 패러다임이 지배적입니다.&lt;/p&gt;
&lt;h2 id=&quot;딥러닝-관점-레이어별-전이-가능성&quot;&gt;딥러닝 관점: 레이어별 전이 가능성&lt;/h2&gt;
&lt;p&gt;Yosinski et al. (2014) 는 AlexNet 의 각 레이어를 하나씩 얼려 (freeze) target 태스크에 옮기는 실험으로 다음을 밝혔습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;저수준 레이어 (conv1, conv2)&lt;/strong&gt;: 에지, 색깔 필터. &lt;strong&gt;일반적&lt;/strong&gt; 이라 대부분의 태스크에 잘 전이됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;중간 레이어&lt;/strong&gt;: 조각, 형태. &lt;strong&gt;부분적&lt;/strong&gt; 으로 전이됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;고수준 레이어 (fc7, fc8)&lt;/strong&gt;: 클래스 특화. 원본 태스크에 강하게 특화되어 있어 &lt;strong&gt;잘 전이되지 않습니다&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 통찰이 오늘날 대부분의 fine-tuning 전략의 근거입니다.&lt;/p&gt;
&lt;h2 id=&quot;fine-tuning-전략&quot;&gt;Fine-tuning 전략&lt;/h2&gt;
&lt;h3 id=&quot;1-feature-extractor&quot;&gt;1. Feature Extractor&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;사전 학습 모델 전체를 freeze&lt;/strong&gt;, 마지막에 새 head (선형 분류기) 만 학습합니다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torchvision.models &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; resnet50&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; resnet50(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;weights&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;IMAGENET1K_V2&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model.parameters():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    p.requires_grad &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; False&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 새 head&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model.fc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.nn.Linear(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2048&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, num_target_classes)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# model.fc.parameters() 만 학습&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;데이터가 극히 적을 때 유리&lt;/li&gt;
&lt;li&gt;학습 빠르고 안정적이지만 성능 상한이 낮음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-full-fine-tuning&quot;&gt;2. Full Fine-tuning&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;모든 파라미터를 학습&lt;/strong&gt;, 다만 작은 learning rate (예: 1e-5) 사용.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; model.parameters():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    p.requires_grad &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; True&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;optimizer &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch.optim.AdamW(model.parameters(), &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;lr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1e-5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;데이터가 충분할 때 최고 성능&lt;/li&gt;
&lt;li&gt;대신 catastrophic forgetting 위험 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-discriminative-fine-tuning-ulmfit&quot;&gt;3. Discriminative Fine-tuning (ULMFiT)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;레이어별로 다른 learning rate&lt;/strong&gt;. 낮은 레이어는 작은 LR, 높은 레이어는 큰 LR.&lt;/p&gt;
&lt;p&gt;$$
\eta^{(l-1)} = \eta^{(l)} / 2.6
$$&lt;/p&gt;
&lt;p&gt;Howard &amp;#x26; Ruder (2018) 이 ULMFiT 에서 제안했고, NLP 파인튜닝의 기준이 되었습니다.&lt;/p&gt;
&lt;h3 id=&quot;4-gradual-unfreezing&quot;&gt;4. Gradual Unfreezing&lt;/h3&gt;
&lt;p&gt;먼저 head 만 학습 (다른 레이어 freeze), 그 다음 마지막 레이어를 unfreeze, 그 다음 그 아래 레이어를 unfreeze 하는 식으로 &lt;strong&gt;레이어별로 서서히 녹입니다&lt;/strong&gt;. Catastrophic forgetting 완화에 효과적입니다.&lt;/p&gt;
&lt;h2 id=&quot;foundation-models&quot;&gt;Foundation Models&lt;/h2&gt;
&lt;p&gt;Bommasani et al. (2021) 는 다음 조건을 만족하는 모델을 &lt;strong&gt;Foundation Model&lt;/strong&gt; 로 명명했습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;대규모 self-supervised pre-training&lt;/li&gt;
&lt;li&gt;광범위한 downstream 태스크에 적응 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;대표: &lt;strong&gt;BERT, GPT, T5, CLIP, ViT, DINO, SAM, LLaMA&lt;/strong&gt;. Transfer learning 이 이제 특별한 기법이 아니라 &lt;strong&gt;AI 시스템 구축의 기본 방식&lt;/strong&gt; 이 되었다는 관점 전환입니다.&lt;/p&gt;
&lt;h2 id=&quot;peft-parameter-efficient-fine-tuning&quot;&gt;PEFT (Parameter-Efficient Fine-Tuning)&lt;/h2&gt;
&lt;p&gt;Foundation model 이 수십억 파라미터 규모가 되면서 full fine-tuning 은 GPU 메모리도, 저장 공간도 감당하기 어려워졌습니다. &lt;strong&gt;일부 파라미터만 학습&lt;/strong&gt; 하는 기법들이 나왔습니다.&lt;/p&gt;
&lt;h3 id=&quot;adapter-houlsby-et-al-2019&quot;&gt;Adapter (Houlsby et al., 2019)&lt;/h3&gt;
&lt;p&gt;Transformer 블록 안에 &lt;strong&gt;작은 병목 레이어&lt;/strong&gt; 를 삽입, 원본 파라미터는 freeze, adapter 만 학습:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;x → [Layer Norm] → [Attention] → [Add] → [Adapter (down → nonlinear → up)] → [FFN] → [Add] → [Adapter] → out&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;전체의 3~5% 정도만 학습해도 full fine-tuning 에 근접한 성능.&lt;/p&gt;
&lt;h3 id=&quot;lora-hu-et-al-2021&quot;&gt;LoRA (Hu et al., 2021)&lt;/h3&gt;
&lt;p&gt;가중치 업데이트 $\Delta W$ 를 &lt;strong&gt;low-rank 분해&lt;/strong&gt; 로 근사:&lt;/p&gt;
&lt;p&gt;$$
W’ = W + \Delta W = W + BA, \quad A \in \mathbb{R}^{r \times k}, B \in \mathbb{R}^{d \times r}
$$&lt;/p&gt;
&lt;p&gt;$r \ll \min(d, k)$ 이면 $BA$ 가 $\Delta W$ 를 근사합니다. 학습 파라미터는 $r(d+k)$ 개로 크게 줄어들고, inference 때는 $W + BA$ 를 병합하면 추가 지연이 없습니다. 오늘날 LLM 파인튜닝의 사실상 표준입니다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# peft 라이브러리 예&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; peft &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LoraConfig, get_peft_model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;config &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LoraConfig(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    r&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,                          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# rank&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    lora_alpha&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,                &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# scaling factor&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    target_modules&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;q_proj&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;v_proj&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    lora_dropout&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.05&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    bias&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;none&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; get_peft_model(base_model, config)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;QLoRA&lt;/strong&gt; (Dettmers et al., 2023) 는 4-bit 양자화 + LoRA 로 GPU 메모리를 더 줄였습니다.&lt;/p&gt;
&lt;h3 id=&quot;prompt-tuning--prefix-tuning&quot;&gt;Prompt Tuning / Prefix Tuning&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;모델은 완전 freeze&lt;/strong&gt;, 입력에 학습 가능한 &lt;strong&gt;soft token 벡터&lt;/strong&gt; 만 추가:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prompt Tuning&lt;/strong&gt; (Lester et al., 2021): 입력 앞에 학습 가능한 임베딩 몇 개 추가&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prefix Tuning&lt;/strong&gt; (Li &amp;#x26; Liang, 2021): 각 Transformer 레이어의 key/value 앞에 접두 벡터 삽입&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;파라미터 수가 극히 작지만 (&amp;#x3C; 0.1%) 매우 큰 모델에서만 효과적입니다.&lt;/p&gt;
&lt;h3 id=&quot;bitfit-ben-zaken-et-al-2021&quot;&gt;BitFit (Ben-Zaken et al., 2021)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;bias 파라미터만 학습&lt;/strong&gt;. 극단적으로 적은 파라미터로도 특정 태스크에서 경쟁력 있음.&lt;/p&gt;
&lt;h2 id=&quot;domain-adaptation&quot;&gt;Domain Adaptation&lt;/h2&gt;
&lt;p&gt;Source 와 target 의 &lt;strong&gt;입력 분포가 다를 때&lt;/strong&gt; 사용됩니다.&lt;/p&gt;
&lt;h3 id=&quot;feature-alignment&quot;&gt;Feature Alignment&lt;/h3&gt;
&lt;p&gt;두 도메인의 feature 분포를 정렬:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MMD (Maximum Mean Discrepancy)&lt;/strong&gt;: RKHS 에서 두 분포의 평균 벡터 거리 최소화&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CORAL (Correlation Alignment)&lt;/strong&gt;: 공분산 매트릭스 정렬&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;adversarial-domain-adaptation-dann&quot;&gt;Adversarial Domain Adaptation (DANN)&lt;/h3&gt;
&lt;p&gt;Ganin et al. (2015) 의 DANN 은 두 도메인의 feature 를 &lt;strong&gt;discriminator 가 구분 못하게&lt;/strong&gt; 학습시킵니다.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;feature extractor → classifier (label 예측, 정상 gradient)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                 → domain discriminator (source vs target, gradient reversal)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Gradient Reversal Layer (GRL) 로 discriminator loss 의 gradient 를 뒤집어 feature 를 domain-invariant 하게 만듭니다.&lt;/p&gt;
&lt;h3 id=&quot;self-training--pseudo-labeling&quot;&gt;Self-training / Pseudo-labeling&lt;/h3&gt;
&lt;p&gt;Target 데이터의 라벨을 모델 예측으로 채우고 (confidence 높은 것만), 다시 학습. 반복.&lt;/p&gt;
&lt;h2 id=&quot;catastrophic-forgetting&quot;&gt;Catastrophic Forgetting&lt;/h2&gt;
&lt;p&gt;Fine-tuning 시 사전 학습에서 얻은 일반 지식이 &lt;strong&gt;소실&lt;/strong&gt; 되는 현상. 특히 target 데이터가 적을 때 심각합니다.&lt;/p&gt;
&lt;p&gt;완화 기법:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;작은 learning rate + 짧은 학습&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Elastic Weight Consolidation (EWC)&lt;/strong&gt; (Kirkpatrick et al., 2017): 원본 파라미터 근처에 머무르도록 L2-regularization, Fisher Information 으로 중요도 가중&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rehearsal&lt;/strong&gt;: 원본 태스크 샘플을 fine-tuning 중에도 계속 노출&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PEFT (adapter, LoRA)&lt;/strong&gt;: 원본 파라미터는 그대로 두므로 자연스럽게 forgetting 방지&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;negative-transfer&quot;&gt;Negative Transfer&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;source 와 target 이 관련 없으면 오히려 성능 하락&lt;/strong&gt;. 예: 자연 이미지 사전 학습 → 위성 이미지 태스크 는 도움이 되지만, 자연 이미지 사전 학습 → 의료 X-ray 태스크는 부정적 전이 사례가 알려져 있습니다.&lt;/p&gt;
&lt;p&gt;방지책:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Source 선택 시 domain similarity 검토 (feature 통계, MMD 로 측정)&lt;/li&gt;
&lt;li&gt;모델 여러 개 후보 중 target 검증으로 선택&lt;/li&gt;
&lt;li&gt;애매하면 사전 학습 도메인이 넓은 foundation model 사용 (CLIP, DINOv2 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;실전-예시&quot;&gt;실전 예시&lt;/h2&gt;
&lt;h3 id=&quot;nlp-bert-fine-tuning&quot;&gt;NLP: BERT fine-tuning&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; transformers &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; BertForSequenceClassification, Trainer, TrainingArguments&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; BertForSequenceClassification.from_pretrained(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;bert-base-uncased&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;num_labels&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;training_args &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; TrainingArguments(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    output_dir&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;./results&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    num_train_epochs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    per_device_train_batch_size&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    learning_rate&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2e-5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,           &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# BERT paper 권장&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    warmup_steps&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;500&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    weight_decay&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.01&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;trainer &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Trainer(&lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;model&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;training_args, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;train_dataset&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ds, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;trainer.train()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;vision-vit-fine-tuning&quot;&gt;Vision: ViT fine-tuning&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; transformers &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ViTForImageClassification&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ViTForImageClassification.from_pretrained(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;google/vit-base-patch16-224&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    num_labels&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;num_classes,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    ignore_mismatched_sizes&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 새 head 필요&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;llm-lora-fine-tuning&quot;&gt;LLM: LoRA fine-tuning&lt;/h3&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; peft &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LoraConfig, get_peft_model, TaskType&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;config &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; LoraConfig(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    task_type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;TaskType.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CAUSAL_LM&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    r&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    lora_alpha&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    lora_dropout&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    target_modules&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;q_proj&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;k_proj&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;v_proj&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;o_proj&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; get_peft_model(base_llm, config)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model.print_trainable_parameters()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# trainable: ~4M / total: ~7B (0.06%)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;참고&quot;&gt;참고&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;관련 지표: [[classification-metrics|분류 모델 지표]]&lt;/li&gt;
&lt;li&gt;관련 시스템: [[federated-learning|Federated Learning]] 에서도 pretrained model 을 초기점으로 씁니다&lt;/li&gt;
&lt;li&gt;관련 평가: [[helm-llm-benchmark|HELM]] 은 여러 downstream 태스크에서 foundation model 을 평가합니다&lt;/li&gt;
&lt;li&gt;HuggingFace: &lt;a href=&quot;https://github.com/huggingface/peft&quot;&gt;PEFT library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Paper: &lt;a href=&quot;https://arxiv.org/abs/2108.07258&quot;&gt;Bommasani et al. 2021, Foundation Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Survey: &lt;a href=&quot;https://arxiv.org/abs/1911.02685&quot;&gt;A Comprehensive Survey on Transfer Learning&lt;/a&gt; (Zhuang et al., 2020)&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>deep-learning</category><category>transfer-learning</category><category>fine-tuning</category><category>foundation-model</category><author>koa (김신건)</author></item><item><title>분류 모델 지표: Confusion Matrix, Precision, Recall, F1</title><link>https://shinkeonkim.com/wiki/ml/classification-metrics/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/classification-metrics/</guid><pubDate>Mon, 29 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;분류 (classification) 모델의 성능을 정량화하는 지표들입니다. 이진 분류를 기준으로 하며, multi-class 로 확장하는 방법도 함께 다룹니다. 핵심 출발점은 &lt;strong&gt;Confusion Matrix&lt;/strong&gt; 이고, 여기서 accuracy, precision, recall, F1, ROC/PR 등 모든 지표가 유도됩니다.&lt;/p&gt;
&lt;h2 id=&quot;confusion-matrix&quot;&gt;Confusion Matrix&lt;/h2&gt;
&lt;p&gt;이진 분류의 예측 결과를 2x2 표로 정리한 것입니다. 스팸 필터를 예로 들면:&lt;/p&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;예측: Positive (스팸)&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;예측: Negative (정상)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;실제: Positive (스팸)&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;TP&lt;/strong&gt; (True Positive)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;FN&lt;/strong&gt; (False Negative)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;실제: Negative (정상)&lt;/strong&gt;&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;FP&lt;/strong&gt; (False Positive)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;TN&lt;/strong&gt; (True Negative)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TP (True Positive)&lt;/strong&gt;: 스팸을 스팸이라고 맞춘 경우&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TN (True Negative)&lt;/strong&gt;: 정상을 정상이라고 맞춘 경우&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FP (False Positive)&lt;/strong&gt;: 정상을 스팸이라고 잘못 예측 (Type I error)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FN (False Negative)&lt;/strong&gt;: 스팸을 정상이라고 놓친 경우 (Type II error)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;[!TIP]
&lt;strong&gt;First letter (T/F)&lt;/strong&gt; 은 예측이 맞았는가 (True/False), &lt;strong&gt;second letter (P/N)&lt;/strong&gt; 은 모델이 무엇으로 예측했는가 (Positive/Negative) 입니다. “FP = 모델은 Positive 라고 예측, 실제는 반대라 False” 로 읽으면 헷갈리지 않습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;기본-지표&quot;&gt;기본 지표&lt;/h2&gt;
&lt;h3 id=&quot;accuracy&quot;&gt;Accuracy&lt;/h3&gt;
&lt;p&gt;$$
\text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN}
$$&lt;/p&gt;
&lt;p&gt;전체 예측 중 맞은 비율. 직관적이지만 &lt;strong&gt;class imbalance&lt;/strong&gt; 에 취약합니다. 99% 정상 메일 데이터에서 “모두 정상” 이라고 예측해도 accuracy 99% 가 나옵니다.&lt;/p&gt;
&lt;h3 id=&quot;precision-정밀도&quot;&gt;Precision (정밀도)&lt;/h3&gt;
&lt;p&gt;$$
\text{Precision} = \frac{TP}{TP + FP}
$$&lt;/p&gt;
&lt;p&gt;모델이 Positive 라고 예측한 것 중 실제로 Positive 인 비율. “&lt;strong&gt;모델이 Positive 라고 외칠 때 얼마나 믿을 만한가?&lt;/strong&gt;”&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;스팸 필터: precision 낮으면 정상 메일이 스팸함으로 감 → 사용자 불만&lt;/li&gt;
&lt;li&gt;추천 시스템: precision 낮으면 관심 없는 상품 추천 → 이탈&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;recall-재현율-sensitivity-tpr&quot;&gt;Recall (재현율, Sensitivity, TPR)&lt;/h3&gt;
&lt;p&gt;$$
\text{Recall} = \frac{TP}{TP + FN}
$$&lt;/p&gt;
&lt;p&gt;실제 Positive 중 모델이 맞춘 비율. “&lt;strong&gt;진짜 Positive 를 얼마나 놓치지 않고 잡았는가?&lt;/strong&gt;”&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;암 진단: recall 낮으면 환자를 놓침 → 치명적&lt;/li&gt;
&lt;li&gt;이상 거래 탐지: recall 낮으면 사기를 놓침 → 손실&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;specificity-tnr&quot;&gt;Specificity (TNR)&lt;/h3&gt;
&lt;p&gt;$$
\text{Specificity} = \frac{TN}{TN + FP}
$$&lt;/p&gt;
&lt;p&gt;실제 Negative 중 Negative 로 맞춘 비율. 의료 통계에서 자주 쓰이며 ROC 곡선의 x 축을 구성합니다.&lt;/p&gt;
&lt;h2 id=&quot;precision-vs-recall-트레이드오프&quot;&gt;Precision vs Recall 트레이드오프&lt;/h2&gt;
&lt;p&gt;두 지표는 대체로 상충됩니다. 이유는 대부분의 확률 모델이 &lt;strong&gt;임계값 (threshold)&lt;/strong&gt; 에 따라 결정을 내리기 때문입니다. Threshold 를 낮추면 (더 많이 Positive 로 예측):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Recall ↑ (놓치는 것 감소)&lt;/li&gt;
&lt;li&gt;Precision ↓ (틀린 Positive 증가)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;반대로 threshold 를 높이면:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Precision ↑ (확신 있을 때만 Positive)&lt;/li&gt;
&lt;li&gt;Recall ↓ (놓치는 것 증가)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;어느 쪽을 우선할지는 도메인 비용 함수&lt;/strong&gt; 에 따라 다릅니다.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;상황&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;우선 지표&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;이유&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;스팸 필터&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Precision&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;정상 메일 놓치는 비용 큼&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;추천 시스템&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Precision&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;관심 없는 추천은 사용자 피로&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;암 진단 스크리닝&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Recall&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;놓치는 비용 (사망) 극심&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;사기 탐지&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Recall&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;놓친 사기의 손실 큼&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;검색 랭킹&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Precision@K&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;상위 K 개만 노출됨&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;f1-score&quot;&gt;F1 Score&lt;/h2&gt;
&lt;p&gt;Precision 과 Recall 의 조화 평균 (harmonic mean):&lt;/p&gt;
&lt;p&gt;$$
F_1 = 2 \cdot \frac{\text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}}
$$&lt;/p&gt;
&lt;p&gt;산술 평균 대신 조화 평균을 쓰는 이유는 &lt;strong&gt;한쪽이 극단적으로 낮을 때 벌점을 주기 위함&lt;/strong&gt; 입니다. Precision=1.0, Recall=0.01 이면 산술 평균은 0.505 지만 F1 은 0.0198 로 곤두박질칩니다.&lt;/p&gt;
&lt;h3 id=&quot;f-beta&quot;&gt;F-beta&lt;/h3&gt;
&lt;p&gt;Precision 과 Recall 을 다른 비중으로 가중:&lt;/p&gt;
&lt;p&gt;$$
F_\beta = (1 + \beta^2) \cdot \frac{P \cdot R}{\beta^2 \cdot P + R}
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$\beta = 1$ → F1 (동일 가중)&lt;/li&gt;
&lt;li&gt;$\beta = 2$ → F2 (recall 을 2 배 중시)&lt;/li&gt;
&lt;li&gt;$\beta = 0.5$ → F0.5 (precision 을 2 배 중시)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$\beta$ 는 “recall 을 precision 대비 몇 배로 중요하게 보는가” 의 계수입니다.&lt;/p&gt;
&lt;h2 id=&quot;roc-곡선과-auc&quot;&gt;ROC 곡선과 AUC&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;ROC (Receiver Operating Characteristic) 곡선&lt;/strong&gt;: 다양한 threshold 에서 (FPR, TPR) 을 그린 곡선.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;x축: &lt;strong&gt;FPR&lt;/strong&gt; (False Positive Rate) = FP / (FP + TN) = 1 - Specificity&lt;/li&gt;
&lt;li&gt;y축: &lt;strong&gt;TPR&lt;/strong&gt; (True Positive Rate) = Recall&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;AUC-ROC&lt;/strong&gt; 는 이 곡선 아래 면적입니다. 0.5 는 random, 1.0 은 완벽. 직관적 해석: &lt;strong&gt;랜덤한 positive 샘플과 negative 샘플을 뽑았을 때, positive 샘플의 점수가 더 높을 확률&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;roc-의-한계-극심한-imbalance&quot;&gt;ROC 의 한계, 극심한 imbalance&lt;/h3&gt;
&lt;p&gt;Negative 가 압도적으로 많을 때 (예: 사기 거래 1% vs 정상 99%), FPR 이 0.01 만 되어도 절대 개수로는 엄청난 오탐입니다. 그러나 ROC 곡선은 FPR 을 %로 표현하므로 오탐의 심각성이 시각적으로 감춰집니다.&lt;/p&gt;
&lt;h2 id=&quot;pr-곡선과-auc-pr&quot;&gt;PR 곡선과 AUC-PR&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Precision-Recall 곡선&lt;/strong&gt;: threshold 별 (Recall, Precision) 을 그린 곡선.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AUC-PR&lt;/strong&gt; 은 그 아래 면적이며, &lt;strong&gt;imbalanced dataset 에서 ROC 보다 정보량이 많습니다&lt;/strong&gt; (&lt;a href=&quot;https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0118432&quot;&gt;Saito &amp;#x26; Rehmsmeier, 2015&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;경험칙:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;양쪽 클래스가 비슷하게 있음 → ROC/AUC 로 충분&lt;/li&gt;
&lt;li&gt;Positive 가 희소함 (예: &amp;#x3C;10%) → &lt;strong&gt;PR 곡선 / AUC-PR&lt;/strong&gt; 을 우선&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;multi-class-확장&quot;&gt;Multi-class 확장&lt;/h2&gt;
&lt;p&gt;이진의 precision/recall/F1 을 여러 클래스로 확장할 때 세 가지 평균 방식이 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;macro-average&quot;&gt;Macro-average&lt;/h3&gt;
&lt;p&gt;각 클래스별 지표를 구한 뒤 &lt;strong&gt;단순 평균&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;$$
\text{Macro-F1} = \frac{1}{K} \sum_{k=1}^{K} F_1^{(k)}
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;각 클래스를 동등하게 취급&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;소수 클래스도 존중&lt;/strong&gt; 하고 싶을 때 적합&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;micro-average&quot;&gt;Micro-average&lt;/h3&gt;
&lt;p&gt;모든 클래스의 TP/FP/FN 을 먼저 합산하고 지표 계산:&lt;/p&gt;
&lt;p&gt;$$
\text{Micro-F1} = 2 \cdot \frac{\sum TP}{\sum TP + \sum FP + \sum FN}
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;전체 샘플을 동등하게 취급 (샘플 많은 클래스가 지배)&lt;/li&gt;
&lt;li&gt;Micro-F1 은 multi-class accuracy 와 같아집니다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;weighted-average&quot;&gt;Weighted-average&lt;/h3&gt;
&lt;p&gt;각 클래스의 support (샘플 수) 로 가중 평균:&lt;/p&gt;
&lt;p&gt;$$
\text{Weighted-F1} = \sum_{k=1}^{K} \frac{n_k}{n} F_1^{(k)}
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;실제 분포를 반영&lt;/li&gt;
&lt;li&gt;다수 클래스가 편중된 경우 macro 대신 자주 쓰임&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;기타-지표&quot;&gt;기타 지표&lt;/h2&gt;
&lt;h3 id=&quot;cohens-kappa&quot;&gt;Cohen’s Kappa&lt;/h3&gt;
&lt;p&gt;우연히 맞을 확률을 보정한 accuracy:&lt;/p&gt;
&lt;p&gt;$$
\kappa = \frac{p_o - p_e}{1 - p_e}
$$&lt;/p&gt;
&lt;p&gt;$p_o$ 는 실제 관측 accuracy, $p_e$ 는 우연히 일치할 기대 확률. 클래스가 매우 불균형할 때 raw accuracy 보다 신뢰할 만합니다.&lt;/p&gt;
&lt;h3 id=&quot;matthews-correlation-coefficient-mcc&quot;&gt;Matthews Correlation Coefficient (MCC)&lt;/h3&gt;
&lt;p&gt;$$
\text{MCC} = \frac{TP \cdot TN - FP \cdot FN}{\sqrt{(TP+FP)(TP+FN)(TN+FP)(TN+FN)}}
$$&lt;/p&gt;
&lt;p&gt;-1 (완전 반대) ~ 0 (random) ~ 1 (완벽). Confusion Matrix 네 셀 모두를 반영하며, &lt;a href=&quot;https://bmcgenomics.biomedcentral.com/articles/10.1186/s12864-019-6413-7&quot;&gt;Chicco &amp;#x26; Jurman 2020&lt;/a&gt; 은 이진 분류에서 F1/accuracy 보다 MCC 를 권장합니다.&lt;/p&gt;
&lt;h3 id=&quot;log-loss--cross-entropy&quot;&gt;Log Loss / Cross-Entropy&lt;/h3&gt;
&lt;p&gt;확률 출력에 대한 지표:&lt;/p&gt;
&lt;p&gt;$$
\text{LogLoss} = -\frac{1}{N} \sum_{i=1}^{N} \left[ y_i \log \hat{p}_i + (1-y_i) \log (1-\hat{p}_i) \right]
$$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;예측 확률이 실제 클래스에서 얼마나 벗어났는지 측정&lt;/li&gt;
&lt;li&gt;Calibration (예측 확률이 실제 빈도와 일치하는가) 를 평가할 때 함께 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;scikit-learn-실전-코드&quot;&gt;scikit-learn 실전 코드&lt;/h2&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sklearn.metrics &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    confusion_matrix,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    classification_report,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    roc_auc_score,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    precision_recall_curve,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    matthews_corrcoef,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Confusion matrix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cm &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; confusion_matrix(y_true, y_pred)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 종합 리포트 (precision, recall, F1, support 를 각 클래스별로)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(classification_report(y_true, y_pred, &lt;/span&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;digits&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 확률 기반 지표 (y_proba 는 positive class 확률)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;auc_roc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; roc_auc_score(y_true, y_proba)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;precision, recall, thresholds &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; precision_recall_curve(y_true, y_proba)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# MCC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mcc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; matthews_corrcoef(y_true, y_pred)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;threshold-튜닝&quot;&gt;threshold 튜닝&lt;/h3&gt;
&lt;p&gt;기본 threshold 0.5 를 그대로 쓰면 안 됩니다. 도메인 비용에 맞춰 조정:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sklearn.metrics &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f1_score&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numpy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;thresholds &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np.linspace(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;101&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f1s &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [f1_score(y_true, y_proba &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; thresholds]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;best_t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; thresholds[np.argmax(f1s)]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;또는 precision 을 최소 몇% 이상 유지하는 조건 아래에서 recall 을 최대화하는 식으로 제약 최적화합니다.&lt;/p&gt;
&lt;h2 id=&quot;참고&quot;&gt;참고&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[[federated-learning|Federated Learning]] 에서도 동일 지표를 클라이언트별로 계산합니다.&lt;/li&gt;
&lt;li&gt;[[transfer-learning|Transfer Learning]] downstream 평가에 대부분 이 지표들을 씁니다.&lt;/li&gt;
&lt;li&gt;[[sagemaker-model-monitor|SageMaker Model Monitor]] 의 Model Quality Monitor 가 이 지표들을 모니터링합니다.&lt;/li&gt;
&lt;li&gt;[[helm-llm-benchmark|HELM]] 의 accuracy 축은 여기서 확장된 형태입니다.&lt;/li&gt;
&lt;li&gt;Wikipedia: &lt;a href=&quot;https://en.wikipedia.org/wiki/Precision_and_recall&quot;&gt;Precision and recall&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Receiver_operating_characteristic&quot;&gt;Receiver operating characteristic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ml</category><category>evaluation</category><category>classification</category><category>metrics</category><author>koa (김신건)</author></item><item><title>모델 양자화</title><link>https://shinkeonkim.com/wiki/ml/quantization/</link><guid isPermaLink="true">https://shinkeonkim.com/wiki/ml/quantization/</guid><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;정의&quot;&gt;정의&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;양자화 (Quantization)&lt;/strong&gt; 는 신경망 모델의 가중치/활성화를 &lt;strong&gt;높은 정밀도 (FP32, FP16) 에서 낮은 정밀도 (INT8, INT4 등) 로 변환&lt;/strong&gt;하여 메모리와 연산량을 줄이는 기법.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;원래 신호 처리 용어. 연속적인 신호 (continuous signal) 를 이산적인 (discrete) 양자 (quantum) 레벨로 변환한다는 뜻에서 “양자(量子)화”라 부른다. 실수 값을 정수 격자에 맞춰 떨어뜨리는 과정.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;FP32 가중치: 0.327891, -1.42876, 0.00123, ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                ↓ 양자화 (4-bit, 16 levels)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;INT4 가중치: 3, -6, 0, ...  (scale 곱해서 복원)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;왜-양자-인가&quot;&gt;왜 “양자” 인가&lt;/h2&gt;
&lt;p&gt;물리학의 양자(quantum) 개념에서 유래. 연속체를 이산적인 단위로 쪼개는 것.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FP32: 약 2^32 가지 값 표현 가능 (사실상 연속)&lt;/li&gt;
&lt;li&gt;INT8: 256 가지 값만 (이산)&lt;/li&gt;
&lt;li&gt;INT4: 16 가지 값만 (매우 이산)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;비유: 아날로그 회전 다이얼 vs 디지털 16 단계 클릭. 16 단계로 “양자화” 된다.&lt;/p&gt;
&lt;h2 id=&quot;왜-필요한가&quot;&gt;왜 필요한가&lt;/h2&gt;
&lt;p&gt;LLM (Large Language Model) 은 메모리와 메모리 대역폭이 가장 큰 병목.&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;모델&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;FP16&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;INT8&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;INT4&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Llama 2 7B&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;13 GB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;7 GB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4 GB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Llama 2 70B&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;140 GB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;70 GB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;40 GB&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;GPT-3 175B&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;350 GB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;175 GB&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;90 GB&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;INT4 로 양자화하면:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;메모리 4~8 배 절약&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;메모리 대역폭 4~8 배 절약&lt;/strong&gt; (가장 중요, 추론 속도 결정)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;연산 2~4 배 빠름&lt;/strong&gt; (INT 연산이 FP 보다 회로가 작음)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;24 GB RTX 4090 한 장에 70B 모델 INT4 로 돌릴 수 있게 됨.&lt;/p&gt;
&lt;h2 id=&quot;양자화의-수학&quot;&gt;양자화의 수학&lt;/h2&gt;
&lt;p&gt;스칼라 양자화의 기본 공식:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;quantize(x) = round(x / scale) + zero_point&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;dequantize(q) = (q - zero_point) * scale&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;여기서&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  scale = (x_max - x_min) / (q_max - q_min)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  zero_point = q_min - round(x_min / scale)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;예) FP32 가중치 범위 &lt;code&gt;[-2.5, 3.0]&lt;/code&gt; 을 INT8 (&lt;code&gt;[-128, 127]&lt;/code&gt;) 로:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;scale = 5.5 / 255 ≈ 0.0216&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zero_point = -128 - round(-2.5 / 0.0216) ≈ -12&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0.327 → round(0.327/0.0216) + (-12) = 15 - 12 = 3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;복원: &lt;code&gt;3 * 0.0216 - (-12 * 0.0216) ≈ 0.324&lt;/code&gt; (오차 0.003)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 오차가 누적되면 모델 품질이 떨어진다. 어떻게 오차를 최소화할지가 양자화 기법의 핵심 차이.&lt;/p&gt;
&lt;h2 id=&quot;양자화-방법론&quot;&gt;양자화 방법론&lt;/h2&gt;
&lt;h3 id=&quot;1-post-training-quantization-ptq&quot;&gt;1. Post-Training Quantization (PTQ)&lt;/h3&gt;
&lt;p&gt;이미 학습된 모델을 그대로 양자화. 재학습 필요 없음.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# PyTorch 의사 코드&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model_fp32 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; load_model()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;calibration_data &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; small_dataset_sample()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model_int8 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; quantize_ptq(model_fp32, calibration_data)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;장점&lt;/strong&gt;: 빠름 (수십 분), 학습 데이터 불필요&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단점&lt;/strong&gt;: 정확도 손실 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;가장 실용적, 가장 널리 사용.&lt;/p&gt;
&lt;h3 id=&quot;2-quantization-aware-training-qat&quot;&gt;2. Quantization-Aware Training (QAT)&lt;/h3&gt;
&lt;p&gt;학습 중에 양자화 효과를 시뮬레이션. 모델이 양자화 오차에 적응.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# fake quantize 삽입&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; forward_pass(x)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y_quantized &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fake_quantize(y)  &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 양자화 + 즉시 역양자화&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# backward 에서는 Straight-Through Estimator (STE) 로 gradient 통과&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;장점&lt;/strong&gt;: 가장 정확도 좋음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단점&lt;/strong&gt;: 재학습 비용 (full training 의 5~30%)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;극한 압축 (4-bit 미만) 시 필수.&lt;/p&gt;
&lt;h3 id=&quot;3-gptq-generative-pre-trained-transformer-quantization&quot;&gt;3. GPTQ (Generative Pre-trained Transformer Quantization)&lt;/h3&gt;
&lt;p&gt;2022년 발표 (&lt;a href=&quot;https://arxiv.org/abs/2210.17323&quot;&gt;arXiv:2210.17323&lt;/a&gt;). LLM 특화 PTQ.&lt;/p&gt;
&lt;h4 id=&quot;동기&quot;&gt;동기&lt;/h4&gt;
&lt;p&gt;기본적인 RTN (Round-To-Nearest) 양자화는 단순하지만 오차가 크다. 한 가중치를 양자화하면 발생한 오차가 이후 출력에 그대로 전파됨. GPTQ 는 &lt;strong&gt;이미 양자화한 가중치의 오차를, 아직 양자화 안 한 가중치들로 보정&lt;/strong&gt;한다.&lt;/p&gt;
&lt;h4 id=&quot;핵심-알고리즘-obq-기반&quot;&gt;핵심 알고리즘 (OBQ 기반)&lt;/h4&gt;
&lt;p&gt;OBQ (Optimal Brain Quantization) 의 LLM-scale 확장. 가중치 행렬 &lt;code&gt;W&lt;/code&gt; 한 행씩 처리:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1. 입력 데이터로 Hessian 행렬 H = 2·X·X^T 계산&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2. 각 column (가중치) 을 순서대로 양자화:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   a. quant(w_j) 로 양자화&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   b. 양자화 오차 e_j = (w_j - quant(w_j)) / [H^-1]_jj&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   c. 아직 양자화 안 한 가중치들을 e_j · H^-1_j,k 만큼 조정 (오차 보정)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;3. 모든 column 끝나면 다음 행으로&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;핵심 통찰: Hessian 의 역행렬 정보 (&lt;code&gt;H^-1&lt;/code&gt;) 가 각 가중치를 얼마나 흔들어야 출력 오차가 최소화되는지 알려준다.&lt;/p&gt;
&lt;h4 id=&quot;cholesky-분해-최적화&quot;&gt;Cholesky 분해 최적화&lt;/h4&gt;
&lt;p&gt;원래 OBQ 는 매 column 마다 Hessian 역행렬 갱신이 필요해 매우 느렸다 (175B 모델에 수개월). GPTQ 는 &lt;strong&gt;Cholesky 분해&lt;/strong&gt;로 미리 &lt;code&gt;H^-1&lt;/code&gt; 의 윗삼각 형태를 한 번에 계산하고, blockwise update 로 메모리/시간 최적화. &lt;strong&gt;175B 모델을 4시간&lt;/strong&gt; 으로 단축.&lt;/p&gt;
&lt;h4 id=&quot;옵션-act-order&quot;&gt;옵션: act-order&lt;/h4&gt;
&lt;p&gt;활성화 크기가 큰 column 순으로 양자화하면 7B 모델에서 PPL 7.15 → 6.09 로 개선. 큰 활성화 → 작은 오차 우선 보정 → 후속 column 영향 최소화.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;장점&lt;/strong&gt;: INT4 에서도 정확도 손실 매우 작음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단점&lt;/strong&gt;: 처리 시간 (1~4시간), 보정용 데이터 128+ 샘플 필요&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;품질&lt;/strong&gt;: LLaMA-7B 기준 FP16 PPL 5.68 vs GPTQ-INT4 6.09 (0.4 차이)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-awq-activation-aware-weight-quantization&quot;&gt;4. AWQ (Activation-aware Weight Quantization)&lt;/h3&gt;
&lt;p&gt;2023년 발표 (&lt;a href=&quot;https://arxiv.org/abs/2306.00978&quot;&gt;arXiv:2306.00978&lt;/a&gt;). GPTQ 와 같은 목표지만 완전히 다른 접근.&lt;/p&gt;
&lt;h4 id=&quot;동기-1&quot;&gt;동기&lt;/h4&gt;
&lt;p&gt;GPTQ 의 Hessian 기반 보정은 수학적으로 우아하지만 비싸다. AWQ 의 관찰: &lt;strong&gt;출력 오차의 대부분은 “outlier channels” 가 만든다&lt;/strong&gt;. 일부 채널의 활성화 크기가 매우 크고, 이 채널의 가중치 양자화 오차가 출력 전체를 망친다.&lt;/p&gt;
&lt;h4 id=&quot;핵심-아이디어-activation-aware-scaling&quot;&gt;핵심 아이디어, Activation-aware Scaling&lt;/h4&gt;
&lt;p&gt;수학적 항등식 활용:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Y = (W · diag(s)^-1) · (diag(s) · X)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  = W_scaled · X_scaled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;여기서 s = per-channel scaling factor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;W_scaled&lt;/code&gt; 에서 salient channels 의 가중치는 &lt;code&gt;s^-1&lt;/code&gt; 배 작아짐 → INT4 격자에서 더 정밀하게 표현&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X_scaled&lt;/code&gt; 에서 같은 채널의 활성화는 &lt;code&gt;s&lt;/code&gt; 배 커짐 → 출력 동일&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;알고리즘&quot;&gt;알고리즘&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1. 캘리브레이션 데이터로 각 채널의 평균 활성화 크기 |X|_c 계산&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;2. s_c = |X|_c^α 형태로 parametrize (α 는 grid search 변수)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;3. α 를 20개 정도 grid 에서 탐색:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   for α in [0, 0.05, 0.1, ..., 1.0]:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     계산 layer 출력 오차&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;4. 가장 작은 오차의 α 채택, W_scaled 를 단순 INT4 RTN 으로 양자화&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;비교&quot;&gt;비교&lt;/h4&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;GPTQ&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;AWQ&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;접근&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Hessian-weighted 가중치 보정&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Pre-quantization 채널 스케일링&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;계산&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Cholesky 분해 + sequential update&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Grid search (20 forward pass/layer)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;시간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;1~4 시간&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;10분&lt;del&gt;30분 (**5&lt;/del&gt;10배 빠름**)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;품질&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;LLaMA-7B INT4: PPL 6.09&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;LLaMA-7B INT4: PPL 6.08 (거의 동일)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;GPTQ vs AWQ: GPTQ 는 “weight 별로 더 열심히 보정”, AWQ 는 “문제를 회전시켜서 weight 별 보정이 쉬워지게”. 실용적으로는 AWQ 가 더 인기.&lt;/p&gt;
&lt;h3 id=&quot;5-gguf--ggml-llamacpp&quot;&gt;5. GGUF / GGML (llama.cpp)&lt;/h3&gt;
&lt;p&gt;CPU + Apple Silicon 친화 양자화 포맷. 여러 비트수 동시 지원.&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;포맷&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;bit&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;7B 메모리&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;품질&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Q2_K&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2.6&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2.8 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;극한 압축 (품질 손실 큼)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Q4_K_M&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4.1&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4.1 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;권장&lt;/strong&gt;, FP16 대비 96~98%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Q5_K_M&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;5.1&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4.8 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;고품질&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Q8_0&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;8.0&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;7.2 GB&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FP16 거의 무손실&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;K_M = Mixed precision (중요 레이어는 더 높은 비트). 로컬 LLM 실행의 사실상 표준.&lt;/p&gt;
&lt;h3 id=&quot;6-qlora-nf4&quot;&gt;6. QLoRA (NF4)&lt;/h3&gt;
&lt;p&gt;2023년 5월 발표 (&lt;a href=&quot;https://arxiv.org/abs/2305.14314&quot;&gt;arXiv:2305.14314&lt;/a&gt;). Tim Dettmers 외. &lt;strong&gt;24 GB GPU 1대로 65B 모델 fine-tuning&lt;/strong&gt; 을 가능하게 만든 기법. 단순한 양자화를 넘어 3가지 혁신을 조합.&lt;/p&gt;
&lt;h4 id=&quot;1-nf4-4-bit-normalfloat&quot;&gt;1. NF4 (4-bit NormalFloat)&lt;/h4&gt;
&lt;p&gt;가장 중요한 혁신. 신경망 가중치는 보통 &lt;strong&gt;정규분포 N(0, σ²) 를 따른다&lt;/strong&gt; 는 관찰에서 시작.&lt;/p&gt;
&lt;p&gt;기존 INT4 / FP4 는 균등 간격으로 16개 값을 잡지만, 정규분포 데이터에서는 0 근처에 값이 몰려 있다. 균등 간격은 비효율.&lt;/p&gt;
&lt;p&gt;NF4 는 &lt;strong&gt;각 양자화 구간이 표준정규분포 N(0, 1) 아래 같은 면적&lt;/strong&gt; 을 가지도록 16개 값을 설계.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;표준정규분포 N(0, 1) 를 16등분 (각 구간 확률 1/16):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  q_i = quantile((i + 0.5) / 16)  for i = 0..15&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;결과 NF4 값들 (대략):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  -1.0,  -0.69, -0.52, -0.40, -0.30, -0.21, -0.13, -0.06,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;   0.06,  0.16,  0.25,  0.34,  0.44,  0.56,  0.72,  1.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;0 근처에 값이 빽빽하고 양 끝에 듬성. 정규분포 데이터에 최적.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;정보이론 관점&lt;/strong&gt;: NF4 는 “정규분포 데이터를 4-bit 로 표현하는 information-theoretically optimal” 양자화. 균등 INT4 대비 같은 비트로 더 적은 정보 손실.&lt;/p&gt;
&lt;h4 id=&quot;2-double-quantization&quot;&gt;2. Double Quantization&lt;/h4&gt;
&lt;p&gt;블록 양자화 (blocksize 64) 에서는 각 블록마다 scale (FP32, 4 bytes) 이 필요. 큰 모델에선 이 scale 자체가 메모리를 차지.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;65B 모델, blocksize 64:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  parameter 수: 65 × 10^9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  block 수: ~10^9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  block 당 FP32 scale: 4 bytes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  scale 총량: 4 GB (! 가중치 압축한 의미가 무색)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Double Quantization: &lt;strong&gt;scale 자체를 다시 양자화&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;원본:     W (FP16) → blockwise quant → W_NF4 + c_1 (FP32 per 64 weights)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Double:   W (FP16) → quant 1 → W_NF4 + c_1_quantized + c_2 (FP32 per 256 c_1)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;c_1 은 8-bit 로 양자화 (c_2 가 c_1 의 scale)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;평균 &lt;strong&gt;0.37 bits/parameter 절약&lt;/strong&gt; (65B 모델에서 ~3 GB).&lt;/p&gt;
&lt;h4 id=&quot;3-paged-optimizer&quot;&gt;3. Paged Optimizer&lt;/h4&gt;
&lt;p&gt;QLoRA 의 또 다른 혁신. LoRA adapter 의 optimizer state (Adam 의 momentum + variance, FP32) 가 메모리 spike 의 원인.&lt;/p&gt;
&lt;p&gt;긴 시퀀스 처리 중 일시적으로 메모리가 부족해지면 OOM. Paged Optimizer 는 &lt;strong&gt;NVIDIA Unified Memory&lt;/strong&gt; 를 활용해 optimizer state 를 자동으로 GPU ↔ CPU RAM 사이에 페이지 단위로 교환. OS 의 가상 메모리 paging 과 동일 개념.&lt;/p&gt;
&lt;h4 id=&quot;전체-qlora-수식&quot;&gt;전체 QLoRA 수식&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Y_BF16 = X_BF16 · doubleDequant(c_1, c_2, W_NF4) + X_BF16 · L_1 · L_2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  W_NF4: 4-bit 양자화된 frozen base model 가중치&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  c_1, c_2: double quantized scales&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  L_1, L_2: LoRA adapters (low-rank decomposition, trainable, BF16)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;doubleDequant 가 NF4 → BF16 복원, 그 후 일반 LoRA forward.&lt;/p&gt;
&lt;h4 id=&quot;결과&quot;&gt;결과&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;LLaMA 65B 를 &lt;strong&gt;단일 48 GB A6000 1장&lt;/strong&gt;으로 fine-tuning&lt;/li&gt;
&lt;li&gt;Guanaco 모델 (QLoRA 로 fine-tuned LLaMA 65B) 가 ChatGPT-3.5 와 비교 가능한 품질 달성&lt;/li&gt;
&lt;li&gt;HuggingFace &lt;code&gt;bitsandbytes&lt;/code&gt; 라이브러리로 한 줄 적용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;bitsandbytes-사용-예&quot;&gt;bitsandbytes 사용 예&lt;/h4&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; transformers &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; AutoModelForCausalLM, BitsAndBytesConfig&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; torch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;quant_config &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; BitsAndBytesConfig(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    load_in_4bit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    bnb_4bit_quant_type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;nf4&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,          &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# NF4 사용&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    bnb_4bit_use_double_quant&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,     &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# Double Quantization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    bnb_4bit_compute_dtype&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;torch.bfloat16,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;model &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; AutoModelForCausalLM.from_pretrained(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &apos;meta-llama/Llama-2-70b-hf&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;    quantization_config&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;quant_config,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# 이제 LoRA 추가 후 학습&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;7-fp8-fp4-hardware-native&quot;&gt;7. FP8, FP4 (Hardware native)&lt;/h3&gt;
&lt;p&gt;NVIDIA H100 부터 FP8 (e4m3, e5m2) 하드웨어 지원. B200 부터 FP4 추가.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;FP8&lt;/strong&gt;: 학습 + 추론. INT8 대비 동적 범위 넓음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FP4&lt;/strong&gt;: 4-bit 부동소수, INT4 대비 정확도 우위&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;INT4 같은 정수 양자화는 별도 calibration 이 필요하지만, FP8/FP4 는 하드웨어가 직접 처리.&lt;/p&gt;
&lt;h2 id=&quot;정확도-vs-압축-트레이드오프&quot;&gt;정확도 vs 압축 트레이드오프&lt;/h2&gt;




























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;포맷&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;압축률&lt;/th&gt;&lt;th align=&quot;center&quot;&gt;품질 (FP16 대비)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP16 / bf16&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;1x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;기준&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP8 (H100)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;2x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~99.7%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;INT8&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~99%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;FP4 (B200)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;~99.0%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;AWQ 4-bit&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;del&gt;98&lt;/del&gt;99%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;GPTQ 4-bit&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;del&gt;97&lt;/del&gt;99%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Q4_K_M GGUF&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;del&gt;96&lt;/del&gt;98%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;NF4 (QLoRA)&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;del&gt;95&lt;/del&gt;97%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;단순 INT4&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;4x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;&lt;del&gt;85&lt;/del&gt;93%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;INT2&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;16x&lt;/td&gt;&lt;td align=&quot;center&quot;&gt;큰 손실&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;시나리오별-권장&quot;&gt;시나리오별 권장&lt;/h2&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;환경&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;권장&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA H100/H200/B200&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FP8 (vLLM, TensorRT-LLM)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA B100/B200 frontier&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;FP4&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;NVIDIA A100/4090&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;AWQ 4-bit&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Apple Silicon (Mac)&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MLX 4-bit 또는 GGUF Q4_K_M&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;CPU 전용&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;GGUF Q4_K_M (llama.cpp)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Fine-tuning, 메모리 제약&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;QLoRA NF4&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;cs-에-미친-영향&quot;&gt;CS 에 미친 영향&lt;/h2&gt;
&lt;p&gt;양자화는 단순한 최적화 기법을 넘어 &lt;strong&gt;모델 배포의 전체 패러다임&lt;/strong&gt;을 바꿨다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;로컬 LLM&lt;/strong&gt;: ChatGPT 급 모델을 노트북에서 실행 (llama.cpp + GGUF Q4)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;edge AI&lt;/strong&gt;: 스마트폰 [[NPU]] 가 INT4 회로로 LLM 추론&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPU 비용&lt;/strong&gt;: 같은 모델을 1/4 메모리로 → 클라우드 비용 4 배 절감&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;연구 방향&lt;/strong&gt;: “더 큰 모델” 만큼 “더 효율적인 양자화” 가 활발한 연구 분야&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>ai</category><category>model-compression</category><category>inference</category><category>machine-learning</category><author>koa (김신건)</author></item></channel></rss>