再呼び出し可能なコードの呼び出し — 永続データを使用したマルチスレッド (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')