Main Content

本页的翻译已过时。点击此处可查看最新英文版本。

通过生成 MEX 函数加快 MATLAB 算法的执行速度

您可以使用 MATLAB® Coder™ 从 MATLAB 代码生成 MEX 函数。MEX 函数是一个 MATLAB 可执行文件。它是可以从 MATLAB 内部调用的生成代码。在 MATLAB 环境内工作时,使用 MEX 函数可加快 MATLAB 代码的计算密集型部分的执行速度。通过使用 MATLAB Coder App 或在 MATLAB 命令行中使用 codegen,从您的 MATLAB 代码生成一个 MEX 函数。

在本教程中,您将使用 MATLAB Codercodegen 命令为 MATLAB 函数生成 MEX 函数。首先,您需要生成一个 MEX 函数,该函数只能接受具有预分配的固定大小的输入。然后生成另一个 MEX 函数,该函数可以接受具有许多不同大小的输入。

教程文件

将教程文件从文件夹 matlabroot\help\toolbox\coder\examples\euclidean 复制到本地工作文件夹。此处,matlabroot 是 MATLAB 安装文件夹,例如 C:\Program Files\MATLAB\R2019a。要将这些文件复制到您的当前文件夹,请运行以下 MATLAB 命令:

copyfile(fullfile(matlabroot,'help','toolbox','coder','examples','euclidean'))
本地工作文件夹不能为私有文件夹或 @ 文件夹。本教程使用 euclidean_data.mateuclidean.mtest.mtest_2d.mbuild_mex_fixed.mbuild_mex_variable.m 文件。

  • MATLAB 数据文件 euclidean_data.mat 包含两段数据:三维欧几里德空间中的一个点以及三维欧几里德空间中的一组其他点。更具体地说:

    • x 是一个 3×1 列向量,表示三维欧几里德空间中的一个点。

    • cb 是一个 3×216 数组。cb 中的每列都表示三维欧几里德空间中的一个点。

  • MATLAB 文件 euclidean.m 包含 euclidean 函数,该函数在本示例中实现核心算法。该函数接受 xcb 作为输入。它计算 xcb 中每个点之间的欧几里德距离,并返回以下量:

    • 列向量 y_min,它等于 cb 中表示与 x 距离最近的点的列。

    • 列向量 y_max,它等于 cb 中表示与 x 距离最远的点的列。

    • 二维向量 idx,它包含 cb 中向量 y_miny_max 的列索引。

    • 二维向量 distance,它包含计算出的到 x 的最小和最大距离。

    function [y_min,y_max,idx,distance] = euclidean(x,cb)
    % Initialize minimum distance as distance to first element of cb
    % Initialize maximum distance as distance to first element of cb
    idx(1)=1;
    idx(2)=1;
    
    distance(1)=norm(x-cb(:,1));
    distance(2)=norm(x-cb(:,1));
    
    % Find the vector in cb with minimum distance to x
    % Find the vector in cb with maximum distance to x
    for index=2:size(cb,2)
        d=norm(x-cb(:,index));
        if d < distance(1)
            distance(1)=d;
            idx(1)=index;
        end
        if d > distance(2)
            distance(2)=d;
            idx(2)=index;
        end
    end
    
    % Output the minimum and maximum distance vectors
    y_min=cb(:,idx(1));
    y_max=cb(:,idx(2));
    
    end
  • MATLAB 脚本 test.m 将数据文件 euclidean_data.mat 加载到工作区中。它调用函数 euclidean 计算 y_miny_maxidxdistance。然后,脚本在命令行中显示计算出的量。

    加载 euclidean_data.mat 是在调用核心算法之前执行的预处理步骤。显示结果是后处理步骤。

    % Load test data 
    load euclidean_data.mat
    
    % Determine closest and farthest points and corresponding distances
    [y_min,y_max,idx,distance] = euclidean(x,cb);
    
    % Display output for the closest point
    disp('Coordinates of the closest point are: ');
    disp(num2str(y_min'));
    disp(['Index of the closest point is ', num2str(idx(1))]);
    disp(['Distance to the closest point is ', num2str(distance(1))]);
    
    disp(newline);
    
    % Display output for the farthest point
    disp('Coordinates of the farthest point are: ');
    disp(num2str(y_max'));
    disp(['Index of the farthest point is ', num2str(idx(2))]);
    disp(['Distance to the farthest point is ', num2str(distance(2))]);
  • MATLAB 脚本 test_2d.m 是表示二维欧几里德空间中点的 test.m 的修改版。test_2d.m 的内容将在本教程后面显示,您可以使用它来针对可变大小输入测试 MEX 函数。

  • 编译脚本 build_mex_fixed.mbuild_mex_variable.m 包含的命令可从您的 MATLAB 代码生成静态 C 库,这两个库分别接受固定大小和可变大小输入。这些脚本的内容显示在本教程后面有关生成 C 代码的部分中。

提示

您可以使用 MATLAB Coder 从 MATLAB 函数生成代码。不支持从 MATLAB 脚本生成代码。

请使用测试脚本将预处理和后处理步骤与实现核心算法的函数分隔开。这种做法使您能够轻松地重用您的算法。您需要为实现核心算法的 MATLAB 函数生成代码。不需要为测试脚本生成代码。

MATLAB 函数生成 MEX 函数

运行原始 MATLAB 代码

在 MATLAB 中运行测试脚本 test.m。输出显示 yidxdistance

Coordinates of the closest point are: 
0.8         0.8         0.4
Index of the closest point is 171
Distance to the closest point is 0.080374


Coordinates of the farthest point are: 
0  0  1
Index of the farthest point is 6
Distance to the farthest point is 1.2923

使 MATLAB 代码适用于代码生成

为了使您的 MATLAB 代码适用于代码生成,您可以使用代码分析器和代码生成就绪工具。MATLAB 编辑器中的代码分析器会在您输入代码时持续检查代码。它会报告问题,并提出修改建议,以最大程度地提高性能和可维护性。代码生成就绪工具会筛查 MATLAB 代码中是否存在代码生成不支持的功能和函数。

C/C++ 代码生成支持的某些 MATLAB 内置函数和工具箱函数、类以及 System object 有特定的代码生成限制。这些限制和相关使用说明列在其对应参考页的扩展功能部分。有关详细信息,请参阅 C/C++ 代码生成支持的函数和对象

  1. 在 MATLAB 编辑器中打开 euclidean.m。MATLAB 编辑器右上角的代码分析器消息指示标记为绿色。分析器未在代码中检测到错误、警告或改进机会。

  2. 在函数声明后面添加 %#codegen 指令:

    function [y,idx,distance] = euclidean(x,cb) %#codegen
    %#codegen 指令提示代码分析器识别特定于代码生成的警告和错误。

    代码分析器消息指示标记变为红色,表示它检测到代码生成问题。

  3. 要查看警告消息,请将光标移到带下划线的代码片段上。警告指示,代码生成要求先对变量 idxdistance 进行完全定义,然后才可以对它们进行下标索引。出现此警告是因为代码生成器必须在这些变量在代码中首次出现时确定其大小。要解决此问题,请使用 ones 函数同时分配和初始化这些数组。

    % Initialize minimum distance as distance to first element of cb
    % Initialize maximum distance as distance to first element of cb
    idx = ones(1,2);
    
    distance = ones(1,2)*norm(x-cb(:,1));

    代码分析器消息指示标记再次变为绿色,表示它没有再检测到任何代码生成问题。

    有关使用代码分析器的详细信息,请参阅检查代码中的错误和警告

  4. 保存文件。

  5. 要运行代码生成就绪工具,请从 MATLAB 命令行调用 coder.screener 函数:

    coder.screener('euclidean')

    该工具不会检测 euclidean 的任何代码生成问题。有关详细信息,请参阅Code Generation Readiness Tool

    MATLAB Online™ 不支持代码生成就绪工具。

    注意

    代码分析器和代码生成就绪工具可能无法检测到所有代码生成问题。消除这两个工具检测到的错误或警告后,使用 MATLAB Coder 生成代码以确定您的 MATLAB 代码是否还存在其他合规性问题。

现在您即可使用 MATLAB Coder App 编译您的代码。此处,编译指从您的 MATLAB 代码生成 C/C++ 代码。

注意

编译 MATLAB 代码指从 MATLAB 代码生成 C/C++ 代码。在其他情况下,“编译”可能指 C/C++ 编译器的操作。

定义输入类型

由于 C 使用静态类型,因此在代码生成时(也称为编译时),代码生成器必须确定 MATLAB 文件中所有变量的类、大小和复/实性。因此,在为文件生成代码时,必须指定入口函数的所有输入参数的属性。入口函数是顶层 MATLAB 函数,您可以从中生成代码。

当您使用 codegen 命令生成代码时,请使用 -args 选项指定入口函数的示例输入参数。代码生成器使用这些信息来确定输入参数的属性。

在下一步中,您将使用 codegen 命令从入口函数 euclidean 生成 MEX 文件。

生成并验证 MEX 函数

编译脚本 build_mex_fixed.m 包含用于为 euclidean.m 生成和验证 MEX 函数的命令。要验证 MEX 函数,请运行测试脚本 test,并将调用 MATLAB 函数 euclidean 替换为调用生成的 MEX 函数。

% Load the test data
load euclidean_data.mat
% Generate code for euclidean.m with codegen. Use the test data as example input. Validate MEX by using test.m.
codegen -report euclidean.m -args {x, cb} -test test
请注意:

  • 默认情况下,codegen 在当前文件夹中生成名为 euclidean_mex 的 MEX 函数。

  • -report 选项指示 codegen 生成代码生成报告,您可使用该报告调试代码生成问题,并验证您的 MATLAB 代码是否适用于代码生成。

  • -args 选项指定入口函数 euclidean 的示例输入参数。代码生成器使用这些信息来确定输入参数的类、大小和复/实性。

  • 您使用 -test 选项运行测试文件 test.m。此选项将测试文件中对 euclidean 的调用替换为对 euclidean_mex 的调用。

有关代码生成选项的详细信息,请参阅 codegen

  1. 运行编译脚本 build_mex_fixed.m

    代码生成器在当前工作文件夹中生成 MEX 函数 euclidean_mex

    输出为:

    Code generation successful: View report.
    Running test file: 'test' with MEX function 'euclidean_mex'.
    Coordinates of the closest point are: 
    0.8         0.8         0.4
    Index of the closest point is 171
    Distance to the closest point is 0.080374
    
    
    Coordinates of the farthest point are: 
    0  0  1
    Index of the farthest point is 6
    Distance to the farthest point is 1.2923
    此输出与原始 MATLAB 函数生成的输出相匹配,并验证 MEX 函数。

  2. 要在 Report Viewer 中查看代码生成报告,请点击 View report

    如果代码生成器在代码生成过程中检测到错误或警告,报告将说明问题并提供有问题的 MATLAB 代码的链接。请参阅Code Generation Reports

提示

在命令行使用编译脚本生成代码。编译脚本自动执行您在命令行重复执行的一系列 MATLAB 命令,可帮助您节省时间和消除输入错误。

为可变大小输入生成 MEX 函数

您为 euclidean.m 生成的 MEX 函数只能接受与您在代码生成期间指定的样本输入具有相同大小的输入。但是,对应的 MATLAB 函数的输入数组可以具有任意大小。在本教程的此部分,您将从 euclidean.m 中生成接受可变大小输入的 MEX 函数。

假设您希望生成的 MEX 函数中的 xcb 的维度具有以下属性:

  • xcb 的第一个维度的大小为可变大小,但不超过 3

  • x 的第二个维度具有固定大小,其值为 1

  • cb 的第二个维度的大小为可变大小,但不超过 216

要指定这些输入属性,请使用 coder.typeof 函数。coder.typeof(A,B,1) 指定一个可变大小的输入,其类和复/实性与 A 相同,其上限由大小向量 B 的对应元素给出。使用编译脚本 build_mex_variable.m,该脚本使用 coder.typeof 在生成的 MEX 函数中指定可变大小输入的属性。

% Load the test data
load euclidean_data.mat

% Use coder.typeof to specify variable-size inputs
eg_x=coder.typeof(x,[3 1],1);
eg_cb=coder.typeof(cb,[3 216],1);

% Generate code for euclidean.m using coder.typeof to specify
% upper bounds for the example inputs
codegen -report euclidean.m -args {eg_x,eg_cb}

您可以验证新 MEX 函数 euclidean_mex 是否接受不同于 xcb 的维度输入。测试脚本 test_2d.m 创建输入数组 x2dcb2d,它们分别是 xcb 的二维版本。然后,它使用这些输入参数调用 MATLAB 函数 euclidean

% Load the test data
load euclidean_data.mat

% Create 2-D versions of x and cb
x2d=x(1:2,:);
cb2d=cb(1:2,1:6:216);

% Determine closest and farthest points and corresponding distances
[y_min,y_max,idx,distance] = euclidean(x2d,cb2d);

% Display output for the closest point
disp('Coordinates of the closest point are: ');
disp(num2str(y_min'));
disp(['Index of the closest point is ', num2str(idx(1))]);
disp(['Distance to the closest point is ', num2str(distance(1))]);

disp(newline);

% Display output for the farthest point
disp('Coordinates of the farthest point are: ');
disp(num2str(y_max'));
disp(['Index of the farthest point is ', num2str(idx(2))]);
disp(['Distance to the farthest point is ', num2str(distance(2))]);

运行 test_2d.m 会生成以下输出:

Coordinates of the closest point are: 
0.8         0.8
Index of the closest point is 29
Distance to the closest point is 0.078672


Coordinates of the farthest point are: 
0  0
Index of the farthest point is 1
Distance to the farthest point is 1.1357

要运行测试脚本 test_2d.m 并将对 euclidean 的调用替换为对 euclidean_mex 的调用,请使用 coder.runTest

coder.runTest('test_2d','euclidean')
输出与原始 MATLAB 函数生成的输出相匹配。这证明新 MEX 函数可以接受不同于 xcb 的维度输入。

接下来的步骤

目的更多信息

了解对 MATLAB 内置函数和工具箱函数、类和 System object 的代码生成支持

C/C++ 代码生成支持的函数和对象

生成 C++ MEX 代码

C++ 代码生成

以交互方式创建和编辑输入类型

Create and Edit Input Types by Using the Coder Type Editor

优化所生成的代码的执行速度或内存使用量。

优化策略

了解代码生成报告

Code Generation Reports

在 MATLAB 探查器中查看生成的 MEX 函数的执行时间和代码覆盖率

使用 MATLAB 探查器探查 MEX 函数

另请参阅

| |