前回の記事(ゼロからGPUへ)では、カスタムカーネルのパッケージ化、配布、利用方法の標準化を目指す 🤗 Kernels プロジェクトを紹介しました。このプロジェクトは摩擦をなくし、セキュアにしつつ、Hub との親和性を最大限に高めることを目指しています。
過去数ヶ月、私たちはこの目標に向かって取り組んできました。その過程で、プロジェクトをほぼ全面的に再設計しました。本記事では、これまでにリリースした主要なアップデートと今後の予定をまとめます。
目次
Kernels – 新しいリポジトリタイプ
Hub に「kernel」という新しいリポジトリタイプを導入しました。これにより、コンピュート関連の特性を持つユーザーのニーズに対応できます。たとえば、ユーザーは特定のkernelでサポートされているアクセラレータ、オペレーティングシステム、バックエンドバージョンを把握できます:
Hub 上で利用可能なすべての kernel はこちらで閲覧できます: https://huggingface.co/kernels。
これらの kernel を Hub の第一級市民として扱うことで、AI エコシステム全体にもメリットがあります。ユーザーは kernel、モデル、それらを利用するアプリケーションのトレンドを確認できるようになりました。また、kernel の発見性も向上します。
セキュリティの強化
Kernel は、読み込む Python プロセスと同じ権限でネイティブコードを実行するため、悪意のある kernel は実際に害を及ぼす可能性があります。そのため、Kernels プロジェクトではセキュリティが常に最優先事項でした。
これが、早期から再現性に注力してきた理由です。kernel を自分で再コンパイルし、公開されているソースと一致することを検証できるようにする必要があります。ビルドを純粋に保つために Nix を使用しています。ビルドレシピの密閉評価と強力に隔離されたサンドボックスにより、ビルドの純度を維持します。さらに、ソースの Git SHA1 を kernel 自体に埋め込むことで、来歴を強化しています。
最近数ヶ月では、信頼できる kernel パブリッシャーとコード署名という追加の防御層を追加しました。
信頼できる kernel パブリッシャー
新しいリポジトリタイプとともに、「trusted publishers」も導入しました。Kernel は Python プロセスと同じ権限でマシン上でコードを実行するため、攻撃者は悪意のある kernel をアップロードし、ユーザーを誘導して使用させることでマシンを侵害する可能性があります。このような悪意のある kernel を避けるため、kernels パッケージはデフォルトでtrusted publishersによる kernel のみ読み込むようになりました。trusted publisher とは、コミュニティから善意で行動すると信頼されている組織です。
trusted publisher ではない組織やユーザーからの kernel の読み込みも引き続きサポートしますが、Hub から kernel を読み込む際には trust_remote_code 引数を使用して明示的にオプトインする必要があります:
from kernels import get_kernel
kernel_module = get_kernel(
“Atlas-Inference/gdn”, version=1, trust_remote_code=True
)
デフォルトでは、ユーザーは Hub 上で kernel リポジトリを公開できません。kernel publisher になるリクエストを行う必要があります。ユーザーと組織はアカウント設定からアクセスをリクエストできます。これにより、リクエストを個別に審査する時間を確保できます。
Kernel の署名
追加のセキュリティ層として、コード署名を導入しています。コード署名は、信頼できるパブリッシャーの Hub 認証情報が侵害され、攻撃者が悪意のある kernel を kernel リポジトリにアップロードするシナリオから保護します。コード署名では、kernel は kernel 開発者だけが知る秘密鍵で署名され、一般に公開されている公開鍵で検証されます。Hub 認証情報が侵害されたシナリオでは、攻撃者は署名に必要な秘密鍵を持っていないため、悪意のある kernel に署名できません。
セキュリティをさらに向上させるため、Sigstore の cosign を使用して一時的な秘密鍵で署名します。これらの署名鍵は有効期間が限定されているため、たとえ漏洩しても攻撃者が秘密鍵を利用することは通常できません。また、kernel が信頼できる GitHub リポジトリの信頼できる GitHub ワークフローによって署名されたことを検証します。
Kernel の署名はすでに kernel-builder でサポートされており、kernel を検証するための kernels verify-signature を提供しています。kernel の読み込み時に署名を検証する機能はまだ有効化していませんが、これは新機能を十分にテストしてから完全に展開するためです。独自の kernel 向けにコード署名を設定するための予備的な注意点は、kernels 0.16.0 のリリースノートに記載されています: https://github.com/huggingface/kernels/releases/tag/v0.16.0。
CLI の刷新
以前は、kernels と kernel-builder の間でユーティリティが混在していました。kernels と kernel-builder の CLI 間で関心の分離を明確にしました。ここでのメンタルモデルは、kernels が kernel を読み込み、利用可能な状態に準備するためのライブラリであるため、「kernel のビルド」に関連するものは含めないべきというものです。
その結果、kernels と kernel-builder の両方が大幅にスリム化され、より特化されました。詳細はドキュメントを参照してください:
この改善された CLI 体験により、エージェント型 kernel 開発の台頭にもより良く対応できます。詳細は後述します。
フレームワークとバックエンドのさらなる対応
フレームワークのサポートを拡張しました。主な変更点は以下の通りです:
- Torch Stable ABI を kernels と kernel-builder に追加しました。Torch Stable ABI により、kernel 開発者は特定の Torch バージョン、またはそれ以降にリリースされる任意のバージョンを約 2 年間ターゲットにできます。たとえば、Torch 2.9 Stable ABI をターゲットにした kernel は Torch >= 2.9 をサポートします。
- Apache TVM FFI が Torch 以外の最初のフレームワークとしてサポートされました。TVM FFI は PyTorch、Jax、CuPy などの他のフレームワークと相互運用可能な kernel 向けの標準化された ABI です。これにより、kernel 開発者は複数のフレームワークで動作する kernel を作成できます。
エージェント型カーネル開発の基盤
kernel-builder と kernels は、エージェントを活用してゼロから(最適化された)kernel を生成するエージェント型 kernel 開発の台頭を補完します。両者は、エージェントが kernel をスキャフォールディング、ビルド、ベンチマークし、反復的に最適化するワークフローをサポートします。
エージェント型 kernel 開発はまだ初期段階であり、適切な開発ループは今後も進化し続けます。そのため、ツールが人々が選択するあらゆるエージェントワークフローやフレームワークに簡単に組み込めるよう、シンプルで明確な基本が特に重要になります。
kernel-builder は、kernel のソースコードをどのようにスキャフォールディングし、再現可能なビルドを実行すべきかという構造を強制します。これにより、エージェントは予測可能なプロジェクトレイアウトと反復可能なワークフローの中で動作できます。また、CLI も エージェントに最適化されています。たとえば、非対話型のコマンドや、エージェントがプログラムで解釈しやすい出力が挙げられます。この目的のため、異なるバックエンドの特異性に対応するための バックエンド固有のスキル も提供しています。これらのスキルは、バックエンド固有のツールチェーン、コンパイルパス、パフォーマンス上の考慮事項を捉えます。
kernel を正常にビルドするだけでは不十分で、ターゲットハードウェア上でベースラインに対して実際の高速化を実現する必要があります。成功したビルドは、最初の検証ステップに過ぎません。通常、このターゲットハードウェアには多くの異なるアクセラレータ、さらには同じアクセラレータの異なるファミリが含まれる可能性があります。
したがって、関連するハードウェアベンダーや世代間で結果を評価することが重要になります。HF Jobs との緊密な 統合 により、このベンチマークプロセスを容易にできます。エージェントはこの統合を使用してベンチマークスイートを実行し、パフォーマンス結果を収集し、定義されたベースラインと比較できます。
この方法により、エージェントは異なるハードウェア構成でテストを実行し、生成された kernel のパフォーマンスに関する信頼できるフィードバックを得て、必要な作業を特定できます。そのフィードバックは、次の最適化イテレーションに役立てられます。
以下は、エージェント拡張された kernel の例です。これらは、このワークフローを通じて開発・評価可能な kernel の種類を示しています:
その他
環境セットアップ
kernel-builder で kernel をビルドするための環境セットアップは煩雑になることがあります。ユーザーがより簡単に利用できるように、ワンクリックで環境をセットアップする インストールスクリプト を用意しました。一時的なインスタンスで作業することを好む場合は、Terraform セットアップガイド を参照してください。
Kernel のシステムカード
kernel がビルドされた後、各 kernel に対してシステムカードを作成し、使用方法や公開インターフェースなどの有用な情報を公開します。kernel が Hub にプッシュされると、このシステムカードは kernel のフロントマターになります:
自分のシステムで kernel は互換性があるか?
計画を立てるために何度も聞く質問です。この目的には has_kernel() メソッドを使用します:
from kernels import has_kernel
print(has_kernel("kernels-community/activation", version=1))
これは bool を返します。特定の kernel がサポートされていない理由について詳しく知りたい場合は、get_kernel_variants() を使用します:
from kernels import get_kernel_variants, VariantAccepted
for decision in get_kernel_variants("kernels-community/activation", version=1):
name = decision.variant.variant_str
if isinstance(decision, VariantAccepted):
print(f"{name}: compatible")
else:
print(f"{name}: rejected ({decision.reason})")
以下のように出力されます(使用しているマシンによって異なります):
torch212-cxx11-cu130-aarch64-linux: compatible
torch210-cu128-x86_64-windows: rejected (CPU (x86_64) does not match system CPU (aarch64))
torch211-cu128-x86_64-windows: rejected (CPU (x86_64) does not match system CPU (aarch64))
torch212-metal-aarch64-darwin: rejected (OS (darwin) does not match system OS (linux))
torch211-metal-aarch64-darwin: rejected (OS (darwin) does not match system OS (linux))
torch210-metal-aarch64-darwin: rejected (OS (darwin) does not match system OS (linux))
torch29-metal-aarch64-darwin: rejected (OS (darwin) does not match system OS (linux))
…
manylinux_2_28 サポートの改善
Kernel-builder は当初から manylinux_2_28 をターゲットにしてきました。以前は glibc 2.28 でコンパイルされた最新の gcc ツールチェーンを使用して manylinux をターゲットにしていました。古いバージョンの libstdc++ との互換性問題を避けるため、libstdc++ を静的にリンクしていました。
しかし、このアプローチは最近いくつかの問題を引き起こしました。一部の libstdc++ 機能はグローバル初期化を使用します。これにより、PyTorch によって動的にリンクされる libstdc++ と kernel によって静的にリンクされる libstdc++ のように、複数の libstdc++ バージョンが関与する場合にデータが破損する可能性があります。最近の kernel の中には、グローバル初期化を引き起こす機能(例: C++ の正規表現)を使用するものがあり、これがデータ破損を引き起こし、セグメンテーション違反などの問題を発生させていました。
この問題を解決するため、kernels は libstdc++ を動的にリンクするようになりました。古い libstdc++ バージョンとの互換性を確保するため、公式の manylinux_2_28 ツールチェーンで kernel をコンパイルするようになりました。
結論
Kernels プロジェクトの目標は、kernel 開発者とカスタム kernel のユーザーの両方に役立つことです。改善方法についてのコミュニティからのフィードバックを常に歓迎しています。ぜひ貢献してください!
謝辞: 記事のレビューをしてくれた Aritra に感謝します。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.