nbd-vram - LinuxでNVIDIA GPUのVRAMをスワップ領域として使うツール
(github.com/c0dejedi)- nbd-vramは、LinuxでNVIDIA GPUのアイドル状態のVRAMを高優先度のスワップ領域として使えるようにする小さなデーモン
- はんだ付けメモリでアップグレードが難しく、内蔵AMD/ATI GPUが画面出力を担うハイブリッドグラフィックスノートPCで、遊休状態のNVIDIA VRAMをメモリ圧迫の緩和に活用
- テスト環境は AMD/ATI + RTX 3070 Laptop、RAM 16GB、VRAM 8GB、NVIDIA driver 580.159.03、kernel 6.17、Pop!_OS で、VRAM 7GBをスワップとして割り当て、zram・SSDスワップまで含めて約46GBのアドレス指定可能メモリを構成
- 動作順序は、まずRAMが埋まり、次にVRAMがPCIe経由であふれたページを吸収し、その後zramがCPUで圧縮し、最後にSSDを使う構成
- デーモンはCUDA driver APIでVRAMを割り当て、Unix socket上の**NBD(Network Block Device)**プロトコルでブロックデバイスを提供し、カーネル内蔵の
nbdドライバが/dev/nbdXとして公開して通常のスワップデバイスのように使う - データパスは kernel swap subsystem →
/dev/nbdX→ nbd kernel driver → Unix socket → nbd-vram daemon →cuMemcpyHtoD/DtoH→ GPU VRAM と続く - 別途カーネルモジュールやNVIDIAカーネルシンボルが不要なため、カーネル・ドライバ更新後も再ビルドなしで維持できる
- NVIDIA P2P API方式は consumer GeForce GPU で
nvidia_p2p_get_pages_persistentがEINVALを返し、BAR1直接ioremap_wc方式も約16MiBのディスプレイフレームバッファ以外の領域読み取りが0を返して失敗 - CUDAコピー経路である
cuMemcpyHtoDとcuMemcpyDtoHは特別な権限なしでCUDA GPU上で動作するため、NBDアクセスがP2P・BAR1の制約を回避 - 要件は、CUDA対応NVIDIA GPU、
libcuda.so.1があるNVIDIAドライバ、Linux kernel 3.0+ の nbd モジュール、nbd-client、gcc、makeで、CUDA toolkit は不要 - インストール後は
vram-swap-nbdsystemd サービスが起動時に自動実行され、/etc/systemd/system/vram-swap-nbd.serviceのVRAM_SETUP_SIZE_MBとVRAM_SWAP_PRIORITYで使用するVRAM上限とスワップ優先度を調整 - デーモンは要求されたVRAMサイズをまず試し、GPUメモリが不足している場合は512MiB単位で減らして割り当てるため、
VRAM_SETUP_SIZE_MBは必須サイズではなく上限として動作 - 電源認識管理を有効にすると、AC電源が外れたときやバッテリー残量がしきい値以下のときにサービスが自動停止し、電源が復旧すると再起動し、手動の
systemctl stopは上書きしない - RTX 3070 Laptop ベンチマークでは、シーケンシャルスループットと持続的ランダムI/OはNVMeのほうが速いが、4K読み取り 1 request/sec のレイテンシはVRAMが平均335usで、NVMeの9.05msより27倍高速
- MITライセンスで提供され、リポジトリにはスモークテスト用
test-nbd.sh、全パーティション検査用test-fill.sh、スループット・IOPS・レイテンシのベンチマークスクリプトも含まれる
1件のコメント
Hacker Newsのコメント
CUDA経由でファイルストレージやマウントのように扱うとオーバーヘッドが大きいので、BAR を使えばスループットや IOPS を確実に改善できそう
はんだ付けメモリでアップグレードの余地がないノートPC向けという説明なら、高価な RAM からさらに高価な RAM へなぜスワップするのかという即座の疑問には答えになっている
用途は限定的に見えるが、SSD にスワップされる状況では遊んでいる 8GB の VRAM を使うのは、必要なときには良いアイデア
たとえばゲーム用に GPU を買ったなら、ゲームしていないときにデスクトップ描画で 16GB VRAM は不要なのだから、別用途に使ってもよいのではと思う
ただしゲームを起動するときに、スワップとして使っていた VRAM をシステムが解放できるという前提が必要で、実際に可能なのかは気になる
80年代半ばから90年代半ばまで英国で一般的だった Amstrad PCW では最大 512kB の RAM が使え、そのかなり大きな部分を RAM ディスクにできた
Turbo Pascal のコンパイルもとても速くなった :-)
アイデアは良いが、ここでは何か大きく間違っている気がする
RTX 3070 Laptop でシーケンシャルスループットが約 1.3 GB/s とのことだが、この RTX 3070 チップは PCIe 4.0 x16 なので 64GB/s 出るはずで、8GB GDDR6 自体は 448GB/s ある
NVMe ドライブへスワップするほうが2倍は速いだろうが、レイテンシはより高いはず
ベンチマークも ZRAM を使って回しているが、ZRAM はスワップへ書く前にページを圧縮する。その性能オーバーヘッドが正確にどれほどかは分からないが、かなり大きい可能性がある
まずユーザー空間プログラムが、遅いことで知られる nbd ドライバ越しにぶら下がっており、GPU へ転送する前にユーザー空間のバウンスバッファも使っている。カーネルがページをスワップしなければならない場合、まずユーザー空間に公開されたバッファへコピーし、その後ユーザー空間プログラムが再び起きて CUDA 操作を発行し、そのページをデバイスメモリへコピーしなければならない
nbd は高いキュー深度や隣接アクセスのマージもあまりうまく扱えない。カーネルがマージなしで 4K ページのスワップを大量に発行すると、4 GB/s を処理するだけでも毎秒少なくとも100万回のカーネル/ユーザー空間コンテキストスイッチが必要になる。64 GB/s などなおさらだ。これは NBD 部分だけを見た話で、NVIDIA ドライバの複雑さは含んでいない
PCIe は大量のデータを運べるが、総帯域に近づけるには長いページリストを持つ DMA エンジン を使う必要がある。PCIe で 4K ページごとに転送を設定していたのでは、バスを完全に飽和させることはできない
NVMe へのスワップ経路は非常によく最適化されている。スワッパーはページリストを NVMe ドライバへ直接提出でき、コントローラが RAM から直接 DMA で取り込むので、CPU 側のコピーやコンテキストスイッチは一切ない
ublk ドライバへ移せばユーザー空間のバウンスバッファを避けられるかもしれず、複数の書き込みキューで CUDA コピーを並列に設定することもできるので、改善の余地はある
RAM や VRAM は使っても劣化しない
開発マシンに 32GB RAM と、AI モデルを動かしていないときは大半が遊んでいる 32GB VRAM があるので、このアイデアはそこまで悪くない
バックプレッシャー をどう扱うのか気になる。VRAM がスワップ領域として使われている間に VRAM 割り当て要求が来たらどうなるのか?
X11 ではバッファが事前確保されるのでまだましだが、Wayland では割り当てがずっと動的なので、VRAM が足りなくなるとデスクトップ全体が簡単に死にうる
Hyprland+llama-server+KVM でコンピュータを切り替えているとき、VRAM を解放できずにこうしたクラッシュを何度か経験した
ユーザーレベルで スワップデバイス を作るのは、昔から古典的な解決不能問題の1つだった
デーモンがページをスワップインしようとしているが、そのページをスワップインするにはデーモン自身のページを先にスワップインしなければならない場合はどうするのか?
少なくともマイクロカーネルが絶対に動かない理由として、こうした議論があった。ここでの解法が何なのかはよく分からない
Linux カーネルも自分のテキストページがスワップアウトされないようにしているのだから、解法はすでにあり、マイクロカーネル設計にも適用できない理由は分からない
そのデーモン全体のメモリを固定しておけば、この問題は些細なものになる
昔 Linux の MTD/phram ドライバで似たようなことをやった記憶がある: https://wiki.archlinux.org/title/Swap_on_video_RAM
ただ、今でも関係があるのかは分からない。DRM とどう相互作用するのか、VRAM の一部を予約する処理をどうやるのかが分からないからだ。xorg.conf で制限を提案する方式は、今ではかなり時代遅れかもしれない
そのページには OpenCL 上に実装した FUSE ファイルシステムもある: https://github.com/Overv/vramfs
こちらのほうが互換性は高いかもしれない
懐かしい
Windows でも数年前に似たようなものを見たことがある
NVIDIA カードの VRAM で RAM ドライブを作れるようにする実験的な概念実証ドライバで、シーケンシャルアクセスは予想どおり速いが、ランダムアクセスはまだ改善の余地が大きかった
GpuRamDrive は GPU RAM をバックエンドにした仮想ドライブを作る: https://github.com/prsyahmi/GpuRamDrive
AMD 対応フォーク: https://github.com/brzz/GpuRamDrive/
似ているが OpenCL API を使うので AMD でも動く
ただし AMD ドライバはかなりバグが多いので、「動く」の定義は必要だ: https://libguestfs.org/nbdkit-vram-plugin.1.html
32GB RAM 搭載の Apple Silicon Mac で、20GB がまだ未使用/“free” なのに、なぜスワップファイルを使ったり、さらには作成したりするのか分からない
Linux の
swapoff -aのような簡単なコマンドで スワップファイルを完全に無効化 できないのはなぜなのか?SSD の寿命をわざわざ縮めるのが目的でないなら、かなり愚かに見える
GUI でスワップファイルを無効にするシステム設定があってほしいし、Apple が今のシステム設定/レイアウトの「段階」をようやく捨ててもよいと思う。何十年も続いた環境設定パネルと比べても、いまだに単語サラダのようだ
#Apple #Feedback #swapfile
「利用可能メモリ」という概念も、理想的には「別の目的のために素早く回収できるメモリ」に近い
ある時点では、匿名メモリを主記憶に置き続けるより、キャッシュされたファイル内容にその場所を占めさせるほうが良いこともある