View in English

  • メニューを開く メニューを閉じる
  • Apple Developer
検索
検索を終了
  • Apple Developer
  • ニュース
  • 見つける
  • デザイン
  • 開発
  • 配信
  • サポート
  • アカウント
次の内容に検索結果を絞り込む

クイックリンク

5 クイックリンク

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • トピック
  • すべてのビデオ
  • 利用方法

WWDC25に戻る

  • 概要
  • トランスクリプト
  • コード
  • Metal 4による機械学習とグラフィックスの統合

    Metal 4を使用してグラフィックスアプリに機械学習をシームレスに統合する方法を紹介します。レンダリングやコンピューティングのタスクと並行してGPUのタイムラインでモデルを実行するための、テンソルリソースとMLエンコーダの概要を説明します。シェーダMLにおいて、高度なエフェクトの適用と性能の向上のためにシェーダ内にニューラルネットワークを直接埋め込む方法を解説します。また、Metal 4のMLワークロード向けの新しいデバッグツールの使用例を、サンプルアプリを用いたデモでお見せします。

    関連する章

    • 0:00 - イントロダクション
    • 2:52 - テンソルについて
    • 6:21 - MLネットワークのエンコード
    • 12:51 - シェーダへのMLの埋め込み
    • 20:26 - MLワークロードのデバッグ

    リソース

    • Customizing a PyTorch operation
    • Metal Developer Resources
    • Metal Performance Shaders
      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC25

    • イマーシブなアプリを作成するためのMetalレンダリングの新機能
    • Metal 4の概要
    • Metal 4ゲームの知識を深める
    • Metal 4ゲームの詳細

    WWDC24

    • Apple GPUでの機械学習モデルとAIモデルのトレーニング
    • Metalによる機械学習の加速
  • このビデオを検索

    AppleのMetal Frameworkチームの エンジニア Preston Provinsです 同僚のScottも後で参加します 機械学習とゲームを統合するMetalの 追加機能について説明します ScottはMetal 4の 機械学習のデバッグ操作を 向上させるために設計された 追加のGPUツールを紹介します このセッションでは Metal 4での機械学習とグラフィックスの 統合方法をご説明します Metal 4が提供するすべての機能 について詳しくお知りになりたい方は Metal 4の基礎に関する説明をご覧になり Metal 4の他の新機能を学習してください 機械学習ではアップスケーリング アセット圧縮 アニメーションブレンディング ニューラルシェーディングなどの技術を 使ってゲームやグラフィックに 変革をもたらしています これらの技術によって創造性と 没入感の限界が広がります 複雑な現象をシミュレートし 視覚的な忠実度が向上します また新しいスタイルや効果を 効率的に調べることができます CoreMLは セグメンテーション 分類や生成AIなど 幅広い機械学習タスクに最適です 機械学習モデルの作成が容易になります 機械学習のアプリケーションで GPUタイムラインとの 緊密な統合が必要になる場合 Metal 4がこれに対応します 一般的なフレームでは ゲームは演算パスで頂点スキニングを実行し レンダリングパスでシーンをラスタライズし 別の演算パスでアンチエイリアスを 適用できます アンチエイリアスは通常 テンポラルアンチエイリアスなどの 画像処理技術を使って行われます 最先端の技術により こうした従来の方法が 機械学習ネットワークに置き換わります このネットワークは 画像をアップスケールし 残りのレンダリングを 低解像度で実行できるようにして パフォーマンスを向上させます

    シェーダ内で小さなニューラルネットワーク を実行することも一般的になりつつあります 従来のフラグメントシェーダはマテリアル テクスチャをサンプリングしますが 画期的な技術により 小さなニューラルネットワークを使った テクスチャの即時解凍や より高い圧縮率の実現が可能になりました このニューラルレンダリング技術は マテリアルセットを ブロック圧縮されたフットプリントの 50%にまで圧縮します このセッションでは 機械学習ワークフロー用の Metal 4の新しいリソースである MTLTensorについて説明します MTL4MachineLearningCommand Encoderについて詳しく説明します この新しいエンコーダタイプは 他の描画やディスパッチと並行して GPUタイムライン上でネットワーク全体を 実行します シェーダMLについて説明します これを使うと機械学習操作を独自の シェーダ内に埋め込むことができます 最後に Metalデバッガを使ってMLを アプリケーションにシームレスに 統合する方法を説明します MTLBufferとMTLTextureについては もうご存じかと思われます 今年Metal 4は新しいリソース MTLTensorを導入し かつてないほど簡単に機械学習を データに適用できるようになりました MTLTensorは 演算 グラフィックス 機械学習のコンテキストで使える 基本的な機械学習のデータ型です 機械学習ワークロードでは テンソルが広く利用されます MTL4MachineLearning CommandEncoderは MTLTensorを使って入力と出力を表し シェーダMLはMTLTensorを使って 重みおよび入力と出力を表します

    MTLTensorはデータ用の 多次元コンテナであり ランクと各ランクの次元数 によって表されます MTLTensorは2次元を 超えて拡張可能であり 実用的な機械学習の用途に必要な データレイアウトを 柔軟に表現できます たとえばMTLTextureは最大で 4つのチャネルに制限されており テクスチャフォーマットに応じて その範囲に厳密な制限があります 機械学習では 畳み込み演算など 2次元を超えるデータを使うことが 一般的です MTLBufferのような平坦な データ表現を使用する場合 複数の次元を持つデータに対して 複雑なインデックス付けスキームが 必要になります MTLTensorでの多次元データに対する インデックス作成は非常に簡単です 各ランクのストライドと次元が MTLTensorオブジェクトに 組み込まれており インデックス計算で 自動的に使用されるためです MTLTensorを作成する プロセスを見ていきましょう MTLTensorのランクは 軸がいくつあるかを表します このMTLTensorのランクは2です データの行と列で構成されています 次元の範囲はその軸に沿った データ ポイントの数を表します dataTypeプロパティはMTLTensorが ラップしているデータの形式を定義します 使用方法を示すプロパティはMTLTensor が どのように利用されるかを示します MTLTensorUsage MachineLearningは MTL4MachineLearning CommandEncoder用 MTLTensorUsageComputeや MTLTensorUsageRenderは シェーダプログラム内で使います テクスチャのusageプロパティのように 用途を組み合わせることもできます これらはMTLTensorDescriptor オブジェクトに設定すべき 重要なMTLTensorプロパティです ではコードでMTLTensorを作ってみましょう 記述子のプロパティが入力されたら MTLDeviceオブジェクトで newTensorWithDescriptor: offset:error:を呼び出し 新しいMTLTensorを作成します MTLTensorはMTLDeviceオブジェクト または MTLBufferオブジェクトから作成されます ただし デバイスから作成された MTLTensorが 最高のパフォーマンスを発揮します MTLTexturesをスウィズルする方法と 同様に MTLDeviceオブジェクトから MTLTensorを 作成すると 読み取りや書き込み用に最適化 された不透明なレイアウトが生成されます では既存のMTLBufferからの MTLTensorの作成を見てみましょう MTLDeviceから作成された MTLTensorとは異なり MTLBufferから作成されたMTLTensorは 密にパックされることを 想定していないため ストライドを 指定する必要があります 最も内側のストライドは 常に1である必要があります 2番目のストライドは行インデックスが 増分されるときに いくつの要素がスキップされるかを示します

    ソースMTLBufferには 行末にある 未使用の列などのパディングが 含まれている可能性があります MTLTensorが適切な要素をラップするには パディングを考慮する必要があります 基盤となるバッファから MTLTensorを作成するには デバイスに割り当てられたテンソルと同様に dataTypeとusageの プロパティを設定します 次にMTLTensorDescriptorの stridesプロパティを設定します この結果として得られるMTLTensorが MTLBufferの内容を適切にラップします 最後にソースのMTLBufferで newTensorWithDescriptor: offset:error:を使います 以上でMTLTensorを割り当てて 作成する方法について説明しました 次は新しい機械学習エンコーダについて 詳しく説明します MLの処理をGPUタイムラインに 追加してみましょう Metal 4では MTL4ComputeCommandEncoderと MTL4RenderCommandEncoderを使い 演算コマンドとレンダリングコマンドを それぞれGPUタイムラインに 簡単に追加できます 今年は機械学習の処理を GPUタイムラインに追加することで 統合をさらに推し進めます MTL4MachineLearning CommandEncoderでは モデル全体をGPU上の 他のMetalコマンドと 並行して実行し同期させることができます また他のMTLCommandsとの シームレスな統合を実現します これは機械学習コマンドをエンコード するための新しいエンコーダで 演算エンコーダやレンダリングエンコーダに 似たインターフェイスがあります Metal 4同期プリミティブは 演算やレンダリングと同様に 機械学習コマンドでも動作します 同期によりワークオーケストレーションの 制御が可能になり 並列処理が容易になったため 高いパフォーマンスを維持できます MTL4MachineLearningCommand Encoder作成ワークフローは オフラインとランタイムの 2つの部分に分けることができます ワークフローのオフライン部分は アプリケーションの起動前に実行され ランタイム部分はフレームの途中など アプリケーションの動作中に実行されます ワークフローのオフライン部分から始めて MTLPackageを作成しましょう MTLPackageは1つ以上の関数を 格納するコンテナであり 各関数はMLネットワークを表します MTLPackageはMetalで機械学習の 処理を実行するために使用できます この形式はMetalでの読み込みと 実行用に最適化されています MTLPackageを作成するには まずCoreMLパッケージが必要です ここではCoreMLコンバータを使って ネットワークが作成された MLフレームワーク (PyTorchやTensorflowなど)から CoreMLパッケージに 変換します これはPythonのCoreMLツール ライブラリを使用して PyTorchモデルをエクスポートする例です ツールをインポートし モデルでconvertを実行するだけで エクスポートが生成されます 最後にそのエクスポートを MLパッケージとして保存します ここで強調したいことがあります すべてのCoreMLパッケージが MLプログラムというわけではなく サポートされているのは MLプログラムのみだということです CoreMLパッケージが古いOSで エクスポートされた場合 この記事を参照してCoreMLモデルファイルを MLパッケージとしてエクスポートする方法の 詳細を確認してください CoreMLパッケージを作成したら 保存したモデルに対して metal-package-builderコマンドラインを 実行するだけで MTLPackageを生成できます これによりCoreMLパッケージが 実行時に効率的に読み込める 形式に変換されます MTLPackageの作成は以上です ワークフローのオフライン部分は完了し 残りの部分は実行時に開始されます ネットワークをコンパイルするには まずMTLPackageを MTLLibraryとして開きます パッケージ内のネットワークを表す 関数の名前を使用して 関数記述子を作成します この場合はmain関数です MTL4MachineLearningPipelineState を作成してネットワークをコンパイルします ここでは 関数記述子とMTL4Machine LearningPipelineStateDescriptor を使います ネットワークに動的入力がある場合はMTL4 MachineLearningPipelineStateDescriptor で各入力のサイズを指定します 特定のデバイス向けに ネットワークをコンパイルするには MTL4MachineLearningPipeline StateDescriptorを使って MTL4MachineLearningPipeline Stateを作成します

    MTL4MachineLearningPipelineState オブジェクトの作成は以上です 次のステップではMTL4Machine LearningCommandEncoderを作り 処理をエンコードします MTL4MachineLearning CommandEncoder オブジェクトを使って GPUタイムラインで処理をディスパッチする 方法を詳しく見てみましょう MTL4MachineLearningCommand Encoderオブジェクトを作成します これは演算やレンダリングの エンコーダの作成と同様です 作成したMTL4MachineLearning PipelineState オブジェクトを設定し 使用する入力と出力をバインドします dispatchNetworkWith IntermediatesHeap メソッドを使って処理をディスパッチします

    機械学習エンコーダは ヒープを使って操作間の 中間データを保存します バッファを作成して解放する代わりに 異なるディスパッチでの リソースの再利用を可能にします このMTLHeapを作成するには MTLHeapDescriptorを作成し typeプロパティを MTLHeapTypePlacementに設定します パイプラインのintermediateHeapSizeを 照会することで ネットワークの最小ヒープ サイズを 取得できます ヒープのsizeプロパティは その値以上になるように設定します ネットワークディスパッチのエンコード後 エンコードを終了し コマンドを送信して GPUタイムライン上で実行します

    先に説明したように Metal 4同期プリミティブは 演算やレンダリングと同様に 機械学習コマンドでも動作します 機械学習の出力に依存しない処理は 適切に同期されていれば同時に実行できます

    ネットワークの出力を使用する処理だけが スケジュールされた機械学習処理の完了を 待機する必要があります

    MTL4MachineLearningCommand Encoderディスパッチを同期するには MTLBarriersやMTLFencesなどの 標準Metal4同期プリミティブを使います 新しいMTLStageMachineLearningは バリアのMLワークロードを 特定する際に使います たとえばネットワークによって生成された 出力を待機して レンダリング処理を行うには 適切なレンダリングステージと 機械学習ステージの間にバリアを使えます MTL4MachineLearningCommand Encoderの動作を見てみましょう MTL4MachineLearning CommandEncoderで 完全な畳み込みネットワークをディスパッチし ピクセルごとのオクルージョン値を 予測します これを評価するには慎重な同期が必要です 深度バッファとビュー空間の法線は MLワークロードの起動前に設定されます ネットワークでのデータの処理中 レンダラは他のレンダリング関連の タスクを並行してディスパッチし 最終フレームを合成する前に ニューラルの結果を待機します MTL4MachineLearning CommandEncoderは ゲームのフルフレーム情報の処理に限らず リアルタイムの予算に収まる あらゆるネットワークに使用でき Metal 4同期プリミティブを活用することで 統合のニーズに最適な方法で利用できます このようにMetal 4のMTL4Machine LearningCommandEncoderにより GPUタイムライン上で大規模な機械学習 ワークロードを簡単に実行できます まとめると MTL4MachineLearningCommand Encoderにより 機械学習はMetal 4の演算やレンダリングと統合されました MTL4MachineLearningCommand Encoderにより 全ネットワークをGPUタイムラインで 実行できます リソースは他のGPUコマンドと共有可能で 強力なMetal 4同期プリミティブの セットにより 高性能な機械学習処理が実現されます Metal 4では 既存のカーネルや シェーダー内に小規模な 機械学習操作を埋め込むための シェーダMLも導入されています 最先端のゲームでは 従来のレンダリングアルゴリズムに代わって 機械学習を採用しています MLベースの技術によって グローバルイルミネーション マテリアルシェーディング ジオメトリ圧縮 マテリアル圧縮などの ソリューションが提供されます これらの技術はパフォーマンス向上や メモリ占有量削減を実現する場合があります わかりやすい例としてニューラルマテリアル 圧縮を考えてみましょう これはブロック圧縮形式と比べて 最大50%の圧縮を可能にする技術です 従来のマテリアルでは アルベドや法線マップなどの マテリアルテクスチャをサンプリングします ではサンプリングされた値で シェーディングを行います ニューラルマテリアル圧縮で潜在的な テクスチャデータをサンプリングします サンプリングした値で推論を実行し ネットワーク出力を使って シェーディングを実行します

    各ステップを独自のパイプラインに 分割するのは非効率的です 各ステップではデバイスメモリに対して テンソルを同期し 出力の操作後は後続の操作のために 出力を同期し直す必要があるからです

    パフォーマンスを最大化するには これらのステップを1つの シェーダディスパッチに統合します シェーダMLを使うと Metalでは フラグメントシェーダ内で MLネットワークを直接実行でき ステップ間でデバイスメモリを 経由する必要がありません 入力テンソルを初期化し ネットワークを実行し 各フレームで必要なピクセルのみを シェーディングできます これにより実行時のメモリ占有量や ゲームのディスク容量が改善されます ニューラルマテリアル評価について 詳しく見てみましょう 入力MTLTensorの初期化は ネットワークの重みの読み込みと 入力フィーチャMTLTensorの構築の 2つの部分に分けられます 入力フィーチャMTLTensorは フラグメントのUV座標を使いバインドされた テクスチャをサンプリングして作られます

    推論では学習した重み行列によって 入力フィーチャMTLTensorが変換され フィーチャの抽出や 活性化の演算が行われ レイヤを通じて情報が伝播されます この評価は複数のレイヤに対して繰り返され その結果 解凍されたマテリアルが得られます 最終的には解凍されたマテリアルは フラグメントのシェーディング計算に 使われます

    シェーダMLを使った入力MTLTensorの 初期化方法を見てみましょう まずシェーダMLを利用する フラグメントシェーダを宣言し ネットワークの重みを渡します 新しいmetal_tensorヘッダを含めます MTLTensor型を使ってネットワークの 重みにアクセスします MTLTensorはバッファバインディングスロット を使ってシェーダにバインドされます 引数バッファを使って MTLTensorを渡すこともできます MTLTensor型はテンプレート化 されています 最初のテンプレート引数は MTLTensorのdataTypeです これらのMTLTensorは デバイスメモリ内に作成されたため デバイスアドレス空間修飾子を使います 2番目の引数はMTLTensorの次元と MTLTensorに対するインデックス作成に 使われる型を表します ここではdextentsを使い 動的エクステント を持つランク2のテンソルを定義しています フラグメントシェーダが設定されました ニューラルマテリアル圧縮アルゴリズムを 実装しましょう ネットワークの重みを渡すと 4つの潜在的なテクスチャをサンプリング することで入力MTLTensorを作成できます MTLTensorはバインドできる 単なるリソースではなく シェーダ内でインラインMTLTensorを 直接作成することもできます サンプリングされた値をラップする MTLTensorを作成し ネットワークの評価に使います インラインMTLTensorは緊密に パックされることを前提としているため 作成時にストライドを渡す必要はありません これで入力MTLTensorの初期化は 完了です ニューラルネットワークからの値を 推論する設定ができました 評価では学習したパラメータで入力を変換し 入力はその後活性化されます 活性化は後続のレイヤに渡され 最終レイヤの活性化が 解凍されたマテリアルを形成します

    今年 Metalは Metalパフォーマンスプリミティブを導入し シェーディング言語で MTLTensor操作を利用可能にします このライブラリは 高性能なAPIのセットです MTLTensorでパフォーマンスの移植性を 備えたソリューションを実現します 行列乗算や畳み込みの演算を実行できます 行列乗算はニューラルネットワーク評価の 中心となるものです Metalパフォーマンスプリミティブの matmul2d実装を使って パフォーマンスの移植性を備えた ネットワーク評価ルーチンを実装します 始めに 新しいMetalPerformance Primitivesヘッダを Metalシェーダ内に挿入します 行列乗算のパラメータは matmul2d_descriptorオブジェクトを使って 設定します テンプレートパラメータの最初のセットは 行列乗算の問題のサイズを指定します テンプレートパラメータの次のセットは 演算の実行時に行列乗算への入力を 転置する必要があるかどうかを制御します 最後のテンプレートパラメータは 精度要件を制御します

    記述子に加えて 演算に関連するスレッドの数を使って matmul2d演算を特殊化する 必要があります フラグメントシェーダで作業しているため execution_threadを使って このスレッドが行列乗算全体を 実行することを示します 次に その設定を使って 行列乗算を実行します

    最後に ReLU活性化関数を使って 行列乗算の結果の各要素を活性化します このプロセスは2番目の レイヤでも繰り返され シェーダ内でネットワークが 完全に評価されます 評価が完了すると 解凍されたマテリアルがシェーディングで 利用できるようになります 出力MTLTensorは チャンネル情報を保持しており この情報はテクスチャからサンプリングした 他の値と同様に利用できます これはニューラルマテリアル圧縮と 従来のマテリアルを比較した リアルタイムデモです ニューラルマテリアルを使っても 特にシェーディング時には 品質の低下は認識されません これはベースカラーのみのデモです ニューラルマテリアルと従来のマテリアルの 違いはほとんどわかりませんが ニューラルマテリアルでは メモリ使用量やディスク容量が 半分ですみます

    MTLTensor操作はフラグメントシェーダ 専用というわけではありません すべての関数と すべてのシェーダステージでも使えます simdgroupやthreadgroup全体が 同じデータに対して同じ操作を行う場合 より大きな実行グループを選ぶことで ハードウェアを有効に活用できます ただしMTLTensor操作が データに対して分岐していたり MTLTensor操作の呼び出し箇所で 不均一な制御フローを示す場合は 単一スレッドの実行グループを 使う必要があります 他の実行スキームでは 実行グループに対して 分岐や不均一な制御フローが ないと想定します これで 独自のシェーダで行列乗算や 畳み込みなどのML操作を実行できます シェーダーMLを使えば 複数のML操作を 1つのシェーダーで簡単に実行できます これはキャッシュフレンドリで ディスパッチやメモリ帯域幅が少なくて済み 特に小規模なネットワークに適しています またシェーダMLでは カスタム操作の作成に必要な 詳細な制御ができます Metalアプリへの最先端のML技術の 実装が これまでになく簡単になりました 以上の方法で シェーダMLを使って ニューラルネットワークを シェーダプログラムに 埋め込むことができます では同僚のScottにバトンタッチします Metal 4の新しいデバッグツールを使って 機械学習ワークロードのデバッグを 簡単に行う方法を説明します こんにちは GPU Toolsチームの ソフトウェアエンジニア Scott Moyersです 先ほど Prestonが機械学習を使って アンビエントオクルージョンを計算する アプリケーションについて説明しました このアプリでは 機械学習ネットワークを Metalレンダリングパイプラインに 直接エンコードします このアプリの開発を手伝っているとき 出力に深刻なアーティファクトが 発生するという問題が発生しました アンビエントオクルージョンパスだけを 有効にして 問題を強調してみます オブジェクトの角に影があるはずなのに ノイズが多くてシーンの構造が ほとんど見えません 新しいツールを使って 問題の検出と修正を どのように行ったかを紹介します まず XcodeでアプリのGPUトレースを 取り込みます そのためには 画面下部のアイコン ボタンの順にクリックします

    キャプチャが完了すると取り込んだ フレームがに表示されます 左側のデバッグナビゲータには アプリケーションが フレームの構築に使った コマンドの一覧が表示されます たとえば オフスクリーンの コマンドバッファには G-Bufferパスなどの 多くのエンコーダが含まれています 次のコマンドバッファに含まれているのは MTL4MachineLearningCommand Encoderです Metal 4を使うと同期を 詳細に制御できました 依存パス間のバリアやイベントの設定には 注意していましたが 同期の不具合がこれらの問題の 原因ではないかと考えました これを確認するために Metalアプリケーションの構造の概要を 把握するための便利なツールである 依存関係ビューアを使いました 左上のアイコンを クリックします

    このインターフェイスを使うと バリアや イベントなどの同期プリミティブと アプリケーションのすべてのコマンドを 確認できます コマンドエンコーダを拡大すると さらに詳細が表示されます 最初のコマンドバッファの完了があります

    その下のコマンドは 法線をMTLTensorにコピーします 次にバリアがあり その次が MTL4MachineLearningCommand Encoderです 全体的な構造を確認するために コマンドエンコーダを縮小します 新しいアンビエントオクルージョンパスは 右のコマンドバッファにあります このパスを追加する前は アプリケーションは正常に動作していたため 上部と下部のコマンドバッファ内の 依存関係は 正しいと考えられます MTL4MachineLearningCommand Encoderを含む 新しいコマンドバッファを調べます

    コマンドバッファを開始する前に 共有イベントシグナルを待機します コマンドバッファの最後に次のバッファの ブロックを解除するシグナルがあります このため このコマンドバッファと並行して 他のコマンドを実行することはできません コマンドバッファ内では 各エンコーダ間にバリアがあり 各コマンドが順番に 実行されるようになっています この時点では 少なくともこのフレーム内に 同期の問題はないと確信していました そこでMTL4MachineLearningCommand Encoderを直接確認することにしました アンビエントオクルージョンネットワークの ディスパッチ呼び出しをクリックすると バインドされたリソースに移動します 右側では アシスタントエディタに 出力MTLTensorが表示されています 実行中のアプリケーションと 同じアーティファクトを確認できるので 明らかに正しくありません 入力MTLTensorをダブルクリックして 出力の横に表示します 入力にはビュー空間の法線として想定される ものが含まれています 異なる方向を向いているオブジェクトには 異なる成分強度が含まれています つまり問題は機械学習ネットワーク内に あるはずです バインドされたリソースのビューに戻り 今度はをダブルクリックして 新しいMLネットワークデバッガで開きます このツールはモデル内で 何が起こっているかを理解する上で重要です

    このグラフはアンビエントオクルージョン ネットワークの構造を表しています これはPyTorchで記述しました ターゲットのビルドフェーズでは 先ほどPrestonが提案したことを実行して CoreMLパッケージとしてエクスポートし MTLPackageに変換します ボックスは操作を示し 接続はモデル内における 左から右へのデータフローを示します 私はどの操作によってアーティファクトが 発生したのかを知りたかったのです 最終的な出力に問題があり 入力は適切であることはわかったので グラフを二分して絞り込みました ほぼ中間にある操作を選んでみましょう 操作を選ぶと右側にその説明が表示され その属性や入力と出力も表示されます また 操作が出力する 中間MTLTensorデータを 調べることもできます プレビューをクリックして MTLTensorビューアに表示します アーティファクトは ここで確認できるので これより前の操作を調べます

    この操作でも出力に アーティファクトが発生します 入力を調べてみましょう

    このMTLTensorはシーン内のエッジを 強調表示しているように見えますが これは想定通りであり またネットワークへの入力は 深度バッファから抽出されたエッジです つまり ネットワーク領域内に 何か問題があるようです

    この結合された領域は 操作の左上にある矢印をクリックすると 展開できます

    これらの操作の順序とタイプから これがSignedSmoothstep関数 であることがわかります 最初に入力の絶対値を取得します 次に 値を0から1の間に制限します しかし その結果が結果自体の 累乗になっており 正しくないと思われます SignedSmoothstep関数には 累乗演算はなかったはずです 何が起きているのか確認するために Pythonコードを調べてみましょう デバッグセッションを停止して ソースコードに戻ります

    実行しているモデルは LightUNetというクラスにあります 想定通りの動作をしているか 順伝播関数を調べてみます

    最初に実行するカスタム操作は SignedSmoothstepです これはMLネットワークデバッガで確認した 結合された領域です 順伝播関数に移動します

    これは入力の符号を維持する 単純なsmoothstep操作のはずです しかしこの行で バグが見つかりました アスタリスクを多く入力したため 乗算が累乗演算になっています 余分なアスタリスクを削除して 再度実行してみます

    これで Metal 4の組み込み MTL4 MachineLearningCommandEncoder を使ったニューラルアンビエント オクルージョンの実装が動作します

    このデモでは Metalデバッガを使った Metal 4機械学習アプリケーションの デバッグ方法を紹介しました 最初に 依存関係ビューアを使って 同期を検証しました 次に MTLTensorビューアで ネットワークの入出力を調べ 問題がネットワーク内部に あることを確認しました 最後に MLネットワークデバッガを使って ネットワーク内の操作をステップ実行し 問題を特定しました

    これらのツールはMetalアプリのデバッグや 最適化に利用できる ツールのファミリーに含まれています では これまでの内容をまとめましょう Metal 4ではMTLTensorが導入されています MTLTensorは機械学習データ専用に 設計された新しい多次元リソースです MTLTensorは2次元を超える複雑な データレイアウトに柔軟に対応できます ストライドと次元の情報が内蔵されており インデックス作成を大幅に簡素化できます Metal 4の新機能により 機械学習ワークロードを Metalパイプラインに統合できます MTL4MachineLearningCommand Encoderにより 機械学習ネットワーク全体をGPUタイム ライン上で直接実行できます これにより 演算やレンダリング処理との シームレスな統合と同期を実現できます 小規模なネットワークでは シェーダMLとMetalパフォーマンスプリミティブ ライブラリを使うと 機械学習操作をシェーダに 直接埋め込むことができます 最後になりますが Metalデバッガを使うと Metal 4アプリケーションの実行内容を 非常に詳細に可視化できます 新しいMLネットワークデバッガによって ネットワークを理解し デバイス上で どのように実行されるかを把握できます こうした情報は 正確性の確保と パフォーマンスの最適化に不可欠です 次のステップとして 最新のOSとXcodeをインストールし Metal 4の MTL4MachineLearningCommand Encoderと シェーダMLを実際に試してみてください Metalデベロッパツールが どのように役立つかについて詳しくは Apple Developer Webサイトを ご覧ください Metal 4アプリケーションを 最大限活用するには 他のMetal 4に関する説明もご覧ください これらの新機能で皆さんが 何を構築するのかを楽しみにしています ありがとうございました

    • 8:13 - Exporting a Core ML package with PyTorch

      import coremltools as ct
      
      # define model in PyTorch
      # export model to an mlpackage
      
      model_from_export = ct.convert(
          custom_traced_model,
          inputs=[...],
          outputs=[...],
          convert_to='mlprogram',
          minimum_deployment_target=ct.target.macOS16,
      )
      
      model_from_export.save('model.mlpackage')
    • 9:10 - Identifying a network in a Metal package

      library = [device newLibraryWithURL:@"myNetwork.mtlpackage"];
      
      functionDescriptor = [MTL4LibraryFunctionDescriptor new]
      functionDescriptor.name = @"main";
      functionDescriptor.library = library;
    • 9:21 - Creating a pipeline state

      descriptor = [MTL4MachineLearningPipelineDescriptor new];
      descriptor.machineLearningFunctionDescriptor = functionDescriptor;
      
      [descriptor setInputDimensions:dimensions
                       atBufferIndex:1];
      
      pipeline = [compiler newMachineLearningPipelineStateWithDescriptor:descriptor
                                                                   error:&error];
    • 9:58 - Dispatching a network

      commands = [device newCommandBuffer];
      [commands beginCommandBufferWithAllocator:cmdAllocator];
      [commands useResidencySet:residencySet];
      
      /* Create intermediate heap */
      /* Configure argument table */
      
      encoder = [commands machineLearningCommandEncoder];
      [encoder setPipelineState:pipeline];
      [encoder setArgumentTable:argTable];
      [encoder dispatchNetworkWithIntermediatesHeap:heap];
    • 10:30 - Creating a heap for intermediate storage

      heapDescriptor = [MTLHeapDescriptor new];
      heapDescriptor.type = MTLHeapTypePlacement;
      heapDescriptor.size = pipeline.intermediatesHeapSize;
              
      heap = [device newHeapWithDescriptor:heapDescriptor];
    • 10:46 - Submitting commands to the GPU timeline

      commands = [device newCommandBuffer];
      [commands beginCommandBufferWithAllocator:cmdAllocator];
      [commands useResidencySet:residencySet];
      
      /* Create intermediate heap */
      /* Configure argument table */
      
      encoder = [commands machineLearningCommandEncoder];
      [encoder setPipelineState:pipeline];
      [encoder setArgumentTable:argTable];
      [encoder dispatchNetworkWithIntermediatesHeap:heap];
      
      [commands endCommandBuffer];
      [queue commit:&commands count:1];
    • 11:18 - Synchronization

      [encoder barrierAfterStages:MTLStageMachineLearning
                beforeQueueStages:MTLStageVertex
                visibilityOptions:MTL4VisibilityOptionDevice];
    • 15:17 - Declaring a fragment shader with tensor inputs

      // Metal Shading Language 4
      
      #include <metal_tensor>
      
      using namespace metal;
       
      [[fragment]]
      float4 shade_frag(tensor<device half, dextents<int, 2>> layer0Weights [[ buffer(0) ]],
                        tensor<device half, dextents<int, 2>> layer1Weights [[ buffer(1) ]],
                        /* other bindings */)
      {
          // Creating input tensor
          half inputs[INPUT_WIDTH] = { /* four latent texture samples + UV data */ };
      
          auto inputTensor = tensor(inputs, extents<int, INPUT_WIDTH, 1>());
          ...
      }
    • 17:12 - Operating on tensors in shaders

      // Metal Shading Language 4
      
      #include <MetalPerformancePrimitives/MetalPerformancePrimitives.h>
      
      using namespace mpp;
      
      constexpr tensor_ops::matmul2d_descriptor desc(
                    /* M, N, K */ 1, HIDDEN_WIDTH, INPUT_WIDTH,
             /* left transpose */ false,
            /* right transpose */ true,
          /* reduced precision */ true);
      
      tensor_ops::matmul2d<desc, execution_thread> op;
      op.run(inputTensor, layerN, intermediateN);
      
      for (auto intermediateIndex = 0; intermediateIndex < intermediateN(0); ++intermediateIndex)
      {
          intermediateN[intermediateIndex, 0] = max(0.0f, intermediateN[intermediateIndex, 0]);
      }
    • 18:38 - Render using network evaluation

      half3 baseColor          = half3(outputTensor[0,0], outputTensor[1,0], outputTensor[2,0]);
      half3 tangentSpaceNormal = half3(outputTensor[3,0], outputTensor[4,0], outputTensor[5,0]);
      
      half3 worldSpaceNormal = worldSpaceTBN * tangentSpaceNormal;
      
      return baseColor * saturate(dot(worldSpaceNormal, worldSpaceLightDir));

Developer Footer

  • ビデオ
  • WWDC25
  • Metal 4による機械学習とグラフィックスの統合
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習とAI
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード(英語)
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    Apple Developerアプリを入手する
    Copyright © 2025 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン