Можно разработать библиотеку замены кода для операций умножения матрицы/матрицы с плавающей запятой и матрицы/вектора с помощью функций умножения. dgemm и dgemv определено в библиотеке MathWorks BLAS. Если для замены используется библиотека BLAS стороннего производителя, необходимо изменить требования к сборке в этом примере, чтобы указать на библиотеку. Для разработки библиотеки замены кода используйте интерактивный или программный подход. Дополнительные сведения см. в разделе Разработка библиотеки замены кода.
Откройте инструмент замены кода (crtool) в командной строке MATLAB с помощью следующей команды:
>>crtool
Создайте таблицу.
В контекстном меню crtool выберите «Файл» > «Новая таблица».
На правой панели присвойте таблице имя crl_table_blas. Нажмите кнопку «Применить».
Создайте запись. В контекстном меню crtool выберите File > New entry > Blas Operation (Fortran).
Создание параметров записи. В раскрывающемся списке «Функция» выберите Multiply.
Создайте концептуальное представление. Концептуальное представление описывает подпись функции, которую требуется заменить. В подразделе «Концептуальная функция» crtool укажите возвращаемый аргумент. y1и входной аргумент, u1 и u2 с типом данных Double и типом аргумента матрицы.
Создайте представление реализации. Представление реализации описывает сигнатуру функции оптимизации. Для этого примера, чтобы указать, что аргументы реализации имеют тот же порядок и те же свойства, что и концептуальные аргументы, установите флажок Сделать концептуальный и аргумент реализации типами одного и того же типа. Установите уровень BLAS на 2(Vector).
Укажите имя для функции замены в разделе Прототип функции.
Укажите сведения о построении. Щелкните вкладку Сведения о построении, чтобы открыть панель требований к построению. Укажите файлы (источник, заголовок, объект), необходимые генератору кода для замены кода. В этом примере нет необходимости указывать информацию о построении.
Проверьте и сохраните таблицу. На вкладке Информация о сопоставлении щелкните Проверить запись. В контекстном меню crtool выберите «Файл» > «Сохранить таблицу» > «Сохранить».

Зарегистрируйте библиотеку замены кода. При регистрации создается библиотека, состоящая из указанных таблиц. Выберите «Файл» > «Создать файл регистрации». В диалоговом окне Создать файл регистрации заполните следующие поля:

Чтобы использовать библиотеку замены кода, обновите текущий сеанс MATLAB с помощью команды:
>>sl_refresh_customizations
Проверьте библиотеку замены кода. В командной строке MATLAB откройте библиотеку с помощью средства просмотра замены кода и убедитесь, что таблица и запись указаны правильно. Дополнительные сведения см. в разделе Проверка библиотеки замены кода. Настройте модель так, чтобы она использовала библиотеку замены кода, создавала код и проверяла, что замена происходит так, как ожидалось. Если происходит непредвиденное поведение, проверьте попадание и пропустите журналы, чтобы устранить неполадки.
Откройте программный интерфейс в меню MATLAB, выбрав Создать > Функция.
Создайте таблицу.
Создайте функцию для вызова таблицы библиотеки замены кода. Функция не должна иметь аргументов и возвращать объект таблицы.
Создание объекта таблицы путем вызова RTW.TflTable.
function hTable = crl_table_blas % Create a function to call the code replacement library table %% Create a table object hTable = RTW.TflTable;
Создайте запись. Поскольку этот пример заменяет функцию, создайте запись замены кода в таблице, вызвав функцию записи. RTW.TflBlasEntryGenerator.
function hTable = crl_table_blas % Create a code replacement library table %% Create a table object hTable = RTW.TflTable; %% Create an entry %%%%%%%%%%%% Define library path for Windows or UNIX block%%%%%%%%%%%%%%%%%% arch = computer('arch'); if ~ispc LibPath = fullfile('$(MATLAB_ROOT)', 'bin', arch); else % Use Stateflow to get the compiler info compilerInfo = sf('Private','compilerman','get_compiler_info'); compilerName = compilerInfo.compilerName; if strcmp(compilerName, 'msvc90') || ... strcmp(compilerName, 'msvc80') || ... strcmp(compilerName, 'msvc71') || ... strcmp(compilerName, 'msvc60'), ... compilerName = 'microsoft'; end LibPath = fullfile('$(MATLAB_ROOT)', 'extern', 'lib', arch, compilerName); end if ispc libExt = 'lib'; elseif ismac libExt = 'dylib'; else libExt = 'so'; end %%%%%%Beginning of entries for the first dgemm block%%%%%%%%%%%%%%%%%% % Create table entry for dgemm32 hEntry = RTW.TflBlasEntryGenerator;
Создание параметров записи. Поскольку эти примеры заменяют функцию, создайте параметры записи, вызвав функцию setTflCFunctionEntryParameters.
function hTable = crl_table_blas % Create a code replacement library table %% Create a table object hTable = RTW.TflTable; %% Create an entry %%%%%%%%%%%% Define library path for Windows or UNIX block%%%%%%%%%%%%%%%%%% arch = computer('arch'); if ~ispc LibPath = fullfile('$(MATLAB_ROOT)', 'bin', arch); else % Use Stateflow to get the compiler info compilerInfo = sf('Private','compilerman','get_compiler_info'); compilerName = compilerInfo.compilerName; if strcmp(compilerName, 'msvc90') || ... strcmp(compilerName, 'msvc80') || ... strcmp(compilerName, 'msvc71') || ... strcmp(compilerName, 'msvc60'), ... compilerName = 'microsoft'; end LibPath = fullfile('$(MATLAB_ROOT)', 'extern', 'lib', arch, compilerName); end if ispc libExt = 'lib'; elseif ismac libExt = 'dylib'; else libExt = 'so'; end %%%%%%Beginning of entries for the first dgemm block%%%%%%%%%%%%%%%%%% % Create table entry for dgemm32 hEntry = RTW.TflBlasEntryGenerator; %% Create entry parameters setTflCOperationEntryParameters(hEntry, ... 'Key', 'RTW_OP_MUL', ... 'Priority', 100, ... 'ImplementationName', 'dgemm32', ... 'ImplementationHeaderFile', 'blascompat32_crl.h', ... 'ImplementationHeaderPath', fullfile('$(MATLAB_ROOT)','extern','include'), ... 'AdditionalLinkObjs', {['libmwblascompat32.' libExt]}, ... 'AdditionalLinkObjsPaths', {LibPath}, ... 'SideEffects', true);
Создайте концептуальное представление. Концептуальное представление описывает подпись функции, которую требуется заменить. Чтобы явно указать свойства аргумента, вызовите функцию createAndAddConceptualArg. Чтобы указать аргумент матрицы в вызове функции, используйте класс аргументов RTW.TflArgMatrix и укажите базовый тип и размеры, для которых допустим аргумент. Этот тип записи таблицы поддерживает диапазон измерений, заданных в формате [Dim1Min Dim2Min ... DimNMin; Dim1Max Dim2Max ... DimNMax]. Например, [2 2; inf inf] означает двумерную матрицу размером 2x2 или больше. Концептуальный выходной аргумент для записи dgemm32 для замены умножения матрицы/матрицы определяет размеры [2 2; inf inf], в то время как концептуальный выходной аргумент для dgemv32 запись для замены матричного/векторного умножения задает размеры [2 1; inf 1].
function hTable = crl_table_blas % Create a code replacement library table %% Create a table object hTable = RTW.TflTable; %% Create an entry %%%%%%%%%%%% Define library path for Windows or UNIX block%%%%%%%%%%%%%%%%%% arch = computer('arch'); if ~ispc LibPath = fullfile('$(MATLAB_ROOT)', 'bin', arch); else % Use Stateflow to get the compiler info compilerInfo = sf('Private','compilerman','get_compiler_info'); compilerName = compilerInfo.compilerName; if strcmp(compilerName, 'msvc90') || ... strcmp(compilerName, 'msvc80') || ... strcmp(compilerName, 'msvc71') || ... strcmp(compilerName, 'msvc60'), ... compilerName = 'microsoft'; end LibPath = fullfile('$(MATLAB_ROOT)', 'extern', 'lib', arch, compilerName); end if ispc libExt = 'lib'; elseif ismac libExt = 'dylib'; else libExt = 'so'; end %%%%%%Beginning of entries for the first dgemm block%%%%%%%%%%%%%%%%%% % Create table entry for dgemm32 hEntry = RTW.TflBlasEntryGenerator; %% Create entry parameters setTflCOperationEntryParameters(hEntry, ... 'Key', 'RTW_OP_MUL', ... 'Priority', 100, ... 'ImplementationName', 'dgemm32', ... 'ImplementationHeaderFile', 'blascompat32_crl.h', ... 'ImplementationHeaderPath', fullfile('$(MATLAB_ROOT)','extern','include'), ... 'AdditionalLinkObjs', {['libmwblascompat32.' libExt]}, ... 'AdditionalLinkObjsPaths', {LibPath}, ... 'SideEffects', true); %% Create the conceptual representation createAndAddConceptualArg(hEntry, 'RTW.TflArgMatrix', ... 'Name', 'y1', ... 'IOType', 'RTW_IO_OUTPUT', ... 'BaseType', 'double', ... 'DimRange', [2 2; inf inf]); createAndAddConceptualArg(hEntry, 'RTW.TflArgMatrix', ... 'Name', 'u1', ... 'BaseType', 'double', ... 'DimRange', [2 2; inf inf]); createAndAddConceptualArg(hEntry, 'RTW.TflArgMatrix', ... 'Name', 'u2', ... 'BaseType', 'double', ... 'DimRange', [1 1; inf inf]);
Создайте представление реализации. Представление реализации описывает сигнатуру функции оптимизации. Чтобы указать, что аргументы реализации имеют тот же порядок и свойства, что и концептуальные аргументы, вызовите функцию getTflArgFromString. В примере кода настраиваются специальные аргументы реализации, необходимые для dgemm и dgemv замены функций. Методы удобства setReturn и addArgument укажите, является ли аргумент возвращаемым значением или аргументом, и добавьте аргумент к массиву аргументов реализации элемента. Добавление полной записи в таблицу путем вызова функции addEntry.
function hTable = crl_table_blas % Create a code replacement library table %% Create a table object hTable = RTW.TflTable; %% Create an entry %%%%%%%%%%%% Define library path for Windows or UNIX block%%%%%%%%%%%%%%%%%% arch = computer('arch'); if ~ispc LibPath = fullfile('$(MATLAB_ROOT)', 'bin', arch); else % Use Stateflow to get the compiler info compilerInfo = sf('Private','compilerman','get_compiler_info'); compilerName = compilerInfo.compilerName; if strcmp(compilerName, 'msvc90') || ... strcmp(compilerName, 'msvc80') || ... strcmp(compilerName, 'msvc71') || ... strcmp(compilerName, 'msvc60'), ... compilerName = 'microsoft'; end LibPath = fullfile('$(MATLAB_ROOT)', 'extern', 'lib', arch, compilerName); end if ispc libExt = 'lib'; elseif ismac libExt = 'dylib'; else libExt = 'so'; end %%%%%%Beginning of entries for the first dgemm block%%%%%%%%%%%%%%%%%% % Create table entry for dgemm32 hEntry = RTW.TflBlasEntryGenerator; %% Create entry parameters setTflCOperationEntryParameters(hEntry, ... 'Key', 'RTW_OP_MUL', ... 'Priority', 100, ... 'ImplementationName', 'dgemm32', ... 'ImplementationHeaderFile', 'blascompat32_crl.h', ... 'ImplementationHeaderPath', fullfile('$(MATLAB_ROOT)','extern','include'), ... 'AdditionalLinkObjs', {['libmwblascompat32.' libExt]}, ... 'AdditionalLinkObjsPaths', {LibPath}, ... 'SideEffects', true); %% Create the conceptual representation createAndAddConceptualArg(hEntry, 'RTW.TflArgMatrix', ... 'Name', 'y1', ... 'IOType', 'RTW_IO_OUTPUT', ... 'BaseType', 'double', ... 'DimRange', [2 2; inf inf]); createAndAddConceptualArg(hEntry, 'RTW.TflArgMatrix', ... 'Name', 'u1', ... 'BaseType', 'double', ... 'DimRange', [2 2; inf inf]); createAndAddConceptualArg(hEntry, 'RTW.TflArgMatrix', ... 'Name', 'u2', ... 'BaseType', 'double', ... 'DimRange', [1 1; inf inf]); %% Create the Implementation Representation % Using RTW.TflBlasEntryGenerator for xgemm requires the following % implementation signature: % % void f(char* TRANSA, char* TRANSB, int* M, int* N, int* K, % type* ALPHA, type* u1, int* LDA, type* u2, int* LDB, % type* BETA, type* y, int* LDC) % % When a match occurs, the code generator computes the % values for M, N, K, LDA, LDB, and LDC and inserts them into the % generated code. TRANSA and TRANSB are set to 'N'. % Specify replacement function signature arg = getTflArgFromString(hTable, 'y2', 'void'); arg.IOType = 'RTW_IO_OUTPUT'; hEntry.Implementation.setReturn(arg); arg = RTW.TflArgCharConstant('TRANSA'); % Possible values for PassByType property are % RTW_PASSBY_AUTO, RTW_PASSBY_POINTER, % RTW_PASSBY_VOID_POINTER, RTW_PASSBY_BASE_POINTER arg.PassByType = 'RTW_PASSBY_POINTER'; hEntry.Implementation.addArgument(arg); arg = RTW.TflArgCharConstant('TRANSB'); arg.PassByType = 'RTW_PASSBY_POINTER'; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'M', 'integer', 0); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'N', 'integer', 0); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'K', 'integer', 0); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'ALPHA', 'double', 0); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'u1', ['double' '*']); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'LDA', 'integer', 0); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'u2', ['double' '*']); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'LDB', 'integer', 0); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'BETA', 'double', 0); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'y1', ['double' '*']); arg.IOType = 'RTW_IO_OUTPUT'; arg.PassByType = 'RTW_PASSBY_POINTER'; hEntry.Implementation.addArgument(arg); arg = getTflArgFromString(hTable, 'LDC', 'integer', 0); arg.PassByType = 'RTW_PASSBY_POINTER'; arg.Type.ReadOnly = true; hEntry.Implementation.addArgument(arg); %% Add the entry to the table addEntry(hTable, hEntry);
Укажите сведения о построении. В параметрах ввода укажите файлы (заголовок, источник, объект), необходимые генератору кода для замены кода. Для этого примера информация о построении не требуется.
Проверьте и сохраните файл настройки. В меню MATLAB сохраните этот файл настройки, выбрав «Файл» > «Сохранить». В командной строке проверьте таблицу библиотеки замены кода, вызвав ее:
>> hTable = crl_table_blas
Зарегистрируйте библиотеку замены кода. Регистрация создает библиотеку замены кода, определяя имя библиотеки, таблицы замены кода и другую информацию. Создайте файл регистрации со следующими спецификациями:
function rtwTargetInfo(cm) cm.registerTargetInfo(@loc_register_crl); end function this = loc_register_crl this(1) = RTW.TflRegistry; this(1).Name = 'CRL for matrix multiplication for Mathworks Blas code’; this(1).TableList = {'crl_table_blas.m'}; % table created in this example this(1).TargetHWDeviceType = {'*'}; this(1).Description = 'Example code replacement library'; end
Чтобы использовать библиотеку замены кода, обновите текущий сеанс MATLAB с помощью команды:
>>sl_refresh_customizations
Проверьте библиотеку замены кода. В командной строке MATLAB откройте библиотеку с помощью средства просмотра замены кода и убедитесь, что таблица и запись указаны правильно. Дополнительные сведения см. в разделе Проверка библиотеки замены кода. Настройте модель так, чтобы она использовала библиотеку замены кода, создавала код и проверяла, что замена происходит так, как ожидалось. Если происходит непредвиденное поведение, проверьте попадание и пропустите журналы, чтобы устранить неполадки.