ユーザーとライブラリー間のスパース BLAS 行列ハンドル規約#

スパース行列ハンドル (sparse::matrix_handle_t) は、sparse::set_<format>_data(q, handle, /*user data*/) 形式の呼び出しでユーザーからデータを受け取ります (例: sparse::set_csr_data(q, handle, /*ユーザーデータ*/))。他の oneMKL ドメインとは異なり、sparse::matrix_handle_t とユーザーデータは、oneMKL ライブラリーへの個々の呼び出しの外部に保持されます。その後、ユーザーがそのハンドルを使用して oneMKL スパース BLAS API を呼び出すと、ライブラリーは各種操作でハンドル内に内部的に保存されたデータを使用します。行列ハンドルが存在している間は、ユーザーとライブラリーの両方が同時にデータにアクセスできるため、実行できる操作と実行できない操作について何らかの合意が必要です。そのため、スパース BLAS SYCL*API と sparse::matrix_handle_t の使用に関して、ユーザーライブラリー間にそれぞれの役割と責任を記述する暗黙の規約を導入します。

sparse::matrix_handle_t オブジェクトの説明#

まず、sparse::matrix_handle_t は、何らかの内部行列形式または表現を持つ一般スパース行列オブジェクトを表すことに注意してください。sparse::matrix_handle_t オブジェクトでその行列データのデバイス USM ポインターを指定すると、そのハンドルはデバイス USM ポインターに関連付けられた sycl::context および sycl::device にバインドされ、その sycl::device と互換性のあるコンテキスト内の任意のデバイスで使用できるようになります (特定のデバイスからピアツーピアで読み取りできます)。行列データに共有およびホスト USM ポインターまたは sycl::buffer's を使用すると、その sparse::matrix_handle_t オブジェクトが関連付けられている sycl::context にバインドされ、コンテキスト内の任意のデバイスで使用できるようになります。特定のコンテキスト内で適切なキューとデバイスで行列ハンドルを使用していることを確認するのはユーザーの責任です。

次に、 sparse::matrix_handle_t は、「不透明な状態がアタッチされたユーザーの行列データ配列のビュー」として説明できます。つまり、これはそもそも軽量のビューですが、sparse::optimize_* API と、場合によっては実行 API (sparse::matmat() など) を使用することで、ハンドルの有効期間中持続するさまざまな内部最適化/構造によって隠し状態が拡張され、目的とする操作で優れたパフォーマンスを実現できるようになります。

sparse::matrix_handle_t オブジェクトに関するユーザーとライブラリーの合意#

以下の規約は、ハンドルデータの所有権と使用に関するユーザーライブラリーの役割について説明しています。

ユーザーの合意:

  1. ユーザーsparse::matrix_handle_t に提供されるすべてのデータを所有し、それらを適切に作成および破棄する責任があります。つまり、データはユーザーによって作成され、その後、sparse::set_csr_data() などのライブラリー API を使用して行列ハンドルに渡されます。データは、行列ハンドルの使用と行列ハンドルの解放がすべて終了した後にのみ破棄できます。

  2. ユーザーは、データ配列が sparse::matrix_handle_t 内にある間は、データ配列を直接変更しないことに同意します。変更は、行列ハンドルにアタッチする前に行う必要があります。または、可能な場合は、指定された方法で行列ハンドルのデータを変更するスパース BLAS ライブラリー API を使用して間接的に行う必要があります。

ライブラリーの合意:

  1. ライブラリーは、スパース BLAS API ライブラリー呼び出し中に sparse::matrix_handle_t にデータを作成して保存する場合があります。このようなデータはライブラリーが所有し、それぞれの行列ハンドルの解放時の廃棄についてはライブラリーが責任を負います。ユーザーはこのデータにアクセスできません。

  2. ライブラリーは、データの変更が可能であることを明示的に示すライブラリ API (sparse::sort_matrix()sparse::omatcopy() など) を経由しない限り、sparse::matrix_handle_t 内のユーザー提供のデータ配列を変更しないことに同意します。

これらの規約内容を理解し、さらに高度な使用推奨事項を理解することで、ユーザーは oneMKL SYCL* スパース BLAS API を安全に使用してワークロードとアプリケーションを高速化することができ、ライブラリーはハンドルの有効期間を通じてユーザーデータの一貫した状態を信頼できるようになります。

高度な使用に関する推奨事項#

  1. sparse::matrix_handle_t オブジェクトはスレッドセーフとは見なされていないため、ホスト上でシリアル化する必要があります。

  2. ほとんどのスパース BLAS 操作は、sparse::matrix_handle 内のユーザー指定のデータを読み取り専用で使用します。例外は、出力 C 行列 (A と B は読み取り専用のまま) の sparse::matmat() などの sparse::matrix_handle_t を入力する API、または sparse::omatcopy() や、ユーザーデータを変更することを明示的に示す sparse::sort_matrix() などの API です。

    1. ユーザーは、同じコンテキストおよびデバイス上の複数の sparse::matrix_handle_t's で同じデータ配列を使用しないことが推奨されますが、注意すれば安全に使用できる可能性があります。パフォーマンスに影響する可能性があります。

    2. また、ユーザーは、同じコンテキストおよびデバイス上の sparse::matrix_handle_t とは独立して、他のカーネルまたはライブラリー呼び出しで sparse::matrix_handle_t で使用されている生のデータ配列を読み取り専用で使用しないことを推奨しますが、注意すれば安全に実行できる場合もあります。パフォーマンスに影響する可能性があります。

sparse::matrix_handle_t の使用ワークフローの例#

使用モデルを示すワークフローの例は次のとおりです:

// (A) SYCL*USM デバイス alloc や sycl::buffer などを使用して、スパース行列用のユーザーメモリーを割り当てます 
// (B) ホストからデータを memcpy するなど、行列配列で操作を行います 
// (C) スパース行列ハンドルを作成し、行列配列を渡します 
// (D) 選択したライブラリー呼び出しをいくつか実行します (行列ハンドルを使用など) 
// (E) sparse::release_matrix_handle() を呼び出して行列ハンドルを破棄します 
// (F) ユーザーメモリーに対して操作を行います (変更、コピーなど) 
// (G) 同じ配列を使用して別のスパース行列ハンドルを作成します 
// (H) ライブラリー呼び出しを行います 
// (I) sparse::release_matrix_handle() を呼び出して行列ハンドルを破棄します 
// (J) ユーザーメモリーを活用できます