Main Content

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

参考

|