ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
Metal Performance Shaders Graphによる機械学習の加速
Metal Performance Shaders Graphは、線形代数、機械学習、コンピュータビジョン、および画像処理のためのカスタマイズされた多次元グラフをビルド、コンパイル、および実行するのに役立つ計算エンジンです。Apple製品のMetalバックエンドを通じて、MPSGraphが人気のTensorFlowプラットフォームをいかにして加速できるかについて紹介します。グラフに制御フローを加えたり、グラフのコンパイルを管理してパフォーマンスを最適化したり、MPSGraphオペレーションを使用してわずか数行のコードで最もハードな演算アプリケーションを高速化する方法を確認します。
リソース
- Metal
- Metal Performance Shaders
- Metal Shading Language Specification
- Training a Neural Network with Metal Performance Shaders
関連ビデオ
WWDC22
WWDC20
-
ダウンロード
こんにちは サハーシュ・オーザです GPUソフトウェア エンジニアリングの担当です 本日は同僚の ユリヤ・ピリピヴと― Metal Performance Shader Graphの新機能について― お話しします MPSは 画像処理 線型代数学 レイトレーシング 機械学習など さまざまな分野向けの Metalベースの高性能 GPU促進型プリミティブの ライブラリです MPSチームは Metalカーネルを最適化し― Appleのさまざまな プラットフォームで― 最高のパフォーマンスを 提供します 去年 我々は一般的な目的に 使用するGPU向けの― MPSGraphフレームワークを 発表しました これはMPSフレームを同様に macOS iOS iPadOS tvOSに対応します MPSGraphの前置き情報に 関しては― 去年のセッションを ご覧ください 本日の予定は以下の通りです お話することが たくさんあります MPSGraphを通じた ML推論と― トレーニングの加速について 期待の新しい MPSGraph運用について MPSGraphで コンピレーションを― 管理する新しい方法について そして最後に MPSGraphの 新しいすべての制御フロー 機能についてお話しします では同僚のユリアが― 推論とトレーニング加速に ついての― 最新情報をお届けします サハーシュ ありがとう こんにちは ユリヤ・ピリピヴです GPUソフトウェアチームに 属しています 本日は GPUのトレーニングと― 推論パフォーマンスの 改善についてお話しします ではさっそく始めましょう MPSGrapフレームワークは GPUを加速するために Core MLやTensorFlowなど 高度な― 機械学習フレームワークに 導入されています 今年我々は カーネルの改善と― スティッチングの導入で MPSGraphを― さらに最適化しました これによりMPSを使用する― 機械学習フレームワークの 性能が大きく改善しました ではTensorFlowの Metal Pluginの― 詳細を見てみましょう TensorFlowは人気のある プラットフォームで― GPUは有力な加速装置です 今年我々はTensorFlow 2.5.でリリースされた― PluggableDevice Interfaceを使用して― 新しいMetal Pluginを 開発しました これでMPSと MPSGraphを使って― Metalの力を TensorFlowにもたらします これによりMac プラットフォームGPUで― どんな機械学習モデルでも 変更なしに訓練できます では1つ実演してみましょう このデモでは Jupyter環境を使用します 私のM1システムには― 最新のTensorFlowが インストールされています 物理デバイスのリストを 作ると― CPUデバイスのみが 登録されています
ここで 画像分類 転送学習など― 広範囲で使用されている 人気の機械学習モデル Resnet50を定義します
現在のモデルは 画像サイズが224x224の 標準のImageNet データセットを使用します
ご覧のとおり CPUで実行されている― 最初のエポックの 現在のETAは約20分です 先ほどご紹介した TensorFlow Metal Pluginを インストールして― 現在のネットワークの 高速化が可能か確認します これには― pip install tensorflow- metalを使用し―
先ほど使用したResnet50 モデルに戻ります
ただし今回は― 新しいGPUデバイスが 登録されています このGPUデバイスが Metal Pluginを使用した― TensorFlow プラットフォームの一部です
すべてのコールバックと ネットワークの定義は― 同じままです ETAを比較するために再び ネットワークを開始します GPU版の 同じネットワークは― TensorFlow Metal Pluginを 使用して― 4倍の速さで学習しています
では 他のネットワークの 詳細を見てみましょう これはCPUに関連する 主要な機械学習 トレーニングベンチマークの パフォーマンスです すべてのベンチマークで スピードアップが確認され― M1 MacBook Proで 最大 8倍の速さになっています
新しいMetal Pluginの インストールは簡単です pip install tensorflow-macosを使い― ベースTensorFlowを インストールした後― pip install tensorflow-metalを使用し Metal Pluginを インストールします Metal Pluginは 公式のPython― パッケージ/リポジトリで 利用可能になります 環境設定とインストールの 詳細いついては― Metalデベロッパー リソースをご覧ください TensorFlowについては 以上です 次はCore MLの推論の 加速についてお話しします
Core MLはAppleの機械学習 推論フレームワークです MPSGraphにより Core MLに― 著しい改善が見られました ここにはM1の 機械学習ネットワークの 主要なクラスの推論の 高速化が示されています NLP Appケーションに 使用される 標準的なTransformer ネットワークの― BERTは2倍の加速 コンピュータービジョン AppResnet50は 前回のリリースでテキスチャ パスが微調整されています これはMPSGraphを介した バッファバックエンドで― パフォーマンスがさらに16% 改善しました Core MLとTensorFlowの これらの改善は― Convolution2Dなどの― MPSプリミティブが 寄与しています ここでは 訓練と推測に使用される― NHWCとNCHW データレイアウトの― Convolution2Dの 高速化を示しています 推測と訓練の改善については 以上です 次はサハーシュが MPSGraphの新しい― 演算についてお話しします ユリヤ ありがとう ではMPSGraphが サポートする― 新しい演算をご紹介します
我々は複数の種類の 畳み込みや削減から― すべての基本的な 数学的演算まで― 多数の演算を サポートしています 今年は MPSGraphでさらに 多くのことが行えるように― 特別な演算を追加しました 3つの新しいプリミティブを ご紹介しましょう 制御依存性 ステンシル演算子 ギャザー演算子です まずは制御依存性から 見てみましょう 制御依存性は グラフで明確に― 演算を 命令するのに必要です これを把握するために― グラフ演算を 正式に定義しましょう グラフの演算は 3種類のエッジを介して― お互いにつながります 入力テンソルは どのテンソルが― データ入力として 機能するかを示し― 出力テンソルは 演算が自ら作成し そして最後に 制御依存性という― 特別なエッジがあります 現行の演算が これに依存していなくても― 演算の前に 実行される必要があります また このAPIは― 演算が MPSGraphにより最適化され― 除去されるのを防ぐ 便利な方法も提供します これはバッチ正常化などの 機械学習レイヤを 実装する必要がありました 実際に見てみましょう バッチ正常化は― MLトレーニングで使用される 標準的なレイヤで― ネットワークをより安定にし より迅速に収束します これは訓練に使用された バッチ 正常化の計算グラフです 最初に 平均と偏差を算出します これらは推論に必要な 移動平均と移動偏差を― 更新するために 順番に使用されます しかしトレーニンググラフの 結果には― これらの変数が 必要でないため― MPSGraphが最適化し 除去する場合があります これは最終正常化の 演算子が― 制御依存性を使用する前に 明示的に命令を出して 解決できます このAPIを使用する方法を 示す― コードの簡単な例を 見てみましょう ここには指数演算子と 代入演算子があります 代入演算子はそれ以外では 使用されていません なので最適化され 削除されています これを解決するには TargetOperationとして― 明示的に 割り当てを設定します しかしこれには デベロッパーが― グラフ全体で依存関係を 追跡する必要があります 代わりに 新しい 制御依存性APIなら― 割り当てにより― 指数演算子を行えます これでtargetOperationの 必要性を削除でき― グラフが最適化し 削除するのを防ぎます 次はこれを コードで見てみましょう
まずは指数が依存する― 演算子を定義します 次に指数演算子を定義する― dependentBlockを 作成します 最後にこのグラフの run APIを呼び出します targetOperationsの 追跡は必要はありません 制御依存性については 以上です 次はステンシル演算子に ついてお話しします
ステンシル演算子は 画像畳み込みなど スライディングウィンドウ 演算子の汎化です これらの演算子は 有限要素法 機械学習 画像処理Appに 不可欠です この5ポイント 2D ステンシルは― 一般的にラプラシアン演算に 使用されます ここに表示されている ステンシル演算子は― この7ポイント 3D ステンシル図形のように― より高度な次元にも 適用できます 演算子を 詳細に見てみましょう ここに示されているように 各出力値は入力テンソルの― ステンシルウィンドウで 加重削減を計算します 演算子は argmin/argmax パディングモード リフレクション ClampToZeroを含む― さまざまな削減モードに 対応します MPSGraphは パフォーマンスの最良化に― スティッチングを 有効化します スティッチングのサポートで ステンシル演算子は 単一のカーネルを起動し 複雑な数学的演算子を― 表現するのを可能にします この例を 実際に見てみましょう 局所応答正規化は Pytorchの演算で― チャネルディメンションの 正常化に使用されます これは新しいステンシル 演算子を使用して― 簡単に実装できます これがこの正常化の 技術のグラフです ステンシル演算子の 周りの― 要素ごとの演算子だと いうことがわかります 新しい演算なしでは― 複数のディスパッチが 必要になります しかしスティッチングが サポートされているので 単一ディスパッチで グラフ全体を起動できます ステンシル演算子については 以上です 次はギャザー演算の― 改善についてです
今年 新しい ギャザー演算が― MPSGraphに追加されました これにより 不連続なメモリ位置に― 任意サイズのスライスを― 効率的に 複製できるようになります 概念的に メモリのかたまりにある 青で示された位置から 値を収集しています これらのギャザーレイヤは Embedding lookupや― 動的マトリックスの複製の 実装を可能にします GatherNDはギャザー演算の 強力な拡張子です 通常は 線型インデックスを サポートしますが― gatherND演算は n次元の インデックス化が可能です これによりn次元入力での どの部分でもシームレスに― データを複製できるように なります この演算の入力は ベクトルの座標で― それぞれの座標は― 入力テンソルの 階級によります 座標で指定されていない 次元は― スライスのコピーに つながります 例を使って 3D テンソルからの― 行スライスの集合の 手順を見てみましょう この例では インデックスは 2つの座標を指定し― マトリックスと 行座標に対応しています インデックスを列にする 3つ目の座標なしで― このgatherNDは 行全体をコピーします 結果のテンソルは 入力マトリックスから― 集められた 2D マトリックスです GatherNDは ほぼすべての ギャザー演算を表現し― すばらしいパフォーマンスを 提供します たとえば ギャザー演算を使用した embedding lookupの 実装方法をご紹介しましょう
Embedding lookupは 一般的な演算で― 提供された一連の 入力オブジェクトの― ベクトルの埋め込みに 使用されます 一般的にこのレイヤは 組み込みマトリックスが 生成され― 語彙の各単語に関連付け ベクトルを組み込む― 言語処理ネットワークで 使用されます 語彙の単語のIDは― インデックスとして ギャザー演算に使用でき 組み込みマトリックスは 入力テンソルになります 各単語IDに対応する行を― 得るには― ギャザーレイヤを使用し 簡単に行えます 座標を1つだけ指定し― それぞれの入力単語に対し すべての行がコピーされます 結果として 行に沿った それぞれの入力単語の― 組み込みベクトルの 2Dマトリックスになります 今年発表した 新しい― MPSGraphについては 以上です では次は コンパイルAPIについてです 今年 我々は 新しい― MPSGraphExecutable APIを 発表します このコンパイルAPIは― 2つの方法で パフォーマンスを改善します まずデベロッパーはグラフを いつコンパイルするか 管理できるようになります 次に据え置きの型推論で コンパイル呼び出し数を― 削減できるようになります それぞれの詳細を 見てみましょう 昨年 我々はMPSGraphを 定義し実行するための― 非常に便利なAPIを 提供しました 内部で評価が初めて リクエストされた時― MPSGraphは入力タイプに コンパイルを呼び出し― 内部で実行可能にしました その後のあらゆる実行にも― MPSGraphはこの 実行ファイルをキャッシュし コンパイルコストが 再び 支払われないようにします ユーザーは事前に― コンパイルを呼び出し― コンパイルのタイムラインを 選択できるようになりました MPSGraphExecutableで コンパイルされた― 実行ファイルを直接 run呼び出しできます これでいつグラフを コンパイルするか管理でき― 実行ファイルを キャッシュできるので― パフォーマンスが さらに向上します これをコードで 見てみましょう この簡単なグラフに 2つのテンソルを追加します コンパイルには 演算と共に フィードのタイプと― 目標のテンソルを入力します コンパイルされたグラフと 実行ファイルを取得します 評価メソッドも実に簡単です Metalコマンドキューと― 入力テンソルデータを 入力します これが MPS graphの コンパイルの基礎です 次は 据え置きの型推論を介した― コンパイル呼び出し数の 削減方法についてです 型推論は ユーザーが指定していない テンソルの形をMPSGraphが― 判断する必要のある コンパイルパスです このグラフでは― 2つの2D テンソルの 行列乗算を行います 入力テンソルの形が ここに示されています しかし 出力テンソルの 形はわかりません 型推論パスが完了すると― 入力と演算の種類に基づき― 出力テンソルが判断されます 標準のニューラル ネットワークでは― ネットワークへの入力は 必ずしも同じではありません 自然言語処理では 文や順序は― 長さが異なる場合があります CNNでは 異なるサイズの画像が― 評価されるために 入ってきます 今年のコンパイルの更新前― すべての 新しいサイズの画像に対し― グラフ全体で型推論を 行うため コンパイルが― 呼び出されていました 今 デベロッパーの皆さんが これを管理できるようになり 型推論をオフにしたまま― コンパイルを 呼び出すことができます これで各反復に対し コンパイル時間を― 数百秒節約でき 最高のパフォーマンスを 得ることができます
MPSGraphランタイムは ジャストインタイムで― エンコーディング中に推論し シームレスに実現します コンパイル時間を 節約するか― 最適なグラフを得るかの どちらかになります 先ほどお見せした コードの例で― これを見てみましょう
型推論パスを無効にするには このように― コンパイル記述子を 設定することで実現できます コンパイルAPIについては 以上です 最後にMPSGraphの 制御フローAPIについて― お話しします これらのAPIで グラフが以前に評価した― テンソルに基づき 動的に 演算をディスパッチできます これはバッチ正常化や 回帰型― ニューラルネットワークなど 通常のAppです では 新規APIを使用せず MPSGraphで― “whileループ”を実装する 方法を見てみましょう
まず述語を計算する― グラフを作成します 次に述語は 明示的なメモリ同期を通じて CPUで評価されます 述語が正確な場合 以前に作成されたグラフは― 新しい入力で実行されます 逆に述語が不正確な場合 ループは終了し 2つ目の MPSGraphが作成され― 結果を消費するために 実行されます 新しい制御フローAPIなら これらの手順は 単一の― MPSGraph実行の一部として 起動させることができます
これで 実装がより便利になります 明示的メモリ同期 プリミティブを― 導入する必要が なくなるからです ではこれがいかに― 効率的になる可能性があるか 見てみましょう こちらは新しいAPIのない― 制御フロータイムラインです CPUに最初のカーネルを 暗号化しました カーネルが完了したら― 結果を読むために メモリの同期が必要です これはCPUがGPUの実行の 完了を待つ必要があるため― 非効率的になる 可能性があります 同様に GPUも― CPUの同期と 後続のエンコーディングが― 完了するのを 待つ必要があります これが各反復で起こります では新しいMPSGraph APIを 使用する際の― メリットをご説明します CPUエンコードの呼び出しは 一度で済みます 述語はGPUタイムラインで 評価されるので― 同期のオーバーヘッドは 発生しません カーネルはバブルなしで 起動します
では新しいAPIを 見てみましょう
新しい制御フローAPIが 3つ追加されました forループとwhileループに if/elseが追加されました if/elseの 述語から始めましょう これには皆さん 精通されていますね 述語に基づき― 異なるコードパスが 実行されます Boolean述語と― コードブロックを“if”と “else”に提供しました この述語が正確なら― Thenブロックの コードを実行します 逆に不正確の場合は― else分岐が実行されます if/else演算は― ニューラルネットワークに 非常に便利です 正規の使用法の1つは batchNormalization演算で 訓練と推論で 異なる動作を行います isTrainingブーリアンなら 単一のグラフで― 正規化群で両方の変数を 表すことができます コードでif/elseブランチを 設定してみましょう
2つの入力 スカラーテンソルの― 簡単な例を見てみましょう 1つ目のテンソルが 2つ目よりも小さい場合 演算の合計を返します さもなければ差を返します まず述語を計算し― APIにパスします 次に述語が正確な場合 ブロックを計算し テンソルに追加します 最後に 述語が不正確な場合は― elseブロックを計算し テンソルを減算します 次は forループの 実装方法をお見せしましょう
forループ述語は 一連の演算を― 固定回数ルーピングします これは訓練中に 異なる長さの配列を ループする必要のある 反復的な― ニューラルネットワークでは 一般的です forループには数々の numberOfIterationsが― 必要です インデックスは0に 初期化され― 各ループの反復で numberOfIterationsと― 比較されます numberOfIterationsよりも 少ない場合は― forループのbodyを実行し― インデックスを1に インクリメントします
インデックスが numberOfIterationsと― 同等か 上回る場合は― ループを終了します これをコードで 実装してみましょう
ごく簡単な例を 実装するとしましょう 結果因子を ある入力値に 初期化します 次にルーピングを4回行い それぞれで別の入力値を使い 結果を増やします 最初にグラフテンソルを 2つ作成します 出力テンソルはinput0に 初期化されます 各反復で― このテンソルはinput1で 掛けられます 次にnumberOfIterationsを 4に設定し― インデックス0から3まで ルーピングを4回実行します 次にforループの bodyを作成します これは単一の反復を表す― 閉包で終了します 各反復は現行の反復の インデックスと― 前回の反復の出力を パスします 次に結果を更新して 次の反復に― パスするために返します 最後に これらすべての引数を― グラフのforループAPIに パスします iterationArgumentsの bodyは― input0テンソルに 初期化されます forループについては 以上です 次は whileループAPIを 見てみましょう
このプリミティブは 条件が適合する間 一連の演算を実行します このAPIを使用するには 2つのブロックの― コードが必要になります 最初のブロックでは― 条件は述語を使って 確認されます 述語が正確な場合は 後のブロックの― whileループのbodyが 実行されます これにより述語が 再計算されます するとMPSGraphは 前のブロックの― 次の反復で この述語を使用します 条件が不正確と 判断された場合は― ループから退出します APIはbodyと 条件評価コードブロックを 交換することで― do-whileループの 実装も可能にします 非常に簡単な例を 実装するとしましょう 結果因子を 入力値に初期化します 次にしきい値を超えるまで 各ループで― 乗数を使い結果を乗算します まず 前回の反復の結果を 使用して― 述語を評価する 一連のコードを定義します また これにより 前回の反復の結果が― returnTensors NSArrayに 保管されます この配列は入力として― 述語が正確な場合に 次の反復で使用され― 述語が不正確な場合は― 最終結果として使用されます 次に テンソルが乗算される whileループの bodyを定義します プロダクトは条件ブロックが 読み込むために返されます
最後に ここに示されているように これらすべての引数を whileループにパスします initialInputs引数は 前回のブロックの― 最初の反復で使用されます
whileループについては 以上です では実際に これを適用してみましょう 画像合成は一般的な 画像編集ユーティリティです オブジェクトが目標の 画像に埋め込まれています ご覧のようにソース画像と― バックグラウンド画像で 始めます 次にソース画像の マスクを作成します このソース画像のマスクを― バックグラウンドに直接 配置します 見た目がよくありません ソース画像のエッジが 見えています 画像合成を使用して― これらの端を滑らかにします Laplacianエッジフィルタと 反復線型ソルバーのペアで― これを達成するのが 一般的です 詳細を見てみましょう ここにMPSGraphで 画像合成を行うのに必要な― パイプラインがあります 入力テンソル バックグラウンド画像 ソース画像 マスク オブジェクトで始めます 次に反復線型ソルバーと― Laplacianエッジ ディテクターを使います この一連の演算の出力は― エッジが滑らかな 合成画像です Laplacianエッジフィルタを 見てみましょう Laplacian エッジフィルタの実装には― 一連のweightを使い ソース画像の― ウインドウ表示を削減します ここに示されているように この実装には ステンシル 演算子が使用されています この演算子を 使用することで― ソース画像のエッジを 確認できます ここで計算されるエッジは― 線型ソルバーの入力として 使用されます では線型ソルバーを 見てみましょう
バックグラウンド画像から 始め― 線型ソルバーに フィードします ソルバーは この画像を更新し― 結果がリードバックされます ご覧のとおり これは反復的なプロセスです 反復が進行すると― 解法画像はエッジが完璧に― 一体化するまで 改善を続けます ループはエラーが ユーザーの定義した 許容範囲を 下回ると終了します これにはwhileループが 必要です MPSGraph制御フローAPIを 使い― これを実装できるように なりました ではデモを見てみましょう 我々はMPSGraphをiPad Pro Appとして使い 画像合成ユーティリティを 実装しました
ソース画像は上部 ターゲット画像が 下部にあります オブジェクトを ソースからターゲットに― クローニングします 最初に 移動させたい牛の周りに― マスクを描く必要があります
ナイーブクローンでは どうなるでしょう
エッジが粗く 見た目がよくありません では先ほど説明した 画像合成技術を― 試してみましょう まず バックグラウンド画像に― 初期解を設定します これを約50回反復します
明らかに解法画像は まだまとまっていません あともう50回 反復してみましょう
エッジが滑らかになり かなり自然になりました プログラミングが簡単な MPSGraphなら― さまざまな技術を簡単に― 試すことができます バックグラウンド画像の 代わりに― クローン画像でソルバーを 初期化することで― より迅速に収束が行えます この初期化モードを 有効化するには― このトグルをオンにします もう一度 反復数を50回に設定し― ナイーブクローンを 再設定しましょう
ソルバーをもう一度 実行します 50回の反復後― 解法画像は改善されています ソース画像で 始めているため― エッジの混色も少なめです すばらしいことですが― 我々が求めているのは エラーの許容範囲に基づき― 収束を自動化することです これには whileループが必要で― このスイッチで 有効にすることができます これを新しいMPSGraph APIで 実装しました エラーの許容範囲は この スライダーで調整できます 画面では0.1,に 設定されています これをナイーブクローンに 戻しましょう ソルバーを開始します このwhileループで 私が回数を指定することなく 約80回の反復で― 解法画像を収束しました では このバックグラウンドに― 他の動物を クローニングしてみましょう この可愛い子犬で 試してみます
トレーシングが完了しました この画像の右下に― 配置してみましょう
次は鳥で試してみましょう
バックグラウンドの 右上に配置します かなり素敵な 画像になりました デモは以上です
要約すると MPSGraphの導入は― CoreMLとTensorFlowの パフォーマンスの― 改善につながることが わかりました 推論は 2倍の速さになりました 広範囲のAppを 有効にする ステンシル演算子を含む 新しい計算プリミティブを― ご紹介しました
MPSGraphが提供する 新しいコンパイルの― 柔軟性をご紹介しました これは推論ネットワークの レイテンシを削減します
そして最後にMPSGraphの― 新しい制御フロー機能を ご紹介しました このAPIは 機械学習ネットワークに加え いくつかの線型代数学 Appの― 鍵となります
皆さんに これらの機能を― ご活用いただくことを 楽しみにしています ありがとうございます WWDC 2021をお楽しみ下さい [アップビードな音楽]
-
-
8:35 - Control dependencies 1
// Execute the graph let results = graph.run(feeds: [inputTensor: inputs], targetTensors: [exp], targetOperations: [assign])
-
9:01 - Control dependencies 2
// Create control dependency let exp = graph.controlDependency(with: [assign], dependentBlock: { return [graph.exponent(with: input, name: nil)] }, name: nil) // Execute the graph let results = graph.run(feeds: [inputTensor: inputs], targetTensors: [exp], targetOperations: nil)
-
14:42 - Evaluation method
// Create the graph let placeholder0 = graph.placeholder(shape: [1, 3], dataType: .float32, name: nil) let placeholder1 = graph.placeholder(shape: [2, 1], dataType: .float32, name: nil) let addTensor = graph.addition(placeholder0, placeholder1, name: nil) // Compile the graph into an executable let executable = graph.compile(with: nil, feeds: [placeholder0: MPSGraphShapedType(shape: [1, 3], dataType: .float32), placeholder1: MPSGraphShapedType(shape: [2, 1], dataType: .float32)], targetTensors: [addTensor], targetOperations: nil, compilationDescriptor: nil) // Execute the graph into an executable let fetch = executable.run(with: commandQueue, inputs: [MPSGraphTensorData(input0), MPSGraphTensorData(input1)], results: nil, executionDescriptor: nil)
-
16:38 - Disabling the type inference pass
// Create the graph compilation descriptor let descriptor = MPSGraphCompilationDescriptor() // Disable type inference descriptor.disableTypeInference() // Compile the graph into an executable let executable = graph.compile(with: nil, feeds: /* feeds */, targetTensors: /* target tensors */, targetOperations: nil, compilationDescriptor: descriptor) // execute the graph
-
19:22 - If/else in batch normalization
// Different behavior during inference and training let results = graph.if(isTraining, then: { ... }, // compute mean and variance else: { ... }, // use running_mean and running_variance name: nil)
-
19:46 - If/else
let predicate = graph.lessThan(a, b, name: nil) let results = graph.if(predicate, then: {[ graph.addition(a, b, name: nil) ]}, else: {[ graph.subtraction(a, b, name: nil) ]}, name: nil)
-
20:58 - For loop 1
var result = input0 for i in 0..<4 { result *= input1 }
-
21:12 - For Loop 2
// Initialize inputs let input0 = graph.placeholder(shape: [], dataType: .int32, name: nil) let input1 = graph.placeholder(shape: [], dataType: .int32, name: nil) let numberOfIterations = graph.constant(4, shape: [], dataType: .int32)
-
21:33 - For Loop 3
// Define Body let body = { (index: MPSGraphTensor, iterationArguments: [MPSGraphTensor]) -> [MPSGraphTensor] in let iterationResult = graph.multiplication(iterationArguments[0], input1, name: nil) return [iterationResult] }
-
21:52 - For Loop 4
// Create for loop operation let result = graph.for(numberOfIterations: numberOfIterations, initialIterationArguments: [input0], body: body)
-
22:51 - While loop 1
var result = initialValue while result < threshold { result *= multiplier }
-
23:01 - While loop 2
// Evaluate condition let condition = { (inputs: [MPSGraphTensor], returnTensors: NSMutableArray) -> MPSGraphTensor in let predicate = graph.lessThan(inputs[0], threshold, name: nil) returnTensors.add(inputs[0]) return predicate }
-
23:22 - While loop 3
// Define body let body = { (inputs: [MPSGraphTensor]) -> [MPSGraphTensor] in let iterationResult = graph.multiplication(inputs[0], multiplier, name: nil) return [iterationResult] }
-
23:33 - While loop 4
// Create while loop operation let results = graph.while(initialInputs: [initialValue], before: condition, after: body, name: nil)
-
25:00 - Edge filter
// Apply the laplacian edge filter on the source image let edges = graph.stencil(with: source, weights: laplacianWeights, descriptor: desc, name: nil)
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。