ggml の紹介
ggml は C と C++ で書かれた低レベル機械学習(ML)ライブラリで、Transformer の推論に特化しています。llama.cpp、whisper.cpp、ollama、Jan、LM Studio、GPT4All など、デバイス上で動作する LLM プロジェクトの基盤エンジンとして利用されています。
ggml の主な利点
ggml はミニマリズムと効率性を重視して設計されており、リソースが限られたハードウェアへの展開に最適です。主な利点は次のとおりです。
- 最小フットプリント: コアライブラリは 5 ファイル未満で完結し、コンパイル後のバイナリサイズは 1 MB 未満です。
- シンプルなコンパイル: GPU サポートが不要な基本的なビルドは GCC または Clang だけで行え、複雑なビルドツールを回避できます。
- 幅広いハードウェア互換性: x86_64、ARM、Apple Silicon、CUDA など様々なアーキテクチャをサポートします。
- メモリ効率: テンソルの保存と計算にかかるオーバーヘッドを最小化し、量子化テンソルによりメモリ使用量を削減、場合によっては性能向上も期待できます。
技術的トレードオフ
開発が活発に進められている低レベルライブラリであるため、ggml には以下のような制限があります。
- バックエンドの差異: すべてのテンソル演算がすべてのバックエンドでサポートされているわけではありません(例: ある演算は CPU では動作するが CUDA では動作しない)。
- 開発の複雑さ: ggml を利用するには低レベルプログラミングに関する深い知識が必要です。
- 安定性: 活発に開発が続いているため、破壊的変更が入る可能性があります。
主な用語と概念
ggml を理解するには、性能を細かく制御できるいくつかの低レベル抽象概念に慣れる必要があります。
ggml_context: テンソル、グラフ、オプションデータを格納するコンテナ。ggml_cgraph: バックエンドが実行する演算順序を表す計算グラフ。ggml_backend: 計算グラフを実行するインターフェース。CPU(デフォルト)、CUDA、Metal、Vulkan、RPC などの実装があります。ggml_backend_buffer_type: 特定のバックエンドに結び付けられたメモリアロケータ(例: GPU メモリの確保)。ggml_backend_buffer:buffer_typeによって確保され、複数テンソルのデータを保持できるバッファ。ggml_gallocr: 計算グラフ内のテンソルを効率的に管理するためのグラフメモリアロケータ。ggml_backend_sched: 複数バックエンドに計算を分散させるスケジューラ(例: CPU と GPU に作業を分割)で、サポートされていない演算は自動的に CPU に割り当てます。
実装ワークフロー
基本的な計算
単純な演算(例: 行列乗算)では、ggml のワークフローは次の手順で行われます。
- テンソルデータ用に
ggml_contextを確保する。 - テンソルを作成し、データを割り当てる。
- 演算用の
ggml_cgraphを定義する(例:ggml_mul_mat)。 ggml_graph_compute_with_ctxで計算を実行する。- 結果を取得し、メモリを解放する。
バックエンド駆動の計算
CUDA など特定のハードウェアバックエンドを利用する場合、デバイスメモリ管理を効率化するために手順が増えます。
ggml_backendを初期化する。- テンソルメタデータだけを保持する
ggml_contextを確保する。 - テンソルのメタデータ(形状と型)を作成する。
- デバイス上にテンソルを格納するための
ggml_backend_bufferを確保する。 - RAM からバックエンドバッファへテンソルデータをコピーする。
- グラフ割り当て用に
ggml_cgraphとggml_gallocrを作成する。 ggml_backend_graph_computeで計算を実行する。- 結果テンソルをデバイスバッファから RAM にコピーする。
計算グラフのデバッグ
開発者は ggml_cgraph を調べて演算順序を確認できます。ライブラリは ggml_graph_print でコンソールにグラフを出力し、ggml_graph_dump_dot で Graphviz の dot 形式にエクスポートして可視化できます。
Sources
- OriginalIntroduction to ggml