NVIDIA の cuBLAS ライブラリについて疑問に思っています。誰もそれを経験したことがありますか?たとえば、BLAS を使用して C プログラムを作成した場合、BLAS の呼び出しを cuBLAS の呼び出しに置き換えることができますか? または、ユーザーが実行時に選択できるメカニズムを実装する方がよいでしょうか?
Boost が提供する BLAS ライブラリを C++ で使用するとどうなりますか?
janneb の回答は正しくありません。cuBLAS はCPU BLAS のドロップイン代替品ではありません。データが既にデバイス上にあると想定し、関数シグネチャには cuBLAS コンテキストを追跡するための追加のパラメーターがあります。
ただし、CUDA 6.0 で登場するのは、まさにこの「ドロップイン」機能を提供する NVBLAS と呼ばれる新しいライブラリです。Level3 BLAS 呼び出し (GEMM、TRSV など) をインターセプトし、それらを自動的に GPU に送信し、オン GPU 計算で PCIE 転送を効果的にタイル化します。
https://developer.nvidia.com/cublasxtにいくつかの情報があり、CUDA 6.0 は CUDA 登録開発者が今日利用できます。
完全なドキュメントは、CUDA 6.0 が一般にリリースされるとオンラインになります。
CUBLASはBLASをラップアラウンドしません。CUBLASは、一部のFortranコードやBLASなど、列優先の順序で行列にもアクセスします。
CUDAの場合でも、Cでコードを書くことに慣れています。CBLAS(BLASのCラップ)で記述されたコードは、CUDAコードに簡単に変更できます。BLASを使用するFortranコードは、CBLASを使用するC /C++コードとはまったく異なることに注意してください。FortranとBLASは通常、行列またはdouble配列を列優先の順序で格納しますが、C /C++は通常行優先の順序を処理します。私は通常、行列を1D配列に保存してこの問題を処理し、#defineを使用して、行列の要素i、jにアクセスするマクロを次のように記述します。
/* define macro to access Aij in the row-wise array A[M*N] */
#define indrow(ii,jj,N) (ii-1)*N+jj-1 /* does not depend on rows M */
/* define macro to access Aij in the col-wise array A[M*N] */
#define indcol(ii,jj,M) (jj-1)*M+ii-1
CBLASライブラリには、各関数に行列の順序を与えるための適切に編成されたパラメーターと規則(const enum変数)があります。行列の格納も異なることに注意してください。行方向の帯行列は、列単位の帯行列と同じように格納されません。
コードを2回記述せずに、ユーザーがBLASとCUBLASのどちらを使用するかを選択できるメカニズムはないと思います。CUBLASには、ほとんどの関数呼び出しで、BLASには表示されない「ハンドル」変数もあります。私は#defineを使って関数呼び出しごとに名前を変更しましたが、これは機能しない可能性があります。
BLAS コードを CUBLAS に移植しています。私が使用している BLAS ライブラリは ATLAS なので、BLAS ライブラリの選択までは正しいかもしれません。
ATLAS BLAS では、列優先か行優先かを指定する必要があります。列優先を使用する CLAPACK を使用していたため、列優先を選択しました。一方、LAPACKE は行優先順序を使用します。CUBLAS は列優先順です。それに応じて調整する必要があるかもしれません。
注文が問題にならなかったとしても、CUBLAS への移植は決して簡単な代替品ではありませんでした。最大の問題は、データを GPU のメモリ空間に出し入れする必要があることです。そのメモリは cudaMalloc() を使用してセットアップされ、期待どおりに機能する cudaFree() で解放されます。cudaMemcpy() を使用して GPU メモリにデータを移動します。これを行う時間は、CPU から GPU に移行する価値があるかどうかの大きな決定要因になります。
ただし、それが完了すると、呼び出しはかなり似ています。CblasNoTrans は CUBLAS_OP_N になり、CblasTrans は CUBLAS_OP_T になります。BLAS ライブラリ (ATLAS のように) でスカラーを値で渡すことができる場合は、それを参照渡しに変換する必要があります (FORTRAN では通常のことです)。
これを考えると、CPU/GPU の選択を可能にするスイッチは、BLAS を使用する関数内よりも簡単に高いレベルになります。私の場合、アルゴリズムの CPU と GPU のバリエーションがあり、問題のサイズに応じてより高いレベルでそれらを選択しました。