Вызовите повторно используемый код без персистентных или глобальных данных (только UNIX)

Этот пример требует потока POSIX (pthread) библиотеки и, поэтому, запускается только на платформах UNIX®. Это - простой многопоточный пример, который не использует персистентных или глобальных данных. Два потока вызывают функцию MATLAB® matrix_exp с различными наборами входных данных.

Обеспечьте основную функцию

Чтобы вызвать повторно используемый код, обеспечьте функцию main что:

  • Включает заголовочный файл matrix_exp.h 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];
    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();
    matrix_exp(myIOData->spillData, myIOData->in, myIOData->out);
    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_expStackData* sd1=(matrix_expStackData*)calloc(1,sizeof(matrix_expStackData));
    matrix_expStackData* sd2=(matrix_expStackData*)calloc(1,sizeof(matrix_expStackData));
         
    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;
    }
    
    /*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);
    
    printf("Finished Execution!\n");
    exit(EXIT_SUCCESS);
    
}

Сгенерируйте повторно используемый код С

Чтобы сгенерировать код, запустите следующий скрипт в подсказке команды 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

% Create a code gen configuration object
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 matrix_exp.m -report -args ones(160,160)  

Этот скрипт:

  • Генерирует сообщение об ошибке, если пример не работает на платформе UNIX.

  • Создает объект настройки кода для генерации исполняемого файла.

  • Позволяет опции MultiInstanceCode сгенерировать допускающий повторное использование, повторно используемый код.

  • Использует опцию PostCodeGenCommand, чтобы установить команду генерации кода сообщения быть функцией setbuildargs. Эта функция устанавливает флаг -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_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_expStackData
#define typedef_matrix_expStackData

typedef struct {
  struct {
    double F[25600];
    double Y[25600];
    double X[25600];
  } f0;
} matrix_expStackData;

#endif                                 /*typedef_matrix_expStackData*/
#endif

/* End of code generation (matrix_exp_types.h) */

Запустите код

Вызовите код с помощью команды:

system('./matrix_exp')
Исполняемое завершение выполнений и отчетов.

Была ли эта тема полезной?