再呼び出し可能なコードの呼び出し — 永続データを使用したマルチスレッド (UNIX のみ)
この例は POSIX スレッド (pthread) ライブラリが必要なので、UNIX® プラットフォームでのみ動作します。これは永続データを使用するマルチスレッドの例です。2 つのスレッドによって、異なる入力データセットをもつ MATLAB® 関数 matrix_exp
が呼び出されます。
この例の MATLAB コード
function [Y,numTimes] = matrix_exp(X) %#codegen % % The function matrix_exp computes matrix exponential % of the input matrix using Taylor series and returns % the computed output. It also returns the number of % times this function has been called. % persistent count; if isempty(count) count = 0; end count = count+1; E = zeros(size(X)); F = eye(size(X)); k = 1; while norm(E+F-E,1) > 0 E = E + F; F = X*F/k; k = k+1; end Y = E ; numTimes = count; |
main 関数の記述
永続データを使用する再呼び出し可能なコードを呼び出すには、次を実行する main
関数を記述します。
ヘッダー ファイル
matrix_exp.h
を含める。各スレッドに対し、スタック データのためのメモリを割り当てる。
スレッドでデータを共有する場合はルート プロセスごとに、それ以外の場合はスレッドごとに、永続データにメモリを割り当てる。
ハウスキーピング関数
matrix_exp_initialize
を呼び出す。詳細については、生成コードの展開を参照してください。matrix_exp
を呼び出す。matrix_exp_terminate
を呼び出す。スタック データおよび永続データに使用されたメモリを解放する。
この例では、main.c
には次が含まれます。
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include "matrix_exp.h" #include "matrix_exp_initialize.h" #include "matrix_exp_terminate.h" #include "rtwtypes.h" #define NUMELEMENTS (160*160) typedef struct { real_T in[NUMELEMENTS]; real_T out[NUMELEMENTS]; real_T numTimes; matrix_expStackData* spillData; } IODATA; /*The thread_function calls the matrix_exp function written in MATLAB*/ void *thread_function(void *dummyPtr) { IODATA *myIOData = (IODATA*)dummyPtr; matrix_exp_initialize(myIOData->spillData); matrix_exp(myIOData->spillData, myIOData->in, myIOData->out, &myIOData>numTimes); printf("Number of times function matrix_exp is called is %g\n",myIOData->numTimes); matrix_exp_terminate(); } int main() { pthread_t thread1, thread2; int iret1, iret2; IODATA data1; IODATA data2; int32_T i; /*Initializing data for passing to the 2 threads*/ matrix_expPersistentData* pd1 = (matrix_expPersistentData*)calloc(1,sizeof(matrix_expPersistentData)); matrix_expPersistentData* pd2 = (matrix_expPersistentData*)calloc(1,sizeof(matrix_expPersistentData)); matrix_expStackData* sd1 = (matrix_expStackData*)calloc(1,sizeof(matrix_expStackData)); matrix_expStackData* sd2 = (matrix_expStackData*)calloc(1,sizeof(matrix_expStackData)); sd1->pd = pd1; sd2->pd = pd2; data1.spillData = sd1; data2.spillData = sd2; for (i=0;i<NUMELEMENTS;i++) { data1.in[i] = 1; data1.out[i] = 0; data2.in[i] = 1.1; data2.out[i] = 0; } data1.numTimes = 0; data2.numTimes = 0; /*Initializing the 2 threads and passing required data to the thread functions*/ printf("Starting thread 1...\n"); iret1 = pthread_create(&thread1, NULL, thread_function, (void*) &data1); if (iret1 != 0){ perror("Thread 1 creation failed."); exit(EXIT_FAILURE); } printf("Starting thread 2...\n"); iret2 = pthread_create(&thread2, NULL, thread_function, (void*) &data2); if (iret2 != 0){ perror( "Thread 2 creation failed."); exit(EXIT_FAILURE); } /*Wait for both the threads to finish execution*/ iret1 = pthread_join(thread1, NULL); if (iret1 != 0){ perror( "Thread 1 join failed."); exit(EXIT_FAILURE); } iret2 = pthread_join(thread2, NULL); if (iret2 != 0){ perror( "Thread 2 join failed."); exit(EXIT_FAILURE); } free(sd1); free(sd2); free(pd1); free(pd2); printf("Finished Execution!\n"); return(0); } |
再呼び出し可能な C コードの生成
コードを生成するには、次のスクリプトを MATLAB コマンド プロンプトで実行します.
% This example can only be run on Unix platforms if ~isunix error('This example requires pthread libraries and can only be run on Unix.'); end % Setting the options for the Config object % Specify an ERT target cfg = coder.config('exe'); % Enable reentrant code generation cfg.MultiInstanceCode = true; % Set the post code generation command to be the 'setbuildargs' function cfg.PostCodeGenCommand = 'setbuildargs(buildInfo)'; % Compiling codegen -config cfg main.c -report matrix_exp.m -args ones(160,160) |
このスクリプトは、以下の処理を実行します。
例が UNIX プラットフォーム上で実行されない場合、エラー メッセージを生成します。
実行可能ファイルの生成用にコード生成構成オブジェクトを作成します。
再利用可能で再呼び出し可能なコードを生成する
MultiInstanceCode
オプションを有効にします。コード生成後のコマンドを関数
setbuildargs
に設定するPostCodeGenCommand
オプションを使用します。この関数は-lpthread
フラグを設定し、ビルドに pthread ライブラリが含まれるように指定します。function setbuildargs(buildInfo) % The example being compiled requires pthread support. % The -lpthread flag requests that the pthread library % be included in the build linkFlags = {'-lpthread'}; addLinkFlags(buildInfo, linkFlags);
詳細は、ビルド プロセスのカスタマイズを参照してください。
次のオプションを使用して
codegen
を呼び出します。-config
: コード生成構成オブジェクトcfg
を渡します。main.c
: このファイルをコンパイルに含めます。-report
: コード生成レポートを作成します。-args
: クラス、サイズ、実数/複素数をもつサンプル入力を指定します。
生成されたコードの検査
codegen
によって、次を定義するヘッダー ファイル matrix_exp_types.h
が生成されます。
大きすぎてスタックに収まらないローカル変数および
matrix_expStackData
グローバル構造体へのポインターが含まれるmatrix_expPersistentData
グローバル構造体永続データが含まれる
matrix_expPersistentData
グローバル構造体
/* * matrix_exp_types.h * * Code generation for function 'matrix_exp' * */ #ifndef __MATRIX_EXP_TYPES_H__ #define __MATRIX_EXP_TYPES_H__ /* Include files */ #include "rtwtypes.h" /* Type Definitions */ #ifndef typedef_matrix_expPersistentData #define typedef_matrix_expPersistentData typedef struct { double count; } matrix_expPersistentData; #endif /*typedef_matrix_expPersistentData*/ #ifndef typedef_matrix_expStackData #define typedef_matrix_expStackData typedef struct { struct { double F[25600]; double Y[25600]; double X[25600]; } f0; matrix_expPersistentData *pd; } matrix_expStackData; #endif /*typedef_matrix_expStackData*/ #endif /* End of code generation (matrix_exp_types.h) */ |
コードの実行
次のコマンドを使用してコードを呼び出します。
system('./matrix_exp')