使用 matlab 探查器探查 mex 函数
您可以使用 matlab® 探查器来探查 matlab coder™ 生成的 mex 函数的执行时间。所生成代码的探查文件显示对应 matlab 函数的调用次数和运行每行代码所花费的时间。使用探查器可识别产生耗时最长的生成代码的 matlab 代码行。这些信息可以帮助您在开发周期的早期确定和更正性能问题。有关 matlab 探查器的详细信息,请参阅 和。
matlab online™ 不支持探查器的图形界面。
生成 mex 探查文件
您可以将 matlab 探查器与生成的 mex 函数结合使用。如果您有调用您的 matlab 函数的测试文件,也可以一步生成 mex 函数并对其进行探查。您可以在命令行上或 matlab coder app 中执行这些操作。
要将探查器与生成的 mex 函数结合使用,请执行以下操作:
通过将配置对象属性
enablemexprofiling
设置为true
启用 mex 探查。您也可以将
codegen
与-profile
选项结合使用。matlab coder app 中的等效设置是 generate 步骤中的 enable execution profiling。
生成 mex 文件
myfunction_mex
。运行 matlab 探查器,并查看探查摘要报告,该报告将在单独窗口中打开。
profile on; myfunction_mex; profile viewer;
确保您没有更改或移动原始 matlab 文件
myfunction.m
。否则,探查器不会将myfunction_mex
视为探查对象。
如果您有调用您的 matlab 函数的测试文件 myfunctiontest.m
,您可以:
通过将
codegen
与-test
和-profile
选项结合使用,一步生成 mex 函数并对其进行探查。如果您以前打开过 matlab 探查器,请在结合使用这两个选项之前将其关闭。codegen myfunction -test myfunctiontest -profile
通过在 app 的 verify 步骤中选择 enable execution profiling 来探查 mex 函数。如果您以前打开过 matlab 探查器,请在执行此操作之前将其关闭。
示例
您使用探查器来识别产生耗时最长的生成代码的函数或 matlab 代码行。下面是 matlab 函数的示例,该函数在一个代码行中将其输入矩阵 a
和 b
的表示从行优先布局转换为列优先布局。对于大型矩阵,这种转换需要很长的执行时间。通过修改特定代码行来避免这种转换会使函数更加高效。
以 matlab 函数为例:
function [y] = myfunction(a,b) %#codegen % generated code uses row-major representation of matrices a and b coder.rowmajor; length = size(a,1); % summing absolute values of all elements of a and b by traversing over the % matrices row by row sum_abs = 0; for row = 1:length for col = 1:length sum_abs = sum_abs abs(a(row,col)) abs(b(row,col)); end end % calling external c function 'foo.c' that returns the sum of all elements % of a and b sum = 0; sum = coder.ceval('foo',coder.ref(a),coder.ref(b),length); % returning the difference of sum_abs and sum y = sum_abs - sum; end
为该函数生成的代码使用方阵 a
和 b
的行优先表示。该代码首先通过逐行遍历矩阵来计算 sum_abs
(a
和 b
的所有元素的绝对值之和)。该算法针对以行优先布局方式表示的矩阵进行了优化。然后,代码使用 coder.ceval
调用外部 c 函数 foo.c
:
#include#include #include "foo.h" double foo(double *a, double *b, double length) { int i,j,s; double sum = 0; s = (int)length; /*summing all the elements of a and b*/ for(i=0;i
对应的 c 头文件 foo.h
是:
#include "rtwtypes.h" double foo(double *a, double *b, double length);
foo.c
返回变量 sum
,它是 a
和 b
的所有元素的总和。函数 foo.c
的性能与矩阵 a
和 b
以行优先布局还是列优先布局表示无关。myfunction
返回 sum_abs
和 sum
的差值。
您可以针对大型输入矩阵 a
和 b
测量 myfunction
的性能,然后进一步对该函数进行优化:
对
myfunction
启用 mex 探查并生成 mex 代码。对两个大型随机矩阵a
和b
运行myfunction_mex
。查看探查摘要报告。a = rand(20000); b = rand(20000); codegen myfunction -args {a,b} foo.c foo.h -profile profile on; myfunction_mex(a,b); profile viewer;
将打开单独的窗口,显示探查摘要报告。
探查摘要报告显示 mex 文件及其子文件(为原始 matlab 函数生成的代码)的总时间和自用时间。
在 function name 下,点击第一个链接查看为
myfunction
生成的代码的探查详细信息报告。您可以查看耗时最多的代码行:调用
coder.ceval
的代码行需要很长时间(16.914 秒)。此代码行的执行时间很长,因为coder.ceval
将矩阵a
和b
的表示从行优先布局转换为列优先布局,然后将其传递给外部 c 函数。您可以通过在coder.ceval
中使用附加参数-layout:rowmajor
来避免此转换:sum = coder.ceval('-layout:rowmajor','foo',coder.ref(a),coder.ref(b),length);
使用修改后的
myfunction
再次生成 mex 函数和探查。a = rand(20000); b = rand(20000); codegen myfunction -args {a,b} foo.c foo.h -profile profile on; myfunction_mex(a,b); profile viewer;
myfunction
的探查详细信息报告显示,调用coder.ceval
的代码行现在只需 0.653 秒:
折叠表达式对 mex 代码覆盖率的影响
当您使用 coder.const
将表达式折叠成常量时,会导致 matlab 函数和 mex 函数的代码覆盖率不同。以如下函数为例:
function y = myfoldfunction %#codegen a = 1; b = 2; c = a b; y = 5 coder.const(c); end
探查 matlab 函数 myfoldfunction
会在探查详细信息报告中显示以下代码覆盖率:
但是,探查 mex 函数 myfoldfunction_mex
会显示不同的代码覆盖率:
生成的代码中不会执行第 2、3 和 4 行,因为您已将表达式 c = a b
折叠成常量以进行代码生成。
此示例使用用户定义的表达式折叠。代码生成器有时会自动折叠某些表达式,以优化生成代码的性能。这种优化还导致 mex 函数的覆盖率不同于 matlab 函数。
另请参阅
| codegen
| | | |