Как умножить матрицу с ее транспонированием, используя базу данных Oracle и utl_nla - PullRequest
2 голосов
/ 29 ноября 2010

Я схожу с ума от этой проблемы.Я не могу получить результат от следующего умножения:

X^t * X

X - это матрица m * n с m = 36 строками и n = 3 столбцами, которые представлены типом utl_nla_array_dbl.Данные берутся из таблицы и копируются с помощью простого кода pl / sql.

Чтобы решить мою проблему, я выбрал метод utl_nla.blas_gemm .Это матрично-матричный метод, в отличие от utl_nla.blas_gemv как матрично-векторного метода (я получил этот работающий. Мне удалось умножить эту самую матрицу X на вектор y и получить правильный результат).

Вот соответствующий код, который выводит мне матрицу с правильным измерением (3X3), но только с нулями в нем.Чтобы было понятнее, я жестко запрограммировал большинство параметров:

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);

Переменная XtX также имеет тип utl_nla_array_dbl и должна содержать результат.

Есть идеи, что я делаю не так?Я буду благодарен за каждый вклад, так как я полностью застрял и не могу найти никакой помощи в других местах в Интернете.

Ответы [ 2 ]

1 голос
/ 14 сентября 2013

У меня была такая же проблема, и через несколько дней я уверен, что процедура UTL_NLA.BLAS_GEMM не работает.Он был сломан в версии 10.2g, но такая же ошибка возникает в версии 11.2g.Проблема в процедуре in wrapper, написанной на PL / SQL.Он не обрабатывает параметры M, N, K, LDA, LDB, LDC правильно, в случае, если один или оба параметра TRANSA, TRANSB установлены в «T».Не удивительно, что это работает, когда матрица представляет собой квадратную матрицу, например, матрица A имеет размер 100x100 и соответствующий параметр TRANSA = 'T'.Процедура UTL_NLS.BLAS_GEMM неправильно обрабатывает параметры и в этом случае, но они равны, поэтому это не имеет никакого эффекта.Обходной путь, который я использую, прост: перед тем, как вызвать процедуру, я транспонирую соответствующую матрицу и всегда использую BLAS_GEMM с настройкой TRANSA = 'N' и TRANSB = 'N'.К сожалению, в пакете UTL_NLA нет процедуры транспонирования (кстати, у BLAS есть такая), но написать ее не составляет большого труда:

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;

Для меня настоящей болью была документация, например e40758.pdf,Он также полон ошибок, см., Например, стр.232-26, и это вводит меня в заблуждение, заставляет меня думать, что я передаю неправильные параметры.Я потратил пару часов на поиск в Интернете рабочего примера, но, конечно, напрасно.Вероятно, это простая ошибка в процедуре BLAS_GEMM, на исправление которой уходит половина нашего кода, и все же разработчики ждут правильной версии более 6 лет.

0 голосов
/ 01 декабря 2010

После просмотра спецификации для UTL_NLA и прочтения описания BLAS_GEMM мне кажется, что LDA и LDB должно быть 36. Попробуйте изменить их и посмотрите, поможет ли это.

Поделитесь и наслаждайтесь.

...