オンデバイスLLMのためのKVキャッシュ量子化
2 GBのRAMを搭載したAndroidデバイスでLlama 3.2 3Bを動かすのは困難です。ほとんどの開発者はモデルの重みに注目しますが、それは間違いです。真のメモリ消費の主犯はKVキャッシュです。
チャットが進むにつれて、KVキャッシュは増大していきます。標準的なFP16精度を使用すると、キャッシュは数百メガバイトを消費します。これにより、わずか数回のやり取りでアプリがクラッシュしてしまいます。
これを解決するには、3つの具体的なステップがあります。
- 混合精度量子化を使用する KeyとValueに同じ精度は必要ありません。Keyキャッシュは低精度でもうまく機能しますが、Valueキャッシュはそうではありません。
- KeyにはINT4を使用します。
- ValueにはINT8を使用します。
このアプローチにより、キャッシュサイズを62%削減できます。2048トークンのコンテキストの場合、224 MBから84 MBまで削減可能です。これはモデルの重みを変えることなく実現できます。
スライディングウィンドウによるエビクションを実装する すべてのトークンをアクティブメモリに保持し続けることはできません。スライディングウィンドウを使用して、直近の1536トークンのみを保持します。システムプロンプトを維持するために、最初の64トークンはアンカーとして保持してください。
フラッシュ・スピリング(Flash Spilling)を使用する トークンがスライディングウィンドウから外れたら、フラッシュストレージに移動させます。Androidではメモリマップドファイルを使用してください。最新のUFS 4.0ストレージは、遅延なくデータをメモリにページインできるほど高速です。
結果は劇的です。Snapdragon 8 Gen 3では:
- ピークメモリが2 GBの制限を下回ります。
- 最大会話ターン数が4回から12回以上に増加します。
- キャッシュが小さくなることでメモリ帯域幅をより効率的に利用できるため、トークン生成速度が向上します。
- モデルの品質はほぼ維持されます。
以下の間違いを避けてください:
- KeyとValueを同じレベルで量子化しないでください。品質が低下します。
- サーマルスロットリングを無視しないでください。継続的な推論は発熱を伴います。パフォーマンスを管理するためにAndroid Thermal HALを確認してください。
- キャッシュのライフサイクルを忘れないでください。メモリリークを避けるため、マップされたバッファは常に適切なスコープに関連付けてください。
機能の実装に取り組む前に、メモリ予算を策定してください。
出典: https://dev.to/software_mvp-factory/kv-cache-quantization-for-on-device-llms-kf