Lapack 和 Matlab 之间的不同结果

Different results between Lapack and Matlab

我想将 matlab 代码转换为 C。为此,我将 C 代码与英特尔 MKL 库连接并包含 "mkl_lapacke.h"。 Matlab代码包含:

>>A=mldivide(A1,A2) 其中 A1 和 A2 都是 10x10 实数方阵。 这可以解释为系统A1*X=A2

的解

在C代码中,我调用了Dgesv如下: info = LAPACKE_dgesv( LAPACK_ROW_MAJOR, n, nrhs, a, lda, ipiv,b, ldb ); 其中 lda=10,n=10 和 nrhs=10

问题是Matlab和Lapack返回的10x10的解有很大的不同! 这是 A1=a 和 A2=b

的代码
#include <stdlib.h>
#include <stdio.h>
#include "mkl_lapacke.h"

/* Auxiliary routines prototypes */
extern void print_matrix( char* desc, MKL_INT m, MKL_INT n, double* a, MKL_INT lda );
extern void print_int_vector( char* desc, MKL_INT n, MKL_INT* a );

/* Parameters */
#define N 10
#define NRHS 10
#define LDA N
#define LDB NRHS

/* Main program */
int main() {
        /* Locals */
        MKL_INT n = N, nrhs = NRHS, lda = LDA, ldb = LDB, info;
        /* Local arrays */
        MKL_INT ipiv[N];
       double a[LDA*N] = {
            -0.0091,    0.1024,   -0.2640,   -0.0956,    0.0635,   -0.1776,    0.1257,    0.1048,   -0.0869,    0.0106,
   -0.0865,    0.2401,    0.0455,   -0.0483,   -0.2640,    0.3985,    0.1095,   -0.2429,    0.1452,   -0.0629,
   -0.0428,    0.1669,   -0.0239,   -0.0877,   -0.0893,    0.2085,  -0.2095,   -0.0423,    0.0712,    0.0051,
   -0.0458,    0.0043,    0.3219,    0.1583,   -0.1277,   -0.0598,    0.2033,   -0.1075,   -0.0131,   -0.0277,
   -0.0597,    0.2190,    0.0053,    0.0084,   -0.0741,   -0.0993,    0.3048,   -0.0046,   -0.0718,   -0.0055,
    0.0538,   -0.0734,   -0.2116,   -0.0733,    0.0203,    0.2163,    0.0991,   -0.1309,    0.1299,   -0.0564,
   -0.0415,    0.1569,   -0.0053,   -0.0754,   -0.0855,    0.1912,   -0.2020,   -0.0347,    0.0524,    0.0122,
    0.0648,   -0.1265,   -0.1628,   -0.0357,    0.0592,    0.1129,    0.0953,   -0.0884,    0.0892,   -0.0431,
    0.0446,   -0.2029,    0.1323,    0.0604,    0.0271,    0.1125,   -0.1788,   -0.0454,    0.0663,   -0.0126,
    0.0241,   -0.1181,    0.1255,    0.0281,   -0.0157,    0.1600,   -0.2448,   -0.0524,    0.0855,    0.0092,};
        double b[LDB*N] = {
             -0.2225,   -0.2789,    0.1338,   -0.3709,   -0.4954,   -0.1445,   -0.0116,    0.0254,    0.0118,    0.0098,
    0.0362,   -0.3659,   -0.1204,   -0.0500,    0.1276,   -0.0473,   -0.2388,    0.0701,   -0.3668,   -0.0480,
    0.2351,    0.0922,   -0.0670,   -0.1074,    0.2423,   -0.3811,    0.0791,   -0.2176,   -0.0391,    0.0532,
   -0.0023,   -0.2109,    0.0767,   -0.1575,    0.2569,   -0.1005,    0.2427,    0.3022,    0.0923,   -0.0445,
    0.4103,    0.3612,    0.0651,   -0.0481,    0.1001,    0.5006,   -0.1107,    0.3178,   -0.0713,    0.4568,
    0.1862,   -0.3224,    0.0601,    0.1015,   -0.2129,    0.0320,   -0.1459,   -0.0723,    0.3412,    0.0431,
    0.1613,    0.3168,    0.0876,   -0.0442,   -0.2465,   -0.1598,   -0.1102,    0.2010,    0.0080,   -0.0619,
    0.0929,    0.1286,   -0.2801,    0.0119,   -0.1908,    0.0509,    0.2731,    0.1054,  -0.1830,    0.0112,
   -0.1971,   -0.1049,   -0.0354,    0.5010,    0.0685,   -0.2606,    0.0225,    0.0164,   -0.0140,   -0.0002,
    0.0452,   -0.2061,    0.2058,    0.0156,    0.0198,   -0.0294,    0.0453,   -0.1110,    0.0098,    0.0145,
        };

        /* Executable statements */
        printf( "LAPACKE_dgesv (row-major, high-level) Example Program Results\n" );
        /* Solve the equations A*X = B */
        info = LAPACKE_dgesv( LAPACK_ROW_MAJOR, n, nrhs, a, lda, ipiv,
                        b, ldb );
        /* Check for the exact singularity */
        if( info > 0 ) {
                printf( "The diagonal element of the triangular factor of A,\n" );
                printf( "U(%i,%i) is zero, so that A is singular;\n", info, info );
                printf( "the solution could not be computed.\n" );
                exit( 1 );
        }
        /* Print solution */
        print_matrix( "Solution", n, nrhs, b, ldb );
        /* Print details of LU factorization */
        print_matrix( "Details of LU factorization", n, n, a, lda );
        /* Print pivot indices */
        print_int_vector( "Pivot indices", n, ipiv );
        exit( 0 );
} /* End of LAPACKE_dgesv Example */

/* Auxiliary routine: printing a matrix */
void print_matrix( char* desc, MKL_INT m, MKL_INT n, double* a, MKL_INT lda ) {
        MKL_INT i, j;
        printf( "\n %s\n", desc );
        for( i = 0; i < m; i++ ) {
                for( j = 0; j < n; j++ ) printf( " %6.2f", a[i*lda+j] );
                printf( "\n" );
        }
}

/* Auxiliary routine: printing a vector of integers */
void print_int_vector( char* desc, MKL_INT n, MKL_INT* a ) {
        MKL_INT j;
        printf( "\n %s\n", desc );
        for( j = 0; j < n; j++ ) printf( " %6i", a[j] );
        printf( "\n" );
}

dgesv返回的解是:

LAPACKE_dgesv (row-major) 


 1.0e+03 *

    0.3270   -0.5215    0.0049    0.0619   -0.0199   -0.1558    2.9911    1.1247   -5.4283    5.2655
    0.0751   -0.2225    0.1936    0.0490   -0.0678   -0.0201    0.2473    0.1422   -0.4608    0.7307
   -0.0683    0.3846   -0.4393   -0.0885    0.1620    0.0024    0.2210   -0.0303   -0.3558   -0.2766
    0.1779   -0.9302    1.0602    0.2237   -0.3761   -0.0056   -0.4986    0.0816    0.7990    0.7407
   -0.1549    0.3202   -0.0615   -0.0345    0.0257    0.0775   -1.3939   -0.5276    2.5444   -2.5409
   -0.0069   -0.0202    0.0594    0.0175   -0.0235    0.0140   -0.1871   -0.0481    0.3191   -0.2247
   -0.0360    0.1518   -0.1521   -0.0332    0.0600    0.0122   -0.0471   -0.0597    0.0958   -0.3078
    0.0675   -0.1360    0.0075    0.0220    0.0272   -0.0318    0.5894    0.1936   -1.0823    1.0735
   -0.0129    0.0052    0.0142   -0.0096    0.0355    0.0096   -0.2460   -0.1281    0.4625   -0.4091
   -0.0963    0.1961   -0.0244   -0.0417   -0.0032    0.0743   -0.8836   -0.3268    1.5972   -1.6047

而Matlab返回的解是:

 1.0e+03 *

    0.1224   -0.0783   -0.1534   -0.0092    0.0609   -0.0555    1.3240    0.4477   -2.3813    2.0963
    0.0528   -0.1725    0.1739    0.0410   -0.0549   -0.0089    0.0615    0.0637   -0.1206    0.3758
   -0.0706    0.3868   -0.4366   -0.0889    0.1543    0.0029    0.2127   -0.0271   -0.3417   -0.2905
    0.1813   -0.9290    1.0499    0.2236   -0.3556   -0.0058   -0.4944    0.0666    0.7945    0.7407
   -0.0576    0.1085    0.0151   -0.0005   -0.0141    0.0297   -0.6005   -0.2044    1.0941   -1.0311
    0.0037   -0.0425    0.0664    0.0211   -0.0263    0.0088   -0.1006   -0.0141    0.1613   -0.0616
   -0.0286    0.1352   -0.1456   -0.0306    0.0543    0.0082    0.0190   -0.0308   -0.0253   -0.1830
    0.0264   -0.0438   -0.0292    0.0067    0.0455   -0.0119    0.2628    0.0591   -0.4845    0.4438
    0.0037   -0.0281    0.0227   -0.0046    0.0308    0.0012   -0.1030   -0.0717    0.2019   -0.1450
   -0.0352    0.0629    0.0242   -0.0202   -0.0285    0.0443   -0.3862   -0.1238    0.6877   -0.6572

正如 TroyHaskin 指出的那样,如果您按照以下步骤进行操作,您将获得 LAPACK 结果:

a=[-0.0091,    0.1024,   -0.2640,   -0.0956,    0.0635,   -0.1776,    0.1257,    0.1048,   -0.0869,    0.0106,
   -0.0865,    0.2401,    0.0455,   -0.0483,   -0.2640,    0.3985,    0.1095,   -0.2429,    0.1452,   -0.0629,
   -0.0428,    0.1669,   -0.0239,   -0.0877,   -0.0893,    0.2085,  -0.2095,   -0.0423,    0.0712,    0.0051,
   -0.0458,    0.0043,    0.3219,    0.1583,   -0.1277,   -0.0598,    0.2033,   -0.1075,   -0.0131,   -0.0277,
   -0.0597,    0.2190,    0.0053,    0.0084,   -0.0741,   -0.0993,    0.3048,   -0.0046,   -0.0718,   -0.0055,
    0.0538,   -0.0734,   -0.2116,   -0.0733,    0.0203,    0.2163,    0.0991,   -0.1309,    0.1299,   -0.0564,
   -0.0415,    0.1569,   -0.0053,   -0.0754,   -0.0855,    0.1912,   -0.2020,   -0.0347,    0.0524,    0.0122,
    0.0648,   -0.1265,   -0.1628,   -0.0357,    0.0592,    0.1129,    0.0953,   -0.0884,    0.0892,   -0.0431,
    0.0446,   -0.2029,    0.1323,    0.0604,    0.0271,    0.1125,   -0.1788,   -0.0454,    0.0663,   -0.0126,
    0.0241,   -0.1181,    0.1255,    0.0281,   -0.0157,    0.1600,   -0.2448,   -0.0524,    0.0855,    0.0092];


    b= [-0.2225,   -0.2789,    0.1338,   -0.3709,   -0.4954,   -0.1445,   -0.0116,    0.0254,    0.0118,    0.0098,
    0.0362,   -0.3659,   -0.1204,   -0.0500,    0.1276,   -0.0473,   -0.2388,    0.0701,   -0.3668,   -0.0480,
    0.2351,    0.0922,   -0.0670,   -0.1074,    0.2423,   -0.3811,    0.0791,   -0.2176,   -0.0391,    0.0532,
   -0.0023,   -0.2109,    0.0767,   -0.1575,    0.2569,   -0.1005,    0.2427,    0.3022,    0.0923,   -0.0445,
    0.4103,    0.3612,    0.0651,   -0.0481,    0.1001,    0.5006,   -0.1107,    0.3178,   -0.0713,    0.4568,
    0.1862,   -0.3224,    0.0601,    0.1015,   -0.2129,    0.0320,   -0.1459,   -0.0723,    0.3412,    0.0431,
    0.1613,    0.3168,    0.0876,   -0.0442,   -0.2465,   -0.1598,   -0.1102,    0.2010,    0.0080,   -0.0619,
    0.0929,    0.1286,   -0.2801,    0.0119,   -0.1908,    0.0509,    0.2731,    0.1054,  -0.1830,    0.0112,
   -0.1971,   -0.1049,   -0.0354,    0.5010,    0.0685,   -0.2606,    0.0225,    0.0164,   -0.0140,   -0.0002,
    0.0452,   -0.2061,    0.2058,    0.0156,    0.0198,   -0.0294,    0.0453,   -0.1110,    0.0098,    0.0145];

a\b

ans = 
  327.0114   -521.4858      4.9027     61.9130    -19.8927   -155.8372   2991.1079   1124.6681  -5428.3234   5265.5139
   75.1284   -222.4563    193.6070     48.9504    -67.7640    -20.0595    247.2690    142.2035   -460.8152    730.6545
  -68.2827    384.6219   -439.3150    -88.4497    162.0169      2.3759    221.0372    -30.3170   -355.8296   -276.5529
  177.9446   -930.1793   1060.1675    223.6455   -376.0511     -5.6118   -498.6298     81.5657    799.0423    740.6989
 -154.9540    320.2519    -61.4950    -34.5545     25.7087     77.4924  -1393.8961   -527.6382   2544.4178  -2540.9034
   -6.9249    -20.1575     59.3966     17.5369    -23.5432     14.0414   -187.0725    -48.1027    319.1279   -224.6643
  -35.9941    151.8283   -152.0953    -33.1855     59.9649     12.1877    -47.0808    -59.6673     95.7806   -307.7863
   67.5132   -136.0433      7.5317     21.9729     27.2220    -31.7538    589.3968    193.5591  -1082.2648   1073.4849
  -12.9406      5.2063     14.1874     -9.5474     35.5088      9.6252   -245.9788   -128.1143    462.4924   -409.1096
  -96.2949    196.1438    -24.3756    -41.7405     -3.1993     74.2884   -883.5854   -326.7665   1597.1577  -1604.6541

在 MATLAB 中将输入向量重塑为数组(假定列顺序),导致输入数组与您输入 LAPACK 的数组不同:

av = [  -0.0091000   0.1024000  -0.2640000  -0.0956000   0.0635000  -0.1776000   0.1257000   0.1048000  -0.0869000   0.0106000  -0.0865000   0.2401000   0.0455000  -0.0483000  -0.2640000   0.3985000  0.1095000  -0.2429000   0.1452000  -0.0629000  -0.0428000   0.1669000  -0.0239000  -0.0877000  -0.0893000   0.2085000  -0.2095000  -0.0423000   0.0712000   0.0051000  -0.0458000   0.0043000  0.3219000   0.1583000  -0.1277000  -0.0598000   0.2033000  -0.1075000  -0.0131000  -0.0277000  -0.0597000   0.2190000   0.0053000   0.0084000  -0.0741000  -0.0993000   0.3048000  -0.0046000 -0.0718000  -0.0055000   0.0538000  -0.0734000  -0.2116000  -0.0733000   0.0203000   0.2163000   0.0991000  -0.1309000   0.1299000  -0.0564000  -0.0415000   0.1569000  -0.0053000  -0.0754000 -0.0855000   0.1912000  -0.2020000  -0.0347000   0.0524000   0.0122000   0.0648000  -0.1265000  -0.1628000  -0.0357000   0.0592000   0.1129000   0.0953000  -0.0884000   0.0892000  -0.0431000  0.0446000  -0.2029000   0.1323000   0.0604000   0.0271000   0.1125000  -0.1788000  -0.0454000   0.0663000  -0.0126000   0.0241000  -0.1181000   0.1255000   0.0281000  -0.0157000   0.1600000  -0.2448000  -0.0524000   0.0855000   0.0092000]


reshape(av,10,10)

ans =

  -0.0091000  -0.0865000  -0.0428000  -0.0458000  -0.0597000   0.0538000  -0.0415000   0.0648000   0.0446000   0.0241000
   0.1024000   0.2401000   0.1669000   0.0043000   0.2190000  -0.0734000   0.1569000  -0.1265000  -0.2029000  -0.1181000
  -0.2640000   0.0455000  -0.0239000   0.3219000   0.0053000  -0.2116000  -0.0053000  -0.1628000   0.1323000   0.1255000
  -0.0956000  -0.0483000  -0.0877000   0.1583000   0.0084000  -0.0733000  -0.0754000  -0.0357000   0.0604000   0.0281000
   0.0635000  -0.2640000  -0.0893000  -0.1277000  -0.0741000   0.0203000  -0.0855000   0.0592000   0.0271000  -0.0157000
  -0.1776000   0.3985000   0.2085000  -0.0598000  -0.0993000   0.2163000   0.1912000   0.1129000   0.1125000   0.1600000
   0.1257000   0.1095000  -0.2095000   0.2033000   0.3048000   0.0991000  -0.2020000   0.0953000  -0.1788000  -0.2448000
   0.1048000  -0.2429000  -0.0423000  -0.1075000  -0.0046000  -0.1309000  -0.0347000  -0.0884000  -0.0454000  -0.0524000
  -0.0869000   0.1452000   0.0712000  -0.0131000  -0.0718000   0.1299000   0.0524000   0.0892000   0.0663000   0.0855000
   0.0106000  -0.0629000   0.0051000  -0.0277000  -0.0055000  -0.0564000   0.0122000  -0.0431000  -0.0126000   0.0092000

编辑:要获得与 lapack 相同的结果,您有多种选择:

  1. 明确更改输入向量,参见例如here 关于如何更改顺序,基本上类似于

    anew = a'(:);
    

    其中a是matlab矩阵形式(不是向量形式)的原始数据。

  2. 更改告诉 Lapack 例程是采用行顺序还是列顺序的标志。我的猜测是将 LAPACK_COLUMN_MAJOR 而不是 LAPACK_ROW_MAJOR 传递给你的函数,但是我不能保证这一点,因为我没有测试过它。