В этом примере требуются библиотеки, специфичные для Microsoft® Windows® операционная система и, следовательно, работает только на платформах Windows. Это многопоточный пример, в котором используются постоянные данные. Два потока вызывают MATLAB® функциональные matrix_exp
с различными наборами входных данных.
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
функция, которая:
Включает заголовочный файл matrix_exp.h
.
Для каждого потока выделяет память для данных стека.
Выделяет память для стойких данных, один раз на корневой процесс, если потоки совместно используют данные, и один раз на поток в противном случае.
Вызывает matrix_exp_initialize
функции домашнего хозяйства. Дополнительные сведения см. в разделе Развертывание сгенерированного кода.
Вызовы matrix_exp
.
Вызовы matrix_exp_terminate
.
Освобождает память, используемую для стека и стойких данных.
В данном примере main.c
содержит:
#include <stdio.h> #include <stdlib.h> #include <windows.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*/ DWORD WINAPI thread_function(PVOID 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(); return 0; } void main() { HANDLE thread1, thread2; 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"); thread1 = CreateThread(NULL, 0, thread_function, (PVOID) &data1, 0, NULL); if (thread1 == NULL){ perror( "Thread 1 creation failed."); exit(EXIT_FAILURE); } printf("Starting thread 2...\n"); thread2 = CreateThread(NULL, 0, thread_function, (PVOID) &data2, 0, NULL); if (thread2 == NULL){ perror( "Thread 2 creation failed."); exit(EXIT_FAILURE); } /*Wait for both the threads to finish execution*/ if (WaitForSingleObject(thread1, INFINITE) != WAIT_OBJECT_0){ perror( "Thread 1 join failed."); exit(EXIT_FAILURE); } if (WaitForSingleObject(thread2, INFINITE) != WAIT_OBJECT_0){ perror( "Thread 2 join failed."); exit(EXIT_FAILURE); } free(sd1); free(sd2); free(pd1); free(pd2); printf("Finished Execution!\n"); exit(EXIT_SUCCESS); } |
Запустите следующий скрипт в командной строке MATLAB, чтобы сгенерировать код.
% This example can only be run on Windows platforms if ~ispc error... ('This example requires Windows-specific libraries and can only be run on Windows.'); 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; % Compiling codegen -config cfg main.c -report matrix_exp.m -args ones(160,160) |
Этот скрипт:
Генерирует сообщение об ошибке, если пример не работает на платформе Windows.
Создает объект строения генерации кода для генерации исполняемого файла.
Включает MultiInstanceCode
опция для генерации переиспользуемого, повторно входящего кода.
Призывает codegen
со следующими опциями:
-config
для прохождения в объекте строения генерации кода cfg
.
main.c
чтобы включить этот файл в компиляцию.
-report
для создания отчета генерации кода.
-args
чтобы задать вход примера с классом, размером и сложностью.
codegen
генерирует заголовочный файл matrix_exp_types.h
, который определяет:
The matrix_expStackData
глобальная структура, содержащая локальные переменные, которые являются слишком большими для размещения в стеке, и указатель на matrix_expPersistentData
глобальная структура.
The 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.exe')
Управление использованием пространства стека | Распределение стека и эффективность