**HN掲示:NVMe→GPU バイパスでCPUを経由せず、単一のRTX 3090上でLlama 3.1 70B を動作させる**

2026/02/22 5:57

**HN掲示:NVMe→GPU バイパスでCPUを経由せず、単一のRTX 3090上でLlama 3.1 70B を動作させる**

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

NTransformer は、依存関係のない軽量 C++/CUDA エンジンであり、ユーザーが PCIe 上でモデル層をストリーミングし、オプションで高速直接 I/O 用に NVMe を使用することで、70 B 変種を含むフルサイズ Llama モデルをコンシューマ GPU 上で直接実行できるようにします。

  • Resident mode(レジデントモード):Llama 3.1‑8 B Q8_0 は 10 GB の VRAM だけで 48.9 トークン/秒を達成し、tiered‑auto モードは 10.3 GB を使用して 48.8 トークン/秒を提供します。
  • 70 B model(70 B モデル):ストリーミング(mmap)のみでは非常に遅く (0.006 トークン/秒、7.3 GB)、tiered auto はスループットを 0.2 トークン/秒まで向上させ、23.1 GB を消費します。Q4_K_M のレイヤー・スキップを使用すると速度が 0.5 トークン/秒に上昇し、わずか 22.9 GB で済みます。これは単一 RTX 3090 + 48 GB RAM システムでのプレーン mmap に対して 83 倍速です。
  • Bandwidth bottleneck(帯域幅ボトルネック):PCIe Gen3 x8 (~6.5 GB/s) がデータ転送を制限します。Q4_K_M は VRAM に 10 層多く収容でき (36 層対 26 層)、tier‑B 転送が削減され、スループットが向上します。
  • Layer‑skip(レイヤー・スキップ):コサイン類似度キャリブレーションを使用して、1 トークンあたり 20–80 層を最小限の品質低下でスキップし、大規模モデルの推論速度を向上させます。
  • Architecture(アーキテクチャ):3 タイヤの適応型キャッシュが VRAM‑resident、ピン留め RAM、および NVMe/mmap タイヤを自動的にサイズ決定します。エンジンはすべての GGUF 量子化 (Q4_0, Q8_0, Q4_K_M, Q5_K, Q6_K, F16, F32) をサポートし、レジデント、tiered‑auto、layer‑skip、および self‑speculative decoding の 4 種類の自動選択データパスを提供します。
  • System requirements(システム要件):Linux (Ubuntu kernel 6.17+)、CUDA 13.1、gcc‑14/g++‑14、CMake 3.24+、NVIDIA GPU CC 8.0+ (RTX 3090 テスト済み)。直接 I/O 用に別の PCIe スロットに NVMe SSD が必要です。セットアップスクリプトはカーネルモジュールをパッチし、AMD IOMMU を無効化し、NVMe を VFIO にバインドします(DMA 分離について注意)。
  • NVMe‑direct pipeline(NVMe 直接パイプライン):各層 (~670 MB for 70 B Q6_K) は約 202 ms の NVMe コマンドで CUDA‑ピン留めステージングメモリに読み込まれ、非同期 DMA により GPU バッファへ転送され、デュアルバッファ間で計算と重ね合わせて実行されます。
  • Roadmap(ロードマップ):完成済みフェーズ—基盤、SLEP ストリーミング、最適化、NVMe direct。今後の作業には speculative decoding の仕上げと公開 C API の追加が含まれます。

NTransformer は、大規模モデルをコストの高いサーバーインフラなしでコンシューマ GPU 上にローカル実行できるようにすることで、推論コストを低減し、オンプレミス AI サービスのレイテンシを削減し、研究・産業界全体での採用拡大を促進します。

本文

NTransformer

高効率なC++/CUDA LLM推論エンジン – PCIe経由でGPUメモリへモデル層をストリーミングし、CPUを完全にバイパスするNVMeダイレクトI/Oオプション付きで、RTX 3090(24 GB VRAM)単体でLlama 70Bを実行します。


主な成果

モデル実行モードデコード速度使用VRAM備考
Llama 3.1 8B Q8_0Resident48.9 tok/s10.0 GB全層がVRAMに収まる
Llama 3.1 8B Q8_0Tiered (auto)48.8 tok/s10.3 GB32/32層が自動でVRAMへ昇格
Llama 3.1 70B Q6_KStreaming (mmap)0.006 tok/s7.3 GBページキャッシュのスラッシング(53 GB > 48 GB RAM)
Llama 3.1 70B Q6_KTiered (auto)0.2 tok/s23.1 GB26VRAM + 54RAM + 0NVMe
Llama 3.1 70B Q4_K_MTiered (auto)0.3 tok/s22.9 GB36VRAM + 44RAM(50 %高速)
Llama 3.1 70B Q4_K_MTiered + layer skip0.5 tok/s22.9 GB36VRAM + 44RAM、20層スキップ

*三階層適応キャッシュはハードウェアに合わせて自動調整されます:

  • VRAMに常駐(I/Oゼロ)
  • ピン留め済みRAM(H2Dのみ)
  • NVMe/mmapフォールバック*

RTX 3090 + 48 GB RAMの消費者向けハードウェアで、mmapベースより83倍速を実現。

ボトルネック: Gen3 ×8 PCIe H2D帯域(約6.5 GB/s)
Q4_K_MはVRAMに10層多く収める(36 vs 26)、Tier‑B転送が減少。
Layer skip(コサイン類似度調整)は1トークンあたり20/80層を除外し、品質低下を最小化。


主な機能

  • CUDA Toolkit以外に依存せず、PyTorchやcuBLASは不要。
  • GGUFモデルフォーマット:Q4_0, Q8_0, Q4_K_M, Q5_K, Q6_K, F16, F32量子化。
  • 3‑Tier適応キャッシュ:VRAM常駐 + ピン留めRAM + NVMe/mmap階層。
  • SLEPストリーミング:ダブルバッファリングによりNVMe読み込み、PCIe DMA、GPU計算を重ね合わせる。
  • gpu‑nvme‑directバックエンド:ユーザースペースNVMeドライバーでモデルウェイトを直接ピン留めGPUアクセスメモリへ読込む。
  • Layer skip:コサイン類似度調整により冗長層(20/80)をスキップ。
  • Self‑speculative decoding:VRAM常駐層をドラフトモデルとして使用し、追加モデル不要。
  • 4種類のデータパス(自動選択)
    1. VRAM常駐 → GPU計算
    2. ピン留めRAM H2D
    3. Mmapピン留め
    4. CPUワーカー memcpy
  • Llamaアーキテクチャ:RoPE, GQA, SwiGLU, RMSNorm, KVキャッシュ。

要件

項目バージョン
Linux(Ubuntu、カーネル 6.17+で検証)
CUDA Toolkit13.1
GCC/G++14
NVIDIA GPUCompute Capability 8.0+(RTX 3090をテスト)
CMake≥3.24
任意別PCIeスロットにNVMe SSD + gpu‑nvme‑directライブラリ

クイックスタート

# ビルド
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_C_COMPILER=gcc-14 \
  -DCMAKE_CXX_COMPILER=g++-14 \
  -DCMAKE_CUDA_COMPILER=/usr/local/cuda-13.1/bin/nvcc
cmake --build . -j

# Residentモード(モデルがVRAMに収まる場合)
./ntransformer -m /path/to/llama-8b-q8_0.gguf -p "Hello" -n 128

# Streamingモード(モデルがVRAMを超える場合)
./ntransformer -m /path/to/llama-70b-q6_k.gguf -p "Hello" -n 32 --streaming

# Layer skip(70Bで最速)
./ntransformer -m /path/to/llama-70b-q4_k_m.gguf \
  -p "Hello" -n 32 --streaming --skip-threshold 0.98

# Self‑speculative decoding
./ntransformer -m /path/to/llama-70b-q6_k.gguf \
  -p "Hello" -n 32 --self-spec --draft-k 3

# チャットモード
./ntransformer -m /path/to/model.gguf --chat

# ベンチマーク
./ntransformer -m /path/to/model.gguf --benchmark -n 64

NVMeダイレクトI/Oのシステム設定

nvme direct を動作させるにはシステムレベルでいくつか変更が必要です。
自動セットアップスクリプトがすべてを処理します。

# 初回完全セットアップ(対話形式、バックアップ作成)
sudo ./scripts/setup_system.sh

# 現在の状態確認(変更なし)
sudo ./scripts/setup_system.sh --check

# NVMeのみ(再起動後に実行)
sudo ./scripts/setup_system.sh --nvme-only

スクリプトが変更する項目と理由

フェーズ何を変更理由リスク復元
1gcc‑14、cmake、カーネルヘッダーのインストールCUDA 13.1はgcc‑15(Ubuntu 25.10のデフォルト)と非互換低 – 標準パッケージ
apt remove
2GRUBに
amd_iommu=off
を追加
AMDルートコンプレックスがIOMMUオン時にGPU→NVMe P2P読み込みをブロックする。無効化でPCIe書き込み(ドアベル)が可能になる中 – 全PCIeデバイス間のDMA隔離が解除される。マルチテナント/サーバー環境では使用しないこと
/etc/default/grub
から削除、
update-grub
、再起動
3NVIDIA DKMS (
os-mlock.c
) をパッチ
follow_pfn()
がカーネル 6.12+で削除。修正が無ければ
cudaHostRegisterIoMemory
が失敗しGPUがNVMe BAR0をMMIO書き込みできない
高 – パッチ不備でGPUドライバーがロードされず、再起動時にブラックスクリーンになる。
.orig
バックアップ自動作成
cp os-mlock.c.orig os-mlock.c
をDKMSソースディレクトリへ、
dkms remove/install nvidia/VERSION
3bCUDAヘッダー (
math_functions.h
) をパッチ
glibc 2.42+ が
rsqrt()/rsqrtf()
noexcept
宣言。CUDA 13.1 は非宣言で、ビルド失敗になる
低 – 一つのヘッダーのみ影響。バックアップ作成
cp math_functions.h.orig math_functions.h
4VFIOモジュール (
vfio
,
vfio-pci
) をロード
NVMeをVFIOにバインドしてユーザースペースアクセスを可能にする。GeForce GPUは
enable_unsafe_noiommu_mode=1
が必要
低 – モジュールは再起動時にアンロードされる。「Unsafe noiommu」=VFIOデバイスのIOMMU DMA保護が無効再起動または
modprobe -r vfio-pci vfio
5NVMeをカーネルからunbindし、VFIOへbind
gpu‑nvme‑direct
は生RAW PCIeアクセスを必要とする。NVMeはVFIOにバインドされることで
/dev/
に表示されなくなる
高 – 誤ったデバイスを操作するとブートディスクが失われる可能性あり。スクリプトは自動検出し、ブートデバイスへの適用は拒否
sudo ./scripts/restore_nvme.sh

BIOS設定(手動:スクリプト実行前に)

設定
Above 4 GB DecodingON(64‑bit BARマッピングが必要)
IOMMUOFF(またはオンでもスクリプトでパラメータ追加)
Secure BootOFF(署名/パッチ済みカーネルモジュールのロードに必須)

ハードウェア注意事項

本プロジェクトは低レベルPCIe操作(GPU MMIO書き込みによるNVMeコントローラレジスタ制御、ユーザースペースNVMeコマンド送信、VFIOデバイスパススルー)を行います。RTX 3090 + WD SN740で十分にテスト済みですが、誤設定やハードウェア互換性の不備により以下が発生する可能性があります:

  • NVMeリンク障害(GPU読み込み時に電源サイクルが必要)
  • RAWブロックストレージでデータ損失
  • IOMMU無効化やカーネルモジュールパッチによるシステム不安定
    決してブートドライブをNVMeダイレクトI/Oに使用しないでください。専用のセカンダリNVMeを常に使用してください。
    著者はハードウェア損傷やデータ喪失について責任を負いません。自己責任でご利用ください。

スクリプト一覧

スクリプト目的実行タイミング
scripts/setup_system.sh
システム全体設定(7フェーズ)初回セットアップ
scripts/setup_system.sh --nvme-only
VFIO + NVMeバインドのみ再起動後に実行
scripts/setup_system.sh --check
状態確認デバッグ時
scripts/setup_nvme.sh [BDF]
単一NVMeをVFIOへバインドスタンドアロン、再起動後
scripts/restore_nvme.sh [BDF]
NVMeをカーネルデバイスに戻すNVMeダイレクト終了時

NVMeダイレクトストリーミング

VRAMに収まらないモデルでは、NVMeバックエンドがCPUを完全に排除します。

NVMe SSD → (DMA) → ピン留めステージング → (PCIe H2D) → GPUバッファ → 計算

設定手順

# NVMeサポート付きでビルド(gpu‑nvme‑directライブラリが必要)
cmake .. -DCMAKE_BUILD_TYPE=Release -DUSE_GPUNVME=ON \
  -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 \
  -DCMAKE_CUDA_COMPILER=/usr/local/cuda-13.1/bin/nvcc
cmake --build . -j

# GGUFモデルをNVMe生RAWデバイスへ書き込む
sudo ./scripts/restore_nvme.sh           # カーネルドライバーがbindされていること確認
sudo dd if=model.gguf of=/dev/nvme0n1 bs=1M oflag=direct status=progress

# NVMeをVFIOへバインドしてユーザースペースアクセス可能にする
sudo ./scripts/setup_nvme.sh             # VFIOロード、D0パワー状態強制、BusMaster有効化

# NVMeバックエンドで実行
sudo GPUNVME_PCI_BDF=0000:01:00.0 GPUNVME_GGUF_LBA=0 \
  ./build/ntransformer -m /path/to/model.gguf -p "Hello" -n 32 --streaming

# NVMeをカーネルドライバーへ戻す
sudo ./scripts/restore_nvme.sh

動作原理

  1. dd
    でGGUFファイルをNVMeブロックに書き込み。
  2. setup_nvme.sh
    がNVMeをVFIOにバインドし、PCIe D0状態とBusMasterを有効化。
  3. gpu‑nvme‑direct
    がユーザースペースからNVMeコントローラを初期化(admin/IOキュー)。
  4. 推論時には各層(70B Q6_Kは約670 MB)を約670のNVMeコマンドで~202 msに読み込み。
  5. データはCUDAピン留めステージングへ入り、非同期DMAでGPU計算バッファへ転送される。
  6. ダブルバッファリングによりNVMe読込・H2D DMA・GPU計算を重ね合わせ、スループットを最大化。

アーキテクチャ概要

src/
├── core/          # テンソル、アロケータ、GPUデバイス管理
├── cuda/          # CUDAカーネル:GEMV, RMSNorm, RoPE, SwiGLU, softmax
├── memory/        # SLEP層ストリーミングエンジン(NVMe + mmap)
├── model/         # Transformer:設定、GGUFローダー、注意機構、FFN、正規化
├── inference/     # トークナイザ、サンプラー、エンジン
├── utils/         # タイマー、ロガー
└── main.cpp       # CLI入り口

scripts/
├── setup_system.sh   # システム全体設定(GRUB, NVIDIAパッチ, CUDAパッチ, VFIO, NVMe)
├── setup_nvme.sh     # NVMeをVFIOへバインド、gpu‑nvme‑direct用に構成
└── restore_nvme.sh   # NVMeをカーネルデバイスへ戻す

tests/               # ユニットテスト(テンソル, GEMMカーネル, NVMe層ローダ)

3‑Tier適応キャッシュ –
forward_tiered()

階層内容備考
Tier AVRAM常駐(層0–28)GPU計算はI/Oゼロで永続的に保持。
Tier Bピン留めRAM(層29–79、ダブルバッファ)H2D DMAとGPU計算を重ね合わせる。
Tier CNVMe/mmapフォールバック必要時のみ使用。

Tierサイズは

cudaMemGetInfo()
/proc/meminfo MemAvailable
から自動算出。


量子化形式

フォーマット重みビット数ブロックサイズ対応
Q4_04.532はい
Q8_08.532はい
Q4_K_M4.5256はい(Q4_K + Q5_K + Q6_Kの混合)
Q5_K5.5256はい
Q6_K6.6256はい
F16161はい
F32321はい

フェーズロードマップ

フェーズステータスハイライト
1 – 基盤完了Llama 8B Q8_0、カスタムCUDAカーネル、48.9 tok/s
2 – SLEPストリーミング完了70Bを単一GPUで実行、3階層キャッシュ、33×速度向上
3 – 最適化完了Q4_K_M/Q5_Kサポート、Layer skip(0.5 tok/s)、self‑speculative decoding、F16 KVキャッシュ
4 – NVMe Direct完了
gpu‑nvme‑direct
バックエンド(GPU主導NVMe読込、3.35 GB/s)
5 – ポリッシュ計画中ドラフトモデルを用いた推測デコーディング、ベンチマーク、公開C API

ライセンス

BSD‑2‑Clause


同じ日のほかのニュース

一覧に戻る →

2026/02/22 9:29

**Claude コードの使い方:計画と実行の分離**

## 日本語訳: 記事は約9か月の経験に基づくClaude Codeを使用するための規律あるワークフローを提示しています。研究、計画、および実行を分離し、各フェーズが進む前に承認済みのマークダウンアーティファクトを生成することを強調しています。 1. **リサーチ (research.md)** – Claude は対象フォルダーを徹底的にスキャンし、ユーザーが検証しなければならない詳細レポートを作成します。表面的な読み込みは推奨されません。 2. **計画 (plan.md)** – コードスニペット、ファイルパス、トレードオフ、および説明を含む別のマークダウン計画が用意されます。組み込みのプランモードは拒否され、この編集可能なドキュメントが採用されます。 3. **注釈サイクル** – ユーザーはエディタで計画をレビューし、インラインメモや制約を追加して「まだ実装しない」ガード付きで再送します。このサイクルは計画が完全に受理されるまで繰り返されます。 4. **実行** – 実装前に詳細なTODOリストが計画に追加されます。その後、著者は固定プロンプト「implement it all…」を発行し、Claude にすべてを実行させ、計画内の完了状況を更新させ、不必要なコメントや未知のタイプを避け、型チェックを継続的に実行させます。 5. **修正** – 実行中にユーザーは簡潔な修正(多くの場合単一文)を提供します。フロントエンドでの修正にはスクリーンショットや既存パターンへの参照が含まれる場合があります。 6. **制御と永続性** – 著者はアーキテクチャ的なコントロールを決して手放しません。Claude の提案を評価し、必要に応じて変更またはスキップします。3つのフェーズすべてが単一の長時間セッションで行われ、計画ファイルは自動圧縮を通じて保持され、主要な参照として機能します。 マークダウンファイルを共有可変状態として維持することで、このアプローチはノイズの多いチャットインタラクションを減らし、追跡性を向上させ、大規模プロジェクト全体で一貫したインターフェースを保ちます。

2026/02/22 9:21

**回答** 実際には、ほとんどの最新コンパイラは「決定的(deterministic)」です。 同じソースコードと同一のコンパイルオプション(使用するコンパイラのバージョンや基盤となるプラットフォームを含む)を与えれば、何度実行しても同一のオブジェクトファイルまたはバイナリが生成されます。 ただし、いくつか注意すべき点があります。 | 要因 | 決定性への影響 | |------|----------------| | **コンパイラ実装** | よく設計されたコンパイラは決定的ですが、不具合のあるものではそうでない場合もあります。 | | **ビルド環境** | OS、CPU アーキテクチャ、またはライブラリのバージョンが異なると、ソースコード自体に変更がなくても出力が変わることがあります。 | | **非決定的なパス** | 例としてランダム化されたレジスタ割り当てなど、一部の最適化は性能調査のために意図的にばらつきを導入します。 | | **タイムスタンプ/ビルドメタデータ** | バイナリにはしばしばタイムスタンプやビルド識別子が埋め込まれます。 これを削除(例:GCC/Clang の `-Wl,--build-id=none`)すると、バイト単位で完全に同一の出力が得られます。 | したがって、環境を統制し安定したコンパイラリリースを使用すれば決定的な結果が期待できます。 セキュリティや監査目的で確実な再現性が必要な場合は、**Reproducible Builds** のようなツールを使い、非決定的データを除去する手順を踏むと良いでしょう。

## Japanese Translation: 記事は、ソフトウェアビルドにおける真の決定論が実現しづらい理由を説明しています。入力状態のすべての部分―ソースコード、コンパイラフラグ、ツールチェーンバイナリ、環境変数、ファイルシステムレイアウト、ロケール、クロック、カーネル動作、さらにはハードウェア並列性までも―を完全に指定しなければ、「ノイズ」が出力の漂移を引き起こします。 再現可能ビルドの実践は、ツールチェーンを凍結し、タイムスタンプを正規化(`SOURCE_DATE_EPOCH`)、揮発性メタデータを除去し、`-ffile-prefix-map` でパスを標準化し、ヘルミティックコンテナ内でビルドし、アーカイブを決定的に作成(`ar -D`)することでこれらの問題を緩和します。そうしても、GCC 18574 のようなバグが示すように、内部ポインタハッシュの不安定性は同一ソースから生成されるコードを変化させる可能性があります。 コンパイラ契約はビット単位での同一性ではなく、セマンティクス(観測可能な I/O、揮発性アクセス、アトミック保証)の保持に焦点を当てています。不定動作がこの保証を弱めるため、再現可能ビルドはより厳格な要件となります。`__DATE__/__TIME__` のようなエントロピー源、デバッグ情報内の絶対パス、ロケール依存のソート(`LC_ALL`)、並列ビルドの競合順序、ランダムシード、ネットワークフェッチはすべて再現性を破る要因となり得ます。ASLR がコンパイラパスに間接的に影響することも同様です。 歴史的には、2013 年以降の Debian の再現可能ビルド取り組みが、同一ソースから同一アーティファクトを作ることを主流化し、コンパイラ・リンカ・パッケージング・ビルドシステム全体で意図的な設計が必要であることを示しています。 将来に向けて、記事は LLM で支援される開発チームが決定論的検証ゲート―制約付き入力、テスト可能な出力、再現性のある CI パイプライン―を導入して信頼できるデプロイを確保する必要があると主張しています。完全な決定論は必須ではありませんが、予測可能な振舞いと検証可能性は本番システムに不可欠です。 主要な結論は、多くのエコシステムが多くの境界ケースで意図的な取り組みを通じて再現可能ビルドをサポートしているということですが、Ken Thompson の「Reflections on Trusting Trust」からの根本的な警告は残ります―コンパイラは信頼できるように見えても妥協され得るのです。

2026/02/22 4:40

**「Rustにおけるパース・非検証設計と型駆動開発」**

## 日本語訳: **要約** この記事は、Rust の型システムを利用して、プリミティブ値を *newtype* でラップすることでコンパイル時にドメイン不変条件をエンコードできることを示しています。生成関数を失敗可能(例:`NonZeroF32::new` が `Option<NonZeroF32>` を返す)にすることで、値がゼロでないことを保証します。その後、関数は生のプリミティブではなくこれら newtype を受け取るようになり、検証を関数内部から呼び出し前へ移動させ、冗長なランタイムチェックを排除します。 同様のパターンが `NonEmptyVec<T>` にも適用されます。これはベクタが空でないことを保証し、`first()` のような安全メソッドを追加のガードなしに提供します。著者は、これを `Option` や `Result` を返す通常の失敗可能関数と対比し、より強力な型保証が API 契約をどれだけ簡素化するかを強調しています。 実際の例として、Rust 自体の `String` は検証済み `Vec<u8>` の newtype であり、Serde は JSON をデシリアライズしてコンパイル時にスキーマ制約を課す具体的な構造体へ変換できます。また、記事は「ショットガン解析」や Curry–Howard 対応といった関数型プログラミングの概念も参照し、タイプによる早期かつ包括的な検証の動機付けを行っています。 実務上のアドバイスとして、より意味のある型(例:単なるブールフラグではなく `LightBulbState` のような列挙体)が正確性を向上させる場合はプリミティブを避けるべきです。newtyping はコードを冗長にすることがありますが、一般的にはより明確で安全な API を提供し、ランタイムエラーを減らします。主な制限点は、Rust が現在 newtype 用のエルゴノミック委譲(delegation)をサポートしていないことであり、将来の RFC やライブラリがこの障壁を低くする可能性があります。 この要約はキーポイントリストからすべての主要点を捉えつつ、メッセージを明確に保ち、余計な推論を排除しています。

**HN掲示:NVMe→GPU バイパスでCPUを経由せず、単一のRTX 3090上でLlama 3.1 70B を動作させる** | そっか~ニュース