开发者

How to multiply matrix with its transpose using Oracle database and utl_nla

开发者 https://www.devze.com 2023-01-28 12:58 出处:网络
I\'m going nuts with this issue. I can\'t get the result from the following multiplication: X^t * X X is an m * n matrix with m = 36 rows and n = 3 columns which is represented by an utl_nla_array_

I'm going nuts with this issue. I can't get the result from the following multiplication:

X^t * X

X is an m * n matrix with m = 36 rows and n = 3 columns which is represented by an utl_nla_array_dbl datatype. The data origins from a table and gets copied by simple pl/sql code.

To solve my problem, I chose the method utl_nla.blas_gemm. It's a matrix-matrix method, in contrast to utl_nla.blas_gemv as a matrix-vector method (I got that one working. I was able to multiply that very matrix X by a vector y and received the right result).

Here is the relevant code, which outputs me a matrix with the right dimen开发者_如何学Pythonsion (3X3) but just zeros in it. To make it clearer I hard coded most parameters:

utl_nla.blas_gemm(
    transa => 'T',
    transb => 'N',
    m => 3,
    n => 3,
    k => 36,
    alpha => 1.0,
    a => X,
    lda => 3,
    b => X,
    ldb => 3,
    beta => 0.0,
    c => XtX,
    ldc => 3);

The variable XtX is also of type utl_nla_array_dbl and is to hold the result.

Any idea what I'm doing wrong? I'll appreciate every contribution since I'm totally stuck and can't find any help elsewhere on the web.


I had the same problem, and after a few days I'm sure , that the UTL_NLA.BLAS_GEMM procedure is broken. It was broken in the 10.2g version, and still the same error occurs in version 11.2g. The problem is in the in wrapper procedure written in PL/SQL. It does not handle the parameters M, N, K, LDA, LDB, LDC correctly, in the case when one or both of the parameters TRANSA, TRANSB are set to 'T'. Not surprisingly it is working, when the matrix is a sqare matrix, for example the matrix A is 100x100 and the relevant parameter TRANSA = 'T'. The procedure UTL_NLS.BLAS_GEMM mishandles the parameters in this case too, but they are equal, so it has no effect. The workaround I use is simple: before I call the procedure, I transpose the relevant matrix, and I use BLAS_GEMM allways with the setting TRANSA = 'N' and TRANSB = 'N'. Unfortunately there is no transpose procedure in the UTL_NLA package (btw. BLAS has one), but to write one is not a big deal:

PROCEDURE MatTranspose (nRows IN NUMBER, /* number of rows in A */
                       nCols IN NUMBER, /* number of columns in A */
                       mat_A IN utl_nla_array_dbl, /* supposed it is stored column-wise i.e. 'C' */
                       mat_At IN OUT utl_nla_array_dbl) IS
  /* the array can be larger then nRow * nCol, the rest part is not handled in either matrices */
  nIii   NUMBER;
  nJjj   NUMBER;
BEGIN
  FOR nIii IN 1 .. nRows LOOP                                                                          
     FOR nJjj IN 1 .. nCols LOOP                                                                   
        mat_At (nJjj + nCols * (nIii - 1)) := mat_A (nIii + nRows * (nJjj - 1));
     END LOOP;
  END LOOP;
END MatTranspose;

For me the real pain was the documentation, e.g. e40758.pdf. It is full of mistakes too, see for instance p. 232-26 and it misleads me, makes me think I pass the wrong parameters. I spent couple of hours searching the web for a working example but - of course - in vain. It is probably a simple error in the BLAS_GEMM procedure which takes half an our to fix, and yet developers are waiting more then 6 years for a correct version.


After looking at the spec for UTL_NLA and reading the description of BLAS_GEMM, it looks to me like LDA and LDB should be 36. Try changing those and see if it helps.

Share and enjoy.

0

精彩评论

暂无评论...
验证码 换一张
取 消