この例の問題点は、正方行列に対してのみ機能することです。行列が正方形でない場合、寸法ミスマッチのためにA^t*B^t
を計算することはできません(次元がA*B
の場合は正しいと仮定します)。
実際にcuBLASをインストールしているわけではありませんので、暗闇の中でのショットです。しかし、cuBLASが通常のBLASとは異なる動作をすると本当に驚いています。 BLASは、行列を列メジャーオーダー(別名Fortranオーダー)にすることを期待していますが、行メジャーオーダー(別名Cオーダー)のマトリックスにも使用できます。
私の意見では、完全に間違っているかもしれませんが、gemm_v2
は、2つのC-オーダー行列の乗算を処理する通常の/最良の方法ではありません。たとえば、答えとして次数行列を求める。
次のように働くだろうgemm
の助けを借りて、2つのC-オーダー行列の積を計算するためのトリック:
をそれはおそらくあなたに知られていても、私が上で詳しく説明して最初たい行major-私の答えを体現するために、注文(c-memory-layout)と列major-order(fortran-memory-layout)
我々は持っているので、場合2x3
(すなわち2行3列)、いくつかの連続したメモリ内の行列A
、それを保存、我々が得る:我々が表す連続したメモリを、得れば意味
row-major-order(A) = A11, A12, A13, A21, A22, A23
col-major-order(A) = A11, A21, A12, A22, A13, A33
行列を行優先順位に置き換えて、それを列主要順序の行列として解釈すると、全く異なる行列が得られます!
我々は転置行列A^t
を見てみる場合は、我々は簡単に見ることができます:
row-major-order(A) = col-major-order(A^t)
col-major-order(A) = row-major-order(A^t)
我々は結果として行優先順に行列C
を取得する場合は、ことを意味し、 blas-routineは、転置された行列C
を列メジャーオーダー(この後は変更できません)の後に、この非常にメモリに書き込む必要があります。しかし、C^t=(AB)^t=B^t*A^t
とB^t
とA^t
は、列メジャーオーダーで再解釈された元の行列です。
gemm('N', 'N', m, n, k, 1.0, B, m, A, k, 0.0, C, m)
は注意してください:
- は行っておりません
さて、A
はn x k
- マトリックスとB
k x m
- マトリックス、次のようにする必要がありますgemmルーチンの呼び出しも聞かせて行列A
およびB
を転置する必要があります。これは、C順序をFortranオーダとして再解釈することによって処理されるためです。
A
とB
は、結果としてC^t
をFortranオーダーで取得するために置き換えなければなりません。
- 結果の行列
C
はC順序である(Fortran-orderからC-orderへの再解釈により、^t
を取り除く)。
blasの呼び出しで、gemm(transa、transb、m、n、k、alpha、A:r、B:r、beta、C:w)を指定します。 transaとtransbは行列に適用される演算です。 gemm_v1の例では、これはアイデンティティ操作で、gemm_v2では転置です。次に、m、n、およびkを指定します。これらはA(m)の#rows、B(n)のA /#行の#columns、B(k)の列です。この例の構文でそれを保持している場合は、行列の2乗になるように指定します。したがって、これは変更する場所です。行列の形が宣言と一致していることを確認してください。 – Uvar