酒呑ガジェット

〜静かな環境であなたに...こちらは音のでないコンテンツです。〜

【悲報】Linuxの16%がたった1社のGPUドライバで埋め尽くされる異常事態…650万行の正体に技術者騒然

【悲報】Linuxの16%がたった1社のGPUドライバで埋め尽くされる異常事態…650万行の正体に技術者騒然

オープンソースの心臓部として世界中の技術者が協力して作り上げるLinuxカーネルが、かつてない肥大化の局面を迎えている。最新のカーネル全体のコード量が約4098万行に達する中で、AMDのGPUドライバだけでおよそ652万行、実に全体の約16%を単独で占めていることが明らかになった。たった一つの企業の、一つのハードウェアを動かすためのプログラムがシステム全体の6分の1を占めるというのは極めて異例で、開発を率いるリーナス氏もこの巨大なコード追加について特別に言及するほど話題になっている。単なる無駄な肥大化なのか、それとも必然なのかを巡って議論が広がっている。

通常、プログラムが巨大化すると処理が遅くなり管理も難しくなるため、できるだけコードを短くシンプルに保とうとするのが定石だ。このため巨大化を批判する声もあるが、実態は少し異なる。現代のGPUは昔のようにただ画面に絵を映すだけの装置ではなくなっている。超高解像度の映像伝送、画面更新頻度の細かな調整、高度な計算処理や最新の通信規格への対応など、ソフトウェア側で制御しなければならない項目が爆発的に増えている。さらに新しい製品だけでなく過去の古い製品も全て同じシステム内でサポートし続けるという方針も影響している。つまり無駄に長くなっているわけではなく、必要な機能を確実かつ安全に動かすための必然的な結果という側面が強い。

巨大なGPUチップとLinuxカーネルのコードに囲まれるサーバールームの技術イラスト

650万行のうち410万行は自動生成、無数の設定書が膨張する理由

ドライバ全体の約650万行のうち、なんと410万行以上が特定の単一ディレクトリに集中している。その正体はハードウェアを直接操作するための設定書のようなファイルで、専門用語ではレジスタ定義のヘッダーファイルと呼ばれるものだ。GPUの中には設定を保存したり状態を確認したりするための小さな記憶領域が無数にあり、それぞれに番号が割り振られている。この410万行は誰かが毎日キーボードで打ち込んで作ったものではなく、ハードウェアの設計データから専用のツールを使って自動的にテキストファイルとして出力しているものだ。設計が変わるたびに新しい番号が追加されたり場所が少しずつ変わったりするため、手作業では到底追いつかない。

問題は世代やわずかな仕様変更の度にこの設定ファイルを完全に別々のものとして追加していることだ。例えばディスプレイを出力する部分だけでも世代ごとに異なる設定ファイルが丸ごと用意されている。古いファイルと新しいファイルを共通化してまとめることも理論上は可能だが、あえてそうしていない。グラフィックスの処理は一秒間に何万回もその番号を読み書きするため、実行する瞬間に計算をしていると処理が遅れてしまう。だからあらかじめ世代ごとに決められた番号を直接参照するように作っている。これによってプログラムの容量はどんどん増えてしまうが、動作の致命的な遅延を防ぐことができる。容量と速度を天秤にかけて速度を取った結果だ。

OSの垣根を越えたコード共有と浮動小数点の特例

コードを巨大化させているもう一つの要因が、ディスプレイを制御するための仕組みにある。数年前からWindows向けのドライバとLinux向けのドライバで画面表示に関するプログラムを共有するようになった。以前はOSごとに一からプログラムを書いていたが、画面出力はあまりにも複雑になりすぎた。画面を映すだけなら配線をつなげばいい時代は終わり、今は超高解像度の映像を圧縮して送ったり、画面の更新頻度を細かく調整したりと高度な処理が必要だ。これらをOSごとに別々に作って動作確認をするのは開発の手間を考えると現実的ではない。そこでOSの違いを吸収するための特別な翻訳のようなプログラムを挟むことで、Windows用の膨大なコードをそのまま使えるようにした。

この手法は本来の標準的な作り方とは違うため当初は強い反発があった。プログラムが肥大化したりエラーの原因を突き止めるのが難しくなったりする恐れがあるからだ。しかし最終的には最新のGPUが発売初日から完璧に動作するという圧倒的な利便性が評価され、共有方式が受け入れられた。コードは巨大化したが最新規格を安定して使えるというメリットが、作法の違いというデメリットを上回ったと言える。完全に専用のプログラムが理想的という声もあるが、現実解としてこの共有方式が定着し、数十万行に及ぶコードが新たに追加されることになった。

先のディスプレイ制御の中にはさらに特殊なプログラムが含まれている。それが画面のちらつきを防ぐために非常に精密なタイミング計算を行う部分で、ここでは小数点以下の細かい数値を扱う浮動小数点演算という計算方法が大量に使われている。実はシステムの中核であるカーネルの中でこの少数の計算を行うことは原則としてタブーとされている。割り込み処理の退避コストや実行環境の制約からカーネル内での浮動小数点使用は避けるのが鉄則だが、ディスプレイの精密制御だけは例外として認められている。ちらつきのない滑らかな表示を実現するためにはマイクロ秒単位の厳密な計算が不可欠で、整数演算だけでは精度が足りないからだ。タブーを破ってまで精度を取りに行ったことが、この分野の複雑さを物語っている。

計算専用ドライバの台頭と巨大なSoCとしてのGPU

さらに近年は画面表示とは無関係の計算専用ドライバが台頭している。AI計算や科学技術計算のためにGPUを巨大な並列計算機として使う用途が爆発的に広がり、グラフィックス描画とは別の制御経路が必要になった。メモリの確保方法もキャッシュの扱いも表示用とは全く異なり、ジョブの投入から完了待ち、エラー時の復旧まで専用の管理機構が求められる。この計算スタックだけで数十万行規模のコードが積み上がっている。ゲームや映像のためだけでなく、AI時代の計算基盤としての役割がコード量を押し上げている。

背景にはGPU自体が巨大なSoCとして進化している現実がある。単なる描画チップではなく、内部に複数のプロセッサや電源管理、セキュリティ回路、映像エンジン、通信回路を抱えた一つのコンピュータのような存在だ。電源を入れた瞬間からOSが起動するまでの間に、ファームウェアの読み込み、クロックや電圧の立ち上げ順序、メモリの初期化、各ブロックの自己診断といった複雑極まる起動シーケンスを正確にこなさなければならない。一つでも順序を間違えれば画面が出ないだけでなくシステム全体が不安定になる。これらを世代ごと、製品ごとに記述していくため、コードは際限なく増えていく。

そしてAMDが選んだのが抽象化を捨てる戦略だ。本来ソフトウェア工学では共通部分をくくり出して抽象化し、コードを短く保つのが美徳とされる。しかしGPUの最前線では抽象化のコストが無視できない。関数呼び出し一つのオーバーヘッドや分岐予測の乱れがフレームレートや計算スループットに直結する。そこで世代ごとにほぼ同じ処理でもあえて別々に書き下し、直接参照で最高速を引き出す道を選んだ。美しさより確実性と速度を優先した結果が650万行だ。まとめとして言えるのは、肥大化はサボりの産物ではなく、高速性と互換性と最新規格対応を全て取りに行った代償だということだ。カーネル全体の16%という数字は異常に見えて、現代の計算環境を支えるための請求書でもある。

ネットの反応

ハードが絡む部分が安易に共通処理化できないのは仕方がないと思う。特に高速処理が必要な部分や同期が絡む部分は非常に難しいし。

AIの所感

16%という数字だけ見ると異常事態だが、中身を解くと三つの合理性が見える。自動生成ヘッダによる速度優先、OS横断の共有による発売初日対応、そしてAI計算需要の取り込みだ。いずれも現場の切実な要請から生まれている。課題は今後も増え続けるコードを誰が保守するのかという点だ。自動生成部分と手書きのロジック部分をどう切り分け、バグの温床を減らすのか。抽象化を捨てる戦略は短期的には速いが、長期的には重荷になる可能性がある。カーネルの肥大化を嘆くより、巨大なハードをどう安全に抽象化せずに制御するかという新しい工学の形として捉えるべきだろう。利用者側の教訓は、最新のGPUを使うほど巨大なドライバの恩恵と重さを引き受けているという自覚を持つことだ。

-パソコン