
4GB VRAM のグラフィックカードで 70B クラスの LLM をフルパラメータのまま動かす。
そう聞くと「さすがに無理でしょ」と思いますよね。
でも AirLLM というライブラリを使うと、これが実際に動きます。
ただし「動く」と「使える」は別の話で、そこには明確なトレードオフがあります。
AirLLM がどういう仕組みで VRAM の壁を越えるのか、llama.cpp や Ollama の量子化アプローチとどう違うのか、そして「どんな用途なら採用が合理的か」という判断軸を整理します。
70B モデルを動かすのに必要なメモリ、正直どのくらいか
まず数字の話から始めます。
70B モデルというのは、パラメータ数が約 700 億個あるモデルです。
FP16(16ビット浮動小数点)で保持する場合、1パラメータあたり 2 バイトなので、単純計算で 70B × 2 バイト = 約 140GB の VRAM が必要になります。
民生 GPU の現実と照らし合わせると、このギャップの大きさが分かります。
RTX 4090 でも 24GB、RTX 4060 は 8GB、RTX 3060 は 12GB です。
140GB を一枚のカードに乗せようとすると、A100 80GB を 2 枚並べてもまだ足りません。
ここで「じゃあ量子化すれば?」という発想が出てきますが、それは次節で扱います。
まず押さえておきたいのは、この 140GB という要件が「モデルを丸ごとメモリに乗せる」という設計から来ている、という点です。
トランスフォーマーの推論は、埋め込み層から始まり、多数のトランスフォーマーブロック(レイヤー)を順番に通過して、最後の出力層で終わります。
従来のランタイムはこの全レイヤーを推論前に VRAM へ展開しておく設計になっているため、140GB という要件が生まれます。
さらに推論中には KV キャッシュや中間アクティベーションも VRAM を消費するので、実際の要求量はパラメータ分だけでは収まりません。
「全部同時に乗せなければいけない」という前提を疑うと、別のアプローチが見えてきます。
量子化とレイヤーオフロード――アプローチの根本的な違い
VRAM の壁を越えるための主な手段は、大きく 2 つに分かれます。
ひとつは 量子化。
llama.cpp や Ollama が採用しているアプローチで、「モデルを小さくして全部乗せる」という発想です。
FP16 の重みを INT4 や INT8 に圧縮することで、140GB のモデルを 35〜40GB 程度まで縮小します。
VRAM に収まるサイズにしてしまえば、従来の推論ループをそのまま使えます。
ただし、重みの表現精度を削っているので、元のモデルとは数値的に別物になります。
もうひとつが AirLLM の レイヤー単位オフロード。
「一度に乗せる量を減らす」という発想で、重みの精度には一切手を加えません。
推論ループの中で、レイヤーを 1 枚ずつディスクから GPU に読み込み、そのレイヤーの計算が終わったらアンロードして次のレイヤーを読み込む、という処理を繰り返します。
これが成立する理由は、トランスフォーマーの推論構造にあります。
レイヤーは必ず順番に実行されるので、あるレイヤーの計算中に他のレイヤーの重みは不要です。
つまり「今計算しているレイヤー 1 枚分の VRAM があれば推論できる」というのが AirLLM の核心です。
2 つのアプローチを対比するとこうなります。
- 量子化(llama.cpp / Ollama): 重みの精度を下げてモデルを圧縮し、全レイヤーを VRAM に乗せたまま推論する。速度は速いが、元モデルとの数値的な同一性は失われる。
- レイヤーオフロード(AirLLM): 重みの精度を保ったまま、レイヤーを 1 枚ずつ順次 GPU に載せ替えて推論する。精度は保たれるが、ディスク I/O がボトルネックになり速度は遅い。
要するに、量子化は 精度 を犠牲にしてメモリを節約し、レイヤーオフロードは 速度 を犠牲にして精度を保ちます。
どちらが優れているかではなく、何を優先するかで選ぶものです。
AirLLM の動作環境と最小構成コード
動作要件から確認します。
GPU 推論には NVIDIA GPU と CUDA が必要で、VRAM は 4GB 以上あれば動きます。
システム RAM は 16GB 以上が推奨です。
ストレージは 70B モデルで約 130GB 必要になります。
なお、Apple Silicon(M1/M2/M3)では mlx フレームワーク経由で動作し、2024 年 8 月以降は x86_64 CPU のみの環境にも対応しています。
ストレージが 130GB も必要な理由は、初回実行時の動作にあります。
AirLLM は最初の起動時にモデルをレイヤー単位のシャード(断片)に分解して、ディスクに保存し直します。
以降の推論はこのシャードを順次読み込む形で動くので、HuggingFace のキャッシュディレクトリに十分な空き容量があることを事前に確認しておいてください。
インストールから推論実行までの最小構成コードはこちらです。
pip install airllm
from airllm import AutoModel
# HuggingFace のモデル ID をそのまま指定する
model = AutoModel.from_pretrained("meta-llama/Meta-Llama-3.1-70B-Instruct")
# トークナイザーも同様に取得
tokenizer = model.tokenizer
# 入力テキストをトークナイズ
input_text = ["What is the capital of France?"]
inputs = tokenizer(
input_text,
return_tensors="pt",
padding=True,
truncation=True,
max_length=512,
)
# 推論実行
generation_output = model.generate(
inputs["input_ids"].cuda(),
max_new_tokens=20,
use_cache=True,
)
# デコードして出力
print(tokenizer.decode(generation_output[0], skip_special_tokens=True))
コードの見た目は HuggingFace の Transformers とほぼ同じです。
AutoModel.from_pretrained にモデルの HuggingFace ID を渡すだけで、レイヤー分解からシャード保存まで自動でやってくれます。
もうひとつ触れておきたいのが prefetching の仕組みです。
現在のレイヤーを GPU で計算している間に、次のレイヤーのディスク読み込みをバックグラウンドで並行実行します。
この重ね合わせによってディスク待ち時間の一部が隠蔽され、単純な逐次実行より約 10% 速くなります。
速度の現実と、それでも使う理由
正直に言うと、AirLLM は速くありません。
ボトルネックはディスク I/O です。
GPU の VRAM 帯域は約 1TB/s に達しますが、NVMe SSD の読み取り速度は 5〜10GB/s 程度です。
レイヤーを毎回ディスクから読み込む AirLLM では、この 100 倍以上の速度差がそのままトークン生成速度に響きます。
インタラクティブなチャット用途で使うには、率直に言って厳しいです。
一方、速度よりも精度が優先される場面では、合理的な選択肢になります。
具体的には次のような用途です。
- ベースライン比較: 量子化前のフルパラメータモデルの出力を参照値として使いたい場合。量子化によってどれだけ精度が落ちるかを測るには、フル精度の出力が必要です。
- オフライン評価: 夜間バッチで大量のプロンプトを流して評価スコアを計算するような用途。速度より再現性と精度が重要です。
- ハードウェアが限られた環境での検証: データセンターにアクセスできない状況で、70B クラスのモデルの挙動を手元で確認したい場合。
llama.cpp や Ollama との使い分けを一言で言うなら、インタラクティブに使うなら量子化、精度を保ちたいバッチ処理なら AirLLM です。
「動く」と「使える」は別、という話をしましたが、これは AirLLM を否定しているわけではありません。
「速度を犠牲にしてでも精度を保ちたい」という要件が明確にあるなら、AirLLM は現時点で数少ない現実的な選択肢のひとつです。
その要件がないなら、素直に量子化を使うほうが体験はずっと良くなります。
オプション圧縮で速度を底上げする
AirLLM には内蔵の圧縮機能があります。
ただし、これは llama.cpp の量子化とは 目的が根本的に異なります。
llama.cpp の量子化は「モデル全体を VRAM に収めるためにサイズを削る」ものです。
AirLLM の圧縮は「ディスクから読み込む物理データ量を減らして I/O を速くする」ためのものです。
具体的には、ブロックワイズ量子化(4bit または 8bit)を使って静的な重みを圧縮します。
140GB の 70B モデルが約 35GB まで縮小されるので、各レイヤーのディスク読み取り時間を最大 75% 削減でき、これがトークン生成速度の約 3 倍改善につながります。
重要なのは、AirLLM の圧縮が 静的な重みのみを対象にしている 点です。
動的なアクティベーション(レイヤー間を流れる中間状態)は圧縮しません。
アクティベーションを圧縮するとゼロショット精度が大きく劣化することが知られているため、この設計は意図的なものです。
I/O を削減しながら推論精度への影響を最小化する、というバランスを取っています。
圧縮を有効にするには、公式 README の使用例に従い AutoModel.from_pretrained に compression_ratio を指定します。
from airllm import AutoModel
model = AutoModel.from_pretrained(
"meta-llama/Meta-Llama-3.1-70B-Instruct",
compression_ratio=4,
)
具体的なパラメータ値と圧縮ビット数の対応については、公式 GitHub の README で確認してください。
精度への影響を抑えたい場合は、より高い compression_ratio 値(8bit 相当)から試すのが無難です。
もうひとつ、MoE(Mixture of Experts)モデルへの対応も触れておきます。
DeepSeek-V3 のような MoE モデルでは、全エキスパートをストリームするのではなく、各トークンが実際にルーティングされたエキスパートだけを読み込みます。
これにより、671B という巨大なパラメータ数を持つモデルでも 12GB 程度の VRAM で動作します。
コードは通常モデルと同じで、モデル ID を変えるだけです。
速度の制約は明確にある。
それでも「フル精度のまま手元で動かす」という選択肢が存在することには、確かな意味があります。
株式会社ホコサキは山口県宇部市を拠点に、AI 活用支援や業務システム開発に取り組んでいます。
ローカル LLM の検証から本番環境への組み込みまで、実務に即した相談を受け付けています。
興味があれば お問い合わせページ からお気軽にどうぞ。

