В этом примере требуются библиотеки, специфичные для операционной системы 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, которая определяет:
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.exe')Использование пространства стека элементов управления | Распределение стека и производительность