web-dev-qa-db-ja.com

CUDAカーネルでEigenを操作する方法

Eigenはc ++線形代数ライブラリです http://eigen.tuxfamily.org

基本的なfloat配列などの基本的なデータ型を操作するのは簡単で、それをデバイスメモリにコピーして、ポインタをcudaカーネルに渡すだけです。しかし、固有行列は複雑なタイプなので、それをデバイスメモリにコピーして、cudaカーネルに読み取り/書き込みさせる方法はありますか?

14
Mickey Shine

生のCポインターを介して_Eigen::Matrix_のデータにアクセスするだけの場合は、.data()関数を使用できます。係数は、デフォルトでは列メジャー順にメモリに順次格納されます。要求された場合は行メジャーに格納されます。

_MatrixXd A(10,10);
double *A_data = A.data();
_
8
ggael

2016年11月(Eigen 3.3のリリース)以降、新しいオプションが存在します:CUDAカーネル内で直接Eigenを使用するこの質問 を参照。

リンクされた質問の例:

__global__ void cu_dot(Eigen::Vector3f *v1, Eigen::Vector3f *v2, double *out, size_t N)
{
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if(idx < N)
    {
        out[idx] = v1[idx].dot(v2[idx]);
    }
    return;
}

Eigen::Vector3fの配列をデバイスにコピーする:

Eigen::Vector3f *Host_vectors = new Eigen::Vector3f[N];
Eigen::Vector3f *dev_vectors;
cudaMalloc((void **)&dev_vectors, sizeof(Eigen::Vector3f)*N)
cudaMemcpy(dev_vectors, Host_vectors, sizeof(Eigen::Vector3f)*N, cudaMemcpyHostToDevice)
15
GPMueller

コードの書き換えと再調整とは別に、GPUで行列計算を実行する研究プロジェクトの副産物として記述されたEigen互換ライブラリがあり、複数のバックエンドを使用できます: https://github.com/ rudaoshi/gpumatrix

私はそれを保証することはできませんが、それがうまくいくなら、それはおそらくあなたが探しているものとまったく同じです。

より汎用的なソリューションが必要な場合は、 このスレッド に非常に役立つ情報が含まれているようです

4
rubenvb

2つの方法があります。

EigenをGPUで動作させます。これはおそらく難しく、パフォーマンスが良くありません。少なくとも、GPUでの作業が、GPUをコンパイルして結果を生成することだけを意味する場合。 Eigenは、最新のCPU向けに実質的に手作業で最適化されています。内部的には、Eigenは独自のアロケーターとメモリレイアウトを使用していますが、これらはおそらくCUDAではうまく機能しません。

2番目の方法は実行が簡単で、従来のEigenコードを壊してはなりません。おそらく、あなたの場合に適しているのはおそらく唯一の方法です。基になる行列をプレーン行列に切り替えます(つまり、double**) 使用する - Eigen::Map 。このようにして、コードが壊れないようにプレーンデータ型へのEigenインターフェイスがあり、通常行われているように、通常のc配列として行列をGPUに送信できます。欠点は、おそらくEigenを最大限に活用できないことですが、ほとんどの作業をGPUにオフロードすれば問題ありません。

それは実際に物事を少し逆転させています。 EigenアレイをCUDAで動作させる代わりに、Eigenを通常のアレイで動作させることができます。

3
luk32