View in English

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

クイックリンク

5 クイックリンク

ビデオ

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

その他のビデオ

ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。

  • 概要
  • トランスクリプト
  • コード
  • CPUでリアルタイムのML推論をサポート

    BNNSGraphを使用して、CPUでの機械学習モデルの実行を高速化する方法を解説します。BNNSGraphを使用してCPUで機械学習モデルをコンパイルし、実行する方法を示すとともに、実行時のメモリ割り当てが不要であることや、音声または信号の処理モデルをシングルスレッドで実行できることなど、BNNSGraphが提供するリアルタイムの保証についてもご紹介します。

    関連する章

    • 0:00 - Introduction
    • 1:18 - Introducing BNNS Graph
    • 6:47 - Real-time processing
    • 8:00 - Adopting BNNS Graph
    • 14:52 - BNNS Graph in Swift

    リソース

    • Forum: Machine Learning and AI
      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC24

    • Appleプラットフォームでの機械学習の詳細
  • ダウンロード

    こんにちは AppleのVector & Numerics Groupの Simon Gladmanです 今日は 機械学習ライブラリである Basic Neural Network Subroutines(BNNS)の 素晴らしい新機能について説明します

    ここ数年 BNNSはCPUにおける機械学習の 推論とトレーニングのための 包括的なAPIを提供してきました

    現在Appleでは BNNSをより高速化し エネルギー効率を高め 操作しやすさを格段に向上させています このセッションでは CPUベースの機械学習用の 新たな優れたAPIである BNNS Graphをご紹介します

    まず新しいAPIを紹介し 機械学習とAIモデルを最適化する方法を いくつか説明します 次に BNNS Graphが リアルタイムのユースケースの要求に 応えるための重要な機能を見ていきます そして後ほど アプリでBNNS Graphを採用するために 必要な手順について説明します 最後に BNNS Graphを Swiftで実装する方法に加え SwiftUI/Swift Chartsと連携させる 方法もご紹介します では ぜひお気に入りの椅子に座って お茶でも飲みながら BNNS Graphについて見ていきましょう

    まず始める前に BNNSが Appleの機械学習フレームワークの 全体的なスタックに どのように適合するかを説明します BNNSは Accelerateフレームワークの ライブラリの1つで これを使用することで モデルをアプリに統合できます

    BNNSはCPUでの機械学習を加速させ Appleの機械学習フレームワークである Core MLで使用されています

    CPUベースの機械学習のための 新しいAPIであるBNNS Graphは BNNSライブラリが 個々の機械学習プリミティブでなく グラフ全体を使用できるようにします

    トレーニングはAppleプラットフォームに モデルを導入するための最初のステップです モデルのトレーニングが完了したら デバイスに導入するためのモデルの準備 つまり最適化と変換を行う必要があります モデルの準備ができたら アプリケーションに統合する準備が整います このセッションでは ワークフローの統合部分に焦点を当てます

    BNNS Graphを理解するために まず従来のBNNS APIを見てみましょう

    これまで BNNSはレイヤーに重点を置いた 一連のAPIを提示し 個々のパフォーマンスプリミティブを 提供してきました これは機械学習に使用される構成要素です 畳み込みのような それぞれの演算では通常 多くの詳細情報を構成する必要があります

    n次元配列記述子を使って レイヤーへの引数と そのプロパティを指定します つまり 入力の記述子 出力の記述子 そして 畳み込みカーネルの記述子または 重み行列を作成します そしてお察しのとおり BNNSは畳み込みバイアスを もう1つの配列記述子として 想定していました

    次に これらの配列記述子を使用して パラメータ構造を作成し そのパラメータ構造を レイヤー自体を作成する関数に渡します 最後に 推論の際にレイヤーを適用します

    BNNSを使用して 既存のモデルを実装する場合は 各レイヤーを BNNSプリミティブとしてコーディングし すべての中間テンソルのコードを 記述する必要があります

    Appleではここ数年 新しいAPIである BNNS Graphの開発に取り組んできました BNNS Graphは 複数のレイヤーと それらのレイヤー間の データフローで構成される グラフ全体を取得し それを単一のオブジェクトとして使用します それがグラフオブジェクトです つまり レイヤーごとに コードを記述する必要はありません さらに 皆さんもユーザーも より高速なパフォーマンスと 優れたエネルギー効率の恩恵を受けられます では BNNS Graphを アプリに統合するための ワークフローの簡単な概要を見てみましょう

    Core MLモデルパッケージ つまりmlpackageファイルから始めます mlpackageの作成方法の詳細については 「Deploy machine learning and AI models on-device withCoreML」 セッションをご覧ください

    Xcodeは 自動的にパッケージを mlmodelcファイルにコンパイルします そのあと mlmodelcファイルから グラフを構築するコードを記述します 最後に グラフをラップする コンテキストを作成します 推論を実行するのはそのコンテキストです BNNS Graphは モデル全体を認識しているため 以前は不可能だった多くの最適化を 実行することができます しかもこれらの最適化は 無料で利用できます

    これはモデルの小さなセクションの例です このセクションの最初のレイヤーは テンソルAとBの要素ごとの加算を実行し 結果をCに書き込みます 次のレイヤーは畳み込みを実行します そのあと モデルは畳み込み結果に 活性化関数を適用します 最後に スライスレイヤーは 要素のサブセットを テンソルDに書き込みます

    BNNS Graphの最適化には 数学的変換が含まれます この例では スライス操作が最後のレイヤーです つまり前述のすべての操作は スライスだけでなく テンソル全体に作用します

    数学的変換の最適化により スライスがモデルの先頭に移動されるため BNNSで計算する必要があるのは そのスライス内の要素のサブセットのみです

    レイヤー融合による最適化では いくつかのレイヤーを 1つの操作に結合します この例では BNNSが畳み込みレイヤーと 活性化レイヤーを融合させています もう1つの最適化はコピー省略です スライス操作により スライス内のデータを 新しいテンソルにコピーできます

    BNNS Graphはスライスを最適化し 元のデータにウインドウを渡します

    可能な場合は テンソルが メモリを共有するようにすることで BNNS Graphは メモリ使用量を最適化し 不要な割り当てを排除することもできます この例では テンソルAとCは 同じメモリを共有することができ テンソルBとDも同じメモリを共有できます

    BNNS Graphの 重み再パッキング最適化では 例えば 行優先レイアウトからの重みを ブロックされた反復順序に再パッキングして キャッシュの局所性を 向上させることができます

    こうした最適化のメリットを得るために コードを記述する必要はありません ただ「それだけ」で実行されます また パフォーマンスは 以前のBNNSプリミティブよりも 平均して2倍以上高速になります

    そのため新しいAPIは リアルタイムのユースケースに最適です ここでは そのようなユースケースを見ていきます BNNS GraphをAudio Unitに追加して オーディオを操作するというものです

    Audio Unitを使用すると iOSやmacOSアプリで オーディオやMIDIデータを 作成・変更できます これにはLogic ProやGarageBandなどの 音楽制作アプリが含まれます 機械学習を使用したAudio Unitは さまざまな機能を提供できます たとえば音声を分離して ボーカルを分離または削除したり コンテンツに基づいて 音声をさまざまな領域に分割したり 音色変換を適用して 楽器を別の楽器のように 聞こえるようにしたりなどです

    このデモでは 内容をシンプルにし オーディオを「ビットクラッシュ」すなわち 量子化して歪んだ効果を与える Audio Unitを作成します

    リアルタイム処理の主な要件は 実行フェーズ中のメモリ割り当てや マルチスレッドを回避することです それが起こると カーネルコードへの コンテキストスイッチが発生し リアルタイムの期限に 間に合わなくなる可能性があります BNNS Graphを使用すると モデルのコンパイルと実行を 細かく制御することができ メモリ割り当てなどのタスクのほか 実行をシングルスレッドと マルチスレッドのどちらで行うかも 管理できます

    では次に BNNS Graphを採用した Audio Unitプロジェクトの 作成方法を説明します

    Xcodeでは Audio Unitの作成が 非常に簡単です Audio Unit Extension Appを作成する テンプレートが用意されているからです

    まずbitcrusher mlpackageファイルを プロジェクトナビゲータに ドラッグアンドドロップします

    Xcodeはmlpackageを mlmodelcファイルにコンパイルします このファイルを使用して BNNS Graphをインスタンス化します これで最初の2つのステップが完了しました

    これで Xcode内でmlmodelcファイルを 使用できるようになったので BNNS Graphオブジェクトを作成し 変更可能なコンテキストにラップする 準備ができました グラフを作成するのは1回のみなので 通常 これをバックグラウンドスレッドで 実行するのは アプリの起動後か ユーザーが機械学習に依存する機能を 初めて使用したときです

    グラフのコンパイルでは コンパイルされたCore MLモデルを処理して 最適化された BNNS Graphオブジェクトにします このオブジェクトには 推論で呼び出されるカーネルのリストと 中間テンソルの メモリレイアウトマップが含まれています

    Xcodeテンプレートは ビジネスロジックとユーザーインターフェイスに SwiftとSwiftUIを リアルタイム処理にC++を使用します

    C++ DSPカーネルヘッダファイルでは このプロジェクトの すべての信号処理が行われます このファイルに BNNS Graphコードを追加します

    そのために まずmlmodelcのパスを取得し BNNS Graphをビルドして コンテキストを作成し 引数の型を設定して ワークスペースを作成します ではコードの記述方法を見てみましょう

    これはmlmodelcファイルへのパスを 取得するコードです 先に説明したように mlpackageファイルだけを プロジェクトにコピーした結果 Xcodeによって パッケージから mlmodelcファイルが生成されています

    実行中にグラフが1つのスレッドだけを 使用するように指定するには デフォルト設定で コンパイルオプション構造を作成します デフォルトの動作では BNNS Graphがマルチスレッドで実行されます そこで SetTargetSingleThread関数を 呼び出して それを変更します

    次にコンパイルオプションと mlmodelcファイルへのパスを使用して グラフをコンパイルします GraphCompileFromFile関数で グラフが作成されます ここでは2番目の引数としてNULLを渡し ソースモデル内のすべての関数が コンパイルされるように指定しています

    コンパイルが完了したら コンパイルオプションの割り当てを 安全に解除できます

    これでステップ3が完了し グラフが作成されました これで不変のグラフができたので ContextMake関数によって グラフが可変のコンテキストでラップされます BNNS Graphでは 動的な形状やその他の 特定の実行オプションをサポートするために 可変のコンテキストが必要です コンテキストでは コールバック関数を設定して 出力とワークスペースメモリを 自分で管理することもできます

    BNNS Graphは テンソル構造を処理して 形状 ストライド そしてランクを指定し 基になるデータを ポイントすることもできれば 基になるデータへのポインタを 直接処理することもできます

    このデモでは オーディオバッファを直接処理するので コンテキストの引数はポインタになるように 指定します

    BNNSがオーディオデータを 処理している間は メモリを割り当てないようにする 必要があります そのためこの初期化中に ページ境界に揃えたワークスペースを 作成します

    コンテキストを更新して 処理するデータの最大サイズが 認識されるようにする必要があります そのためには Audio Unitがレンダリングできる 最大フレームに基づく形状を SetDynamicShapes関数に渡します

    次に GetWorkspaceSize関数が ワークスペースに割り当てる必要のある メモリの量を返します

    ワークスペースメモリは ページ境界に揃っている必要があるので aligned_allocを呼び出して ワークスペースを作成します

    ここで注意すべきなのは 元のPythonコードの引数の順序が mlmodelcファイルの引数の順序と 同じではない可能性があることです GraphGetArgumentPosition関数は それぞれの引数の正しい位置を返します この位置は後で実行関数に渡されます

    これでコンテキストが適切に構成されました

    次に進む前に 他のオプションについても 簡単に触れておきます コンパイルオプションを処理しているときに 最適化の環境設定を行う機会がありました BNNSはデフォルトで グラフのパフォーマンスを最適化します これはAudio Unitに最適です

    パフォーマンスが最適化されるということは BNNS Graphオブジェクトの フットプリントが増加する場合でも 追加作業はコンパイルフェーズに 移動される可能性があります

    ただし アプリのフットプリントが重要な場合は サイズを最適化することができます サイズを最適化すると データは 可能な限り小さい形式で残されますが 変換を実行するためのコストが原因で 実行パフォーマンスが 低下する可能性があります

    もう1つ便利なのは BNNS Graphには NaNAndInfinityChecksを 有効にする関数が含まれていることです このデバッグ設定は 16ビットの アキュムレータがオーバーフローしたときに テンソル内の無限大などの問題を 検出するのに役立ちます ただし このチェックを製品コードで 有効にすることは望ましくありません

    これで グラフとコンテキストを初期化し シングルスレッド実行を指定して ワークスペースを作成しましたので BNNSで割り当ては実行されません これでグラフを実行する準備ができました では その実行に必要なコードを 見てみましょう

    SetBatchSize関数は 入力信号形状と出力信号形状の 最初の次元のサイズを フレーム内のオーディオサンプルの数に 設定します この場合 2番目の引数は ソースファイル内の関数名を参照します ただしソースファイルには 関数が1つしか含まれていないため NULLを渡すことができます

    そして5つの引数 出力信号と入力信号 そして量子化の量を定義するスカラ値を 配列として実行関数に渡します 追加する最初の引数は出力信号です data_ptrフィールドと data_ptr_sizeフィールドを 現在のオーディオチャネルの outputBufferに基づいて指定します

    次の引数は入力信号です ここではdata_ptrフィールドと data_ptr_sizeフィールドを指定しますが これは現在のオーディオチャネルの inputBufferに基づきます

    次の引数は3つのスカラ値で ユーザーインターフェイスのスライダから 取得されるものです

    これで関数を実行できます GraphContextExecute関数は コンテキスト 引数 そしてもちろん重要なワークスペースを 受け付けます 戻り値として 出力ポインタには推論の結果が含まれます SetBatchSize関数と同様に 2番目の引数は ソースファイル内の関数名を参照します ソースファイルには関数が1つしか 含まれていないため NULLを渡します

    最後に BNNS GraphをSwiftプロジェクトに 統合する方法を見てみましょう

    Swiftの使用に最適なユースケースの1つは BNNS GraphをAudio Unitの SwiftUIコンポーネントに 実装することです それにより Audio Unitの ユーザーインターフェイスに オーディオ信号自体と同じ パラメータを使用して 同じモデルで処理された正弦波を 表示することができます Audio Unitの ユーザーインターフェイスコンポーネントは Swift UIを使用して sampleCount要素を含むデータに ビットクラッシャーモデルを適用し 滑らかな正弦波を表示します

    srcChartDataバッファには 正弦波表現が格納され dstChartDataバッファには BNNS Graphが効果を適用した後の 正弦波データが格納されます

    これら3つのバッファには ユーザーがユーザーインターフェイスの スライダで制御するスカラ値が格納されます

    APIは CとSwiftで一貫しているので 先ほど説明した オーディオ処理コードと同様に グラフとコンテキストを定義しましょう

    Swiftではリアルタイムの安全性は 保証されませんが C++のようにワークスペースを提供することで BNNS Graphが実行中に メモリ割り当てを行う必要がなくなります

    そのためこれはAudio Unitの パフォーマンスと エネルギー効率の向上に役立ちます

    次に引数インデックス変数を宣言し 引数配列内で引数がどこにあるかを 定義します

    ここに表示されているのは 波形表示コンポーネントの初期化メソッドに 含まれるコードです ここで グラフ コンテキスト ワークスペースを作成します

    最初のステップは Xcodeがmlpackageからコンパイルした mlmodelcファイルへのパスを 取得することです

    次に mlmodelcを BNNS Graphオブジェクトにコンパイルします

    そのあと C++コードで行ったのと同じように グラフコンテキストを作成します

    ユーザーインターフェイスと オーディオ処理の両方に 同じコンテキストを使用しないのはなぜかと 疑問に思うかもしれません それはコンテキストが 一度に1つのスレッドしか 実行できないからです Audio Unitがデータを処理している間に ユーザーがスライダの1つを 調整する可能性もあるため プロジェクトの各部分に 別々のコンテキストが必要です

    ここで簡単なチェックを行い BNNSがグラフとコンテキストを 正常に作成したことを確認します

    オーディオ処理のコードで行ったように ソースと宛先のチャートデータへのポインタを 直接処理することにします そのためコンテキストに 引数がテンソルではなく ポインタであることを伝えます

    この場合 バッチサイズ つまりソースと宛先の信号データバッファの 最初の次元のサイズは 例に挙げた正弦波のサンプル数です

    SetBatchSize関数が返されたあと GetWorkspaceSize関数は サンプル数の正しいサイズを返します

    次に 引数配列のインデックスを計算します ユーザーがスライダの値を変更するたびに SwiftはupdateChartData() 関数を呼び出し 正弦波に ビットクラッシャー効果を適用します

    updateChartData()関数の 最初のステップは スカラ値を 対応するストレージに コピーすることです

    次にインデックスを使用して 引数配列を正しい順序で作成します

    これで サンプルの正弦波に対して ビットクラッシャーを実行できます 実行関数が返されると SwiftUIは ユーザーインターフェイスのチャートを更新し ビットクラッシャーされた 正弦波を表示します

    ここでXcodeに戻ります 波形を表示するSwiftチャートは すでに追加してあるので 引数を格納するバッファを宣言します

    グラフ コンテキスト そして引数のインデックスも宣言します

    イニシャライザ内で グラフとコンテキストを初期化し

    ワークスペースを作成して 引数のインデックスを計算します 次にupdateChartData()関数で インデックスを使用して引数関数を作成し 正しい順序を確認してから

    グラフを実行します

    Xcodeの実行ボタンを押して アプリを起動し 動作しているビットクラッシャーを 聞いてみましょう

    ありがとうございました では今日の内容をまとめたいと思います BNNS Graphが提供する APIを使用すると 高パフォーマンスで エネルギー効率が高く リアルタイムでレイテンシの影響を受けやすい 機械学習をCPUで実現できます これはオーディオアプリに最適です 改めて ご視聴ありがとうございました

    • 0:01 - Create the graph

      // Get the path to the mlmodelc.
              NSBundle *main = [NSBundle mainBundle];
              NSString *mlmodelc_path = [main pathForResource:@"bitcrusher"
                                                       ofType:@"mlmodelc"];
              
              // Specify single-threaded execution.
              bnns_graph_compile_options_t options = BNNSGraphCompileOptionsMakeDefault();
              BNNSGraphCompileOptionsSetTargetSingleThread(options, true);
              
              // Compile the BNNSGraph.
              bnns_graph_t graph = BNNSGraphCompileFromFile(mlmodelc_path.UTF8String,
                                                            NULL, options);
              assert(graph.data);
              BNNSGraphCompileOptionsDestroy(options);
    • 0:02 - Create context and workspace

      // Create the context.
              context = BNNSGraphContextMake(graph);
              assert(context.data);
              
              // Set the argument type.
              BNNSGraphContextSetArgumentType(context, BNNSGraphArgumentTypePointer);
              
              // Specify the dynamic shape.
              uint64_t shape[] = {mMaxFramesToRender, 1, 1};
              bnns_graph_shape_t shapes[] = {
                  (bnns_graph_shape_t) {.rank = 3, .shape = shape},
                  (bnns_graph_shape_t) {.rank = 3, .shape = shape}
              };
              BNNSGraphContextSetDynamicShapes(context, NULL, 2, shapes);
              
              // Create the workspace.
              workspace_size = BNNSGraphContextGetWorkspaceSize(context, NULL) + NSPageSize();
              workspace = (char *)aligned_alloc(NSPageSize(), workspace_size);
    • 0:03 - Calculate indices

      // Calculate indices into the arguments array.
              dst_index = BNNSGraphGetArgumentPosition(graph, NULL, "dst");
              src_index = BNNSGraphGetArgumentPosition(graph, NULL, "src");
              resolution_index = BNNSGraphGetArgumentPosition(graph, NULL, "resolution");
              saturationGain_index = BNNSGraphGetArgumentPosition(graph, NULL, "saturationGain");
              dryWet_index = BNNSGraphGetArgumentPosition(graph, NULL, "dryWet");
    • 0:04 - Execute graph

      // Set the size of the first dimension.
                  BNNSGraphContextSetBatchSize(context, NULL, frameCount);
                  
                  // Specify the direct pointer to the output buffer.
                  arguments[dst_index] = {
                      .data_ptr = outputBuffers[channel],
                      .data_ptr_size = frameCount * sizeof(outputBuffers[channel][0])
                  };
                  
                  // Specify the direct pointer to the input buffer.
                  arguments[src_index] = {
                      .data_ptr = (float *)inputBuffers[channel],
                      .data_ptr_size = frameCount * sizeof(inputBuffers[channel][0])
                  };
                  
                  // Specify the direct pointer to the resolution scalar parameter.
                  arguments[resolution_index] = {
                      .data_ptr = &mResolution,
                      .data_ptr_size = sizeof(float)
                  };
                  
                  // Specify the direct pointer to the saturation gain scalar parameter.
                  arguments[saturationGain_index] = {
                      .data_ptr = &mSaturationGain,
                      .data_ptr_size = sizeof(float)
                  };
                  
                  // Specify the direct pointer to the mix scalar parameter.
                  arguments[dryWet_index] = {
                      .data_ptr = &mMix,
                      .data_ptr_size = sizeof(float)
                  };
                  
                  // Execute the function.
                  BNNSGraphContextExecute(context, NULL,
                                          5, arguments,
                                          workspace_size, workspace);
    • 0:05 - Declare buffers

      // Create source buffer that represents a pure sine wave.
          let srcChartData: UnsafeMutableBufferPointer<Float> = {
              let buffer = UnsafeMutableBufferPointer<Float>.allocate(capacity: sampleCount)
              
              for i in 0 ..< sampleCount {
                  buffer[i] = sin(Float(i) / ( Float(sampleCount) / .pi) * 4)
              }
              
              return buffer
          }()
          
          // Create destination buffer.
          let dstChartData = UnsafeMutableBufferPointer<Float>.allocate(capacity: sampleCount)
          
          // Create scalar parameter buffer for resolution.
          let resolutionValue = UnsafeMutableBufferPointer<Float>.allocate(capacity: 1)
          
          // Create scalar parameter buffer for resolution.
          let saturationGainValue = UnsafeMutableBufferPointer<Float>.allocate(capacity: 1)
          
          // Create scalar parameter buffer for resolution.
          let mixValue = UnsafeMutableBufferPointer<Float>.allocate(capacity: 1)
    • 0:06 - Declare indices

      // Declare BNNSGraph objects.
          let graph: bnns_graph_t
          let context: bnns_graph_context_t
          
          // Declare workspace.
          let workspace: UnsafeMutableRawBufferPointer
          
          // Create the indices into the arguments array.
          let dstIndex: Int
          let srcIndex: Int
          let resolutionIndex: Int
          let saturationGainIndex: Int
          let dryWetIndex: Int
    • 0:07 - Create graph and context

      // Get the path to the mlmodelc.
              guard let fileName = Bundle.main.url(
                  forResource: "bitcrusher",
                  withExtension: "mlmodelc")?.path() else {
                  fatalError("Unable to load model.")
              }
              
              // Compile the BNNSGraph.
              graph = BNNSGraphCompileFromFile(fileName, nil,
                                               BNNSGraphCompileOptionsMakeDefault())
              
              // Create the context.
              context = BNNSGraphContextMake(graph)
              
              // Verify graph and context.
              guard graph.data != nil && context.data != nil else { fatalError()}
    • 0:08 - Finish initialization

      // Set the argument type.
              BNNSGraphContextSetArgumentType(context, BNNSGraphArgumentTypePointer)
              
              // Set the size of the first dimension.
              BNNSGraphContextSetBatchSize(context, nil, UInt64(sampleCount))
              
              // Create the workspace.
              workspace = .allocate(byteCount: BNNSGraphContextGetWorkspaceSize(context, nil),
                                    alignment: NSPageSize())
              
              // Calculate indices into the arguments array.
              dstIndex = BNNSGraphGetArgumentPosition(graph, nil, "dst")
              srcIndex = BNNSGraphGetArgumentPosition(graph, nil, "src")
              resolutionIndex = BNNSGraphGetArgumentPosition(graph, nil, "resolution")
              saturationGainIndex = BNNSGraphGetArgumentPosition(graph, nil, "saturationGain")
              dryWetIndex = BNNSGraphGetArgumentPosition(graph, nil, "dryWet")
    • 0:09 - Create arguments array

      // Copy slider values to scalar parameter buffers.
              resolutionValue.initialize(repeating: resolution.value)
              saturationGainValue.initialize(repeating: saturationGain.value)
              mixValue.initialize(repeating: mix.value)
              
              // Specify output and input arguments.
              var arguments = [(dstChartData, dstIndex),
                               (srcChartData, srcIndex),
                               (resolutionValue, resolutionIndex),
                               (saturationGainValue, saturationGainIndex),
                               (mixValue, dryWetIndex)]
                  .sorted { a, b in
                      a.1 < b.1
                  }
                  .map {
                      var argument = bnns_graph_argument_t()
                      
                      argument.data_ptr = UnsafeMutableRawPointer(mutating: $0.0.baseAddress!)
                      argument.data_ptr_size = $0.0.count * MemoryLayout<Float>.stride
                      
                      return argument
                  }
    • 0:10 - Execute graph

      // Execute the function.
              BNNSGraphContextExecute(context,
                                      nil,
                                      arguments.count, &arguments,
  • 特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。

    クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。

Developer Footer

  • ビデオ
  • WWDC24
  • CPUでリアルタイムのML推論をサポート
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習
    • オープンソース(英語)
    • セキュリティ
    • 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.
    利用規約 プライバシーポリシー 契約とガイドライン