5

行列演算には CUBLAS (Cuda Blas ライブラリ) を使用しています。

CUBLAS を使用して、行列項目の累乗/二乗平均平方根を達成することは可能ですか?

つまり、2x2 行列を持つ

1 4
9 16

私が欲しいのは、与えられた値、例えば2に昇格する関数です

1 16
81 256

二乗平均平方根の計算など

1 2
3 4

これはCUBLASで可能ですか?この目的に適した関数が見つかりませんが、まずここで独自のカーネルのコーディングを開始するように依頼します。

4

1 に答える 1

10

したがって、これは自分で実装する必要があるかもしれません。ライブラリがそれをやってくれないからです。(おそらく、BLAS レベル 3 ルーチン (確かに行列要素の 2 乗) の観点から、それを実装する方法がいくつかありますが、それには費用がかかり、さもなければ不必要な行列とベクトルの乗算が必要になります。 d 平方根演算を行います)。その理由は、これらの操作が実際には線形代数の手順ではないためです。各行列要素の平方根を取ることは、基本的な線形代数操作に実際には対応していません。

幸いなことに、これらの要素単位の操作は CUDA で非常に簡単に実装できます。繰り返しになりますが、最高のパフォーマンスを得るために使用できるチューニング オプションはたくさんありますが、かなり簡単に始めることができます。

行列の加算演算と同様に、ここでは NxM 行列を (N*M) の長さのベクトルとして扱います。これらの要素ごとの操作では、行列の構造は重要ではありません。したがって、行列の最初の要素へのポインターを渡し、それを N*M の数値の単一のリストとして扱います。float(先ほど話していたように、ここでは sSGEMMを使用していると仮定しますSAXPY。)

操作を実装する CUDA コードの実際のビットであるカーネルは、非常に単純です。今のところ、各スレッドは 1 つの配列要素の 2 乗 (または平方根) を計算します。(これがパフォーマンスにとって最適かどうかは、テストできるものです)。したがって、カーネルは次のようになります。B_ij = (A_ij)^2; のようなことをしていると思います。A_ij = (A_ij)^2 のようにその場で演算を実行したい場合は、それも実行できます。

__global__ void squareElements(float *a, float *b, int N) {
    /* which element does this compute? */
    int tid = blockDim.x * blockIdx.x + threadIdx.x;

    /* if valid, squre the array element */
    if (tid < N) 
            b[tid] = (a[tid]*a[tid]);
}

__global__ void sqrtElements(float *a, float *b, int N) {
    /* which element does this compute? */
    int tid = blockDim.x * blockIdx.x + threadIdx.x;

    /* if valid, sqrt the array element */
    if (tid < N) 
            b[tid] = sqrt(a[tid]);   /* or sqrtf() */
}

エラーがわずかに増加しても問題ない場合は、最大エラーが 3 ulp (最後の桁の単位) の 'sqrtf()' 関数の方が大幅に高速であることに注意してください。

これらのカーネルをどのように呼び出すかは、実行する順序によって異なります。これらの行列で既にいくつかの CUBLAS 呼び出しを行っている場合は、既に GPU メモリにある配列でそれらを使用する必要があります。

于 2011-03-27T15:46:34.457 に答える