LAPACK と BLAS 関数の呼び出し
MEX ファイルを使用して、LAPACK または BLAS の関数を呼び出すことができます。MEX ファイルを作成するには、C/C++ または Fortran でのプログラミング経験と、実行可能ファイルをビルドするためのソフトウェア リソース (コンパイラとリンカー) が必要です。また、これは、Fortran サブルーチンの使用方法を理解する場合にも役立ちます。MATLAB® では、matlabroot
/extern/lib
に mwlapack
および mwblas
ライブラリが用意されています。初めてでもすぐに開始できるように、matlabroot
/extern/examples/refbook
にソース コードのサンプルが用意されています。
LAPACK または BLAS 関数を呼び出すには以下を実施します。
mexFunction
ゲートウェイ ルーチンを含むソース MEX ファイルを作成します。プラットフォームでサポートされるコンパイラがあることを確認します。サポートされているコンパイラの最新の一覧については、サポートされるコンパイラを参照してください。
mex
コマンドと実数/虚数分離型複素数のビルド フラグ-R2017b
を使用してバイナリ MEX ファイルをビルドします。ソース ファイルをライブラリ
mwlapack
およびmwblas
のいずれか、またはその両方にリンクする。mwlapack
およびmwblas
ライブラリは、行列の次元について 64 ビットの整数のみをサポートする。-compatibleArrayDims
オプションを使用しないでください。複素数を使用する関数で MEX ファイルをビルドするには、実数/虚数分離型複素数の Fortran 関数への受け渡しを参照してください。
BLAS 関数または LAPACK 関数の詳細については、https://netlib.org/blas/またはhttps://netlib.org/lapack/を参照してください。
BLAS 関数を使用した matrixMultiply
MEX 関数のビルド
この例では、サンプルの MEX ファイル matrixMultiply.c
をビルドする方法を説明します。このファイルは BLAS ライブラリの関数を使用します。このファイルは、ファイルをローカル フォルダーにコピーして使用します。以下に例を示します。
copyfile(fullfile(matlabroot,'extern','examples','refbook','matrixMultiply.c'),'.')
サンプル ファイルは読み取り専用ファイルです。サンプルを変更する場合は、次のように入力してファイルが書き込み可能であることを確認します。
fileattrib('matrixMultiply.c','+w')
MEX ファイルをビルドするには、以下を入力します。
mex -v -R2017b matrixMultiply.c -lmwblas
MEX ファイルを実行するには、以下を入力します。
A = [1 3 5; 2 4 7]; B = [-5 8 11; 3 9 21; 4 0 8]; X = matrixMultiply(A,B)
X = 24 35 114 30 52 162
入力値の変更からの保全
LAPACK および BLAS 関数の多くは渡された引数の値を変更します。変更され得る引数は、これらの関数に渡す前にコピーしておくことをお勧めします。MATLAB での関数 mexFunction
に対する引数の処理方法の詳細については、入出力パラメーターの管理を参照してください。
matrixDivide
の例
この例では、LAPACK 関数 dgesv
を呼び出します。この関数は入力引数を変更します。この例のコードは、prhs[0]
および prhs[1]
をコピーし、そのコピーを関数 dgesv
に渡して入力引数の内容を保存します。
例を表示するには、MATLAB エディターで matrixDivide.c
を開きます。MEX ファイルを作成するには、書き込み可能なフォルダーにソース ファイルをコピーします。
copyfile(fullfile(matlabroot,'extern','examples','refbook','matrixDivide.c'),'.')
次を入力してファイルをビルドします。
mex -v -R2017b matrixDivide.c -lmwlapack
以下を入力してテストします。
A = [1 2; 3 4]; B = [5; 6]; X = matrixDivide(A,B)
X = -4.0000 4.5000
C/C++ プログラムから Fortran 関数への引数の受け渡し
LAPACK および BLAS の関数は Fortran で書かれています。C/C++ と Fortran は関数間の引数の受け渡しに異なる規則を使用します。Fortran 関数は参照によって引数を渡しますが、C/C++ 関数は値によって引数を渡します。値で渡すときは、値のコピーを渡します。参照で渡すときは、値のポインターを渡します。参照とは、値のアドレスのことでもあります。
LAPACK や BLAS の関数のような Fortran のサブルーチンを、C/C++ プログラムから呼び出す場合は、引数を参照で渡すことに注意してください。参照渡しを行うには、引数が既に参照である場合を除き、引数の前にアンパサンド (&
) を付けます。たとえば、関数 mxGetDoubles
を使用して行列を作成する場合、その行列への参照を作成しますが、その引数の前にアンパサンドは必要ありません。
以下のコード スニペットでは、変数 m
、n
、p
、one
および zero
には、参照にするための &
文字が必要です。変数 A
、B
、C
および chn
はポインターで、これらは参照です。
/* pointers to input & output matrices*/ double *A, *B, *C; /* matrix dimensions */ mwSignedIndex m,n,p; /* other inputs to dgemm */ char *chn = "N"; double one = 1.0, zero = 0.0; /* call BLAS function */ dgemm(chn, chn, &m, &n, &p, &one, A, &m, B, &p, &zero, C, &m);
matrixMultiply
の例
サンプル matrixMultiply.c
は、すべての引数を参照で渡して dgemm
を呼び出します。ソース コードを表示するには、MATLAB エディターで matrixMultiply.c
を開きます。この例のビルドと実行については、BLAS 関数を使用した matrixMultiply MEX 関数のビルドを参照してください。
Fortran プログラムから Fortran 関数への引数の受け渡し
Fortran MEX ファイルから LAPACK と BLAS の関数を呼び出すことができます。次の例では 2 つの行列を受け取り、BLAS ルーチン dgemm
を呼び出してそれらの乗算を行います。この例を実行するには、エディターにコードをコピーして、ファイルの名前を calldgemm.F
とします。
#include "fintrf.h" subroutine mexFunction(nlhs, plhs, nrhs, prhs) mwPointer plhs(*), prhs(*) integer nlhs, nrhs mwPointer mxcreatedoublematrix mwPointer mxgetpr mwPointer A, B, C mwSize mxgetm, mxgetn mwSignedIndex m, n, p mwSize numel double precision one, zero, ar, br character ch1, ch2 ch1 = 'N' ch2 = 'N' one = 1.0 zero = 0.0 A = mxgetpr(prhs(1)) B = mxgetpr(prhs(2)) m = mxgetm(prhs(1)) p = mxgetn(prhs(1)) n = mxgetn(prhs(2)) plhs(1) = mxcreatedoublematrix(m, n, 0.0) C = mxgetpr(plhs(1)) numel = 1 call mxcopyptrtoreal8(A, ar, numel) call mxcopyptrtoreal8(B, br, numel) call dgemm(ch1, ch2, m, n, p, one, %val(A), m, + %val(B), p, zero, %val(C), m) return end
関数 dgemm
をもつ BLAS ライブラリにリンクします。
mex -v -R2017b calldgemm.F -lmwblas
UNIX システム上での関数名の変更
LAPACK 関数または BLAS 関数を UNIX® システム上で呼び出す場合は、関数名の後にアンダースコアを追加します。たとえば、dgemm
を呼び出すには、以下を使用します。
dgemm_(arg1, arg2, ..., argn);
または以下の行をソース コードに追加します。
#if !defined(_WIN32) #define dgemm dgemm_ #endif