streaming_node テンプレート・クラス

概要

streaming_node は、キューを利用してデバイスにカーネルおよびデータを渡すストリーミング・プログラミング・モデルを使用できるようにします。streaming_node クラスは、フローグラフにストリーミング・プログラミング・モデルの使用を簡単に統合するために必要なインターフェイスを提供します。開発者は、グラフを使用してヘテロジニアス・プラットフォームの異なるデバイスやハードウェア・リソースで実行する機能を調整できます。使用する具体的なモデルの低水準の詳細を定義するには、streaming_node に Factory を提供する必要があります。

opencl_node は、インテル® スレッディング・ビルディング・ブロック (インテル® TBB) ライブラリーで提供されるモデル固有の streaming_node の例です。opencl_node は、統合型および外付け型グラフィックス・プロセシング・ユニット (GPU) や CPU のような、OpenCL* をサポートするデバイスで OpenCL* カーネルを実行できるようにします。opencl_nodeopencl_factory を使用する streaming_node として実装されます。

開発者は、OpenCL* 以降のほかのモデルをサポートする Factory を定義するように選択できます。また、ほかの Factory をライブラリーの将来のバージョンで提供することもできます。

構文

        template < typename... Args >
      class streaming_node;
        template < typename... Ports, typename JP, typename Factory >
        class streaming_node < tuple < Ports... >, JP, Factory >;
      

ヘッダー

        #define TBB_PREVIEW_FLOW_GRAPH_FEATURES 1
        #include "tbb/flow_graph.h"
      

説明

streaming_node クラスは、ヘテロジニアス・コンピューティング・デバイスをサポートする、より大きなフロー・グラフ・ベースのソリューションの一部です。

このセクションで使用されている用語の定義は次のとおりです。
用語 定義
Factory

Factory は、デバイスに入力データをアップロードし、デバイスでカーネルを実行し、すべての必要な型を提供するインターフェイスを提供します。

デバイス

カーネルを実行する計算リソース。

カーネル

デバイスで実行する計算関数。

カーネル引数

カーネルを実行するためにデバイスに提供されるデータ。

入力引数、出力引数、または両方。

カーネル範囲

単一カーネル実行の計算範囲。

streaming_node 使用モデルにはいくつかの基本原則があります。

streaming_node のダイアグラムを次に示します。
streaming_node のダイアグラム

上記のように、カーネル引数 (およびカーネル範囲 (オプション)) は入力ポートから読み取るかノードを使用する前に定義します。
カーネル引数およびカーネル範囲は入力ポートから読み取る

上記のように、出力ポートは async_msg から派生したメッセージを常に送ります。このため、ノード実行の最後に出力データの準備ができていない場合があります。しかし、async_msg は、ほかのフローグラフのノードがこれらのメッセージに適切に応答し、利用可能になる前にデータを使用しないことを保証します (async_msg を参照)。

単純化された streaming_node アルゴリズムは、次の手順で記述できます。

streaming_node は、常に次のノードに async_msg_type 値を送ります。カーネル実行の終了を待ちません。待機は、‘future-promise’ コンセプトのように、実際の結果データを処理する時点で行われます。(詳細は、async_msg クラスの説明を参照。)

すべてのカーネル引数はカーネルの実行により変更されると仮定しています。この仮定により、出力 async_msgs の読み取り専用引数のデータが利用可能になるのが遅れることがあります。

Factory コンセプト

概要

streaming_node は、Factory オブジェクトを利用して特定のデバイスと通信する抽象実行メカニズムです。Factory は、デバイスに入力データをアップロードし、デバイスでカーネルを実行し、すべての必要な型を提供する具体的な手段を提供します。

要件

次の表は、Factory 型 F の要件を示しています。

Factory コンセプト

擬似署名

意味

template <typename T>

using F::async_msg_type = .....;

デバイス固有の型: 非同期メッセージ型 (async_msg クラスから派生)

typedef ..... F::device_type;

デバイス固有の型: ターゲットデバイス型

typedef ..... F::kernel_type;

デバイス固有の型: デバイスカーネル型

typedef ..... F::range_type;

オプション。デバイス固有の型: 範囲型

template <typename ...Args>

void F::send_kernel(device_type device, const kernel_type& kernel, [const range_type& work_size,] Args&... args)

デバイスでカーネルを実行します

template <typename ...Args>

void F::send_data(device_type device, Args&... args)

デバイスにデータをアップロードします

template <typename FinalizeFn, typename ...Args>

void F::finalize(device_type device, FinalizeFn fn, Args&... args)

カーネル実行後の終了処理

'fn' ファンクターはカーネル実行が実際に停止した後に呼び出します

Factory が範囲の概念をサポートしている場合、range_type 型を定義する必要があります。この場合、streaming_node は範囲を定義するメソッドを提供します。Factory がカーネル範囲をサポートしていない場合、これらのメソッドは利用できません。

その場合、send_kernel インターフェイスは次のようになります。

        template <typename ...Args>
        void F::send_kernel(device_type device, const kernel_type& kernel, Args&... args)

説明

send_kernel メソッドは、ストリーミング・ノードに呼び出され、指定された外部デバイスでカーネルを開始します。すべての入力引数 (Args&... args) は、async_msg_type 型の参照として提供されます。参照は、引数が set_args から値で設定された場合は定数参照、引数が入力ポートからの動的な値 (つまり、set_argsport_ref 引数で設定された値) の場合は非定数参照です。

send_data メソッドは、ストリーミング・ノードに呼び出され、指定されたデバイスにオリジナルのカーネル引数をアップロードします。すべての入力引数 (Args&... args) は、async_msg_type 型の参照として提供されます。リストには、set_args から (port_ref としてではなく) 値で設定される値のみ含まれます。

finalize メソッドはストリーミング・ノードに呼び出され、Factory にグラフのコールバック (カーネル実行が終了したときにグラフに通知) を設定させます。この場合、提供される終了処理ファンクターを呼び出す必要があります。finalize メソッドは、次のグラフノードがこの出力メッセージを拒否した場合、またはノードの出力ポートが次のノードに接続されていない場合 (グラフのどの部分もカーネルの結果を待っていない場合) にのみ、ノードに呼び出されることに注意してください。すべての入力引数 (Args&... args) は、send_kernel メソッドのように、async_msg_type 型の定数/非定数参照として提供されます。

Device Selector の概念

概要

Device Selector オブジェクトは、Factory インスタンスに利用可能なデバイスから 1 つのデバイスを選択する単純なユーザー・ファンクターです。

要件

次の表は、Device Selector 型 DS の要件を示しています。

Device Selector の概念

擬似署名

意味

device_type DS::operator()( factory& f )

ノードでのカーネル実行のために Factory からデバイスを取得します。

サンプル

        struct external_device_selector {
            device_type operator()( factory& f ) {
                return f.get_somehow_an_available_device();
            }
        };

デバイスの型は Factory によって定義されます。

ポート参照の使用法

streaming_node ユーザーは、定数値としてカーネル引数 (および範囲引数 (オプション)) を提供するか、入力ポートをこれらの引数にマップできます。

Factory がカーネル範囲をサポートしている場合、次のメソッドを streaming_node クラスで利用して範囲値を設定します。

        void set_range(const range_type& work_size);

        void set_range(range_type&& work_size);

カーネル引数を定数として設定するには、streaming_node クラスの次のメソッドを使用します。

        template <typename ...Args>
        void set_args( Args&&... args );

サンプル

        node.set_range( {{ width, height }} );
        node.set_args(/* stride_x */ 1, /* stride_y */ 0, /* stride_z */ 0, /* dim */ 1 );

入力ポートをカーネル引数 (およびカーネル範囲 (サポートされている場合) にマップするには、streaming_node クラスの次のメソッドを使用します。

        void set_range( port_ref_entity );

        template <typename ...Args>
        void set_args( Args&&... args ) ; // args can include port_ref_entity(s)

port_ref_entity は下記のヘルパーにより返されます。

サンプル

        node.set_range( port_ref<2> );
        node.set_args( port_ref<0, 1> );

または

        node.set_range( port_ref<2>() );
        node.set_args( port_ref<0, 1>() );

または

        node.set_range( port_ref<2> );
        node.set_args( port_ref<0, 1>() );

アプローチは簡単に組み合わせることができます。

サンプル

        node.set_range( port_ref<2> );
        node.set_args( port_ref<0, 1>(), /* stride_x */ 1, /* stride_y */ 0, /* stride_z */ 0, /* dim */ 1 );

このサンプルは、範囲をポート 2 から受け取り、ポート 0 および 1 からのデータをカーネル引数として事前定義定数引数 (stride_x、stride_y など) とともにデバイスに送ります。

サンプル

opencl_node クラスの実装は streaming_node クラスの使用例です。

詳細は、http://www.isus.jp/products/tbb/opencl-node-overview/ を参照してください。

パブリックメンバー

  
namespace tbb {
namespace flow {

template<typename... Args>
class streaming_node;

template<typename... Ports, typename JP, typename Factory>
class streaming_node< tuple<Ports...>, JP, Factory > : ..... {
public:
    template <typename DeviceSelector>
    streaming_node( graph& g, const kernel_type& kernel, DeviceSelector d, Factory& f );

    streaming_node( const streaming_node& node );

    streaming_node( streaming_node&& node );

    ~streaming_node() ;

    template <typename... Args>
    void set_args( Args&&... args ) ;

    // 次のメソッドは Factory::range_type が
    // 定義されている場合にのみ利用できます
    void set_range(const range_type& work_size);

    void set_range(range_type&& work_size);

    template <int N>
    void set_range(port_ref_impl<N, N>);

    template <int N>
    void set_range(port_ref_impl<N, N>(*)());

};

}
}
次の表は、このテンプレート・クラスのメンバーの詳細な情報を提供します。
メンバー 説明
typename... Ports

ノードの入力データ型。

typename JP

結合ポリシー。詳細は、join_node クラスの説明を参照してください。

typename Factory

デバイス固有の Factory 型。

template <typename DeviceSelector> streaming_node( graph& g, const kernel_type& kernel, DeviceSelector d, Factory& f );

メイン・コンストラクター。

streaming_node( const streaming_node& node );

コピー・コンストラクター。

streaming_node( streaming_node&& node );

ムーブ・コンストラクター。

~streaming_node();

デストラクター。

template <typename... Args> void set_args( Args&&... args );

カーネル実行の引数を設定します (引数には値やポート参照を含めることができます)。

void set_range(const range_type& work_size);

カーネル実行の定数範囲を設定します。

このメソッドは、Factory::range_type が定義されている場合にのみ利用できます。

void set_range(range_type&& work_size);

前のメソッドと同じですが、ムーブ・セマンティクスを使用します。

このメソッドは、Factory::range_type が定義されている場合にのみ利用できます。

template <int N> void set_range(port_ref_impl<N, N>);

N 番目のポートから動的に範囲値を取得するように範囲のポート参照を設定します。

このメソッドは、Factory::range_type が定義されている場合にのみ利用できます。

template <int N> void set_range(port_ref_impl<N, N>(*)());

N 番目のポートから動的に範囲値を取得するように範囲のポート参照を設定します。

このメソッドは、Factory::range_type が定義されている場合にのみ利用できます。

関連情報