MATLAB m语言编程风格
MATLAB是解释型语言,存在计算速度慢地问题。MATLAB提供以下几种方法分析程序的运行状况:
1. Profiler工具
在MATLAB的Start菜单中可以找到其快捷方式,用于查找花费时间较多的代码行位置。
2. 使用tic和toc函数查看运行时间
3. 对于运行时间比较短的程序,可以循环多次运行,使用tic和toc查看总的运行时间,然后计算出一次运行所花费的时间。
改善MATLAB运行效率的方法有以下几种:
一、循环矢量化
MATLAB是一个矩阵语言,是为矢量和矩阵操作设计的,可以通过矢量化方法来加速m文件的运行。矢量化指的是将for循环和while循环转换为等价的矢量或矩阵操作。例如,下面的程序
i = 0;
for t = 0:0.01:10
i = i + 1;
y(i) = sin(t);
end
矢量化以后为:
t = 0:0.01:10;
y= sin(t);
使用tic和toc函数测试,两端程序都循环运行100次,所用时间分别为:
Elapsed time is 0.125000 seconds.
Elapsed time is 0.031000 seconds.
MATLAB中的有些函数内部已经采用了矢量化处理,这些函数包括
all any cumsum diff find ind2sub ipermute logical ndgrid
permute prod repmat reshape shiftdim sort squeeze sub2ind sum
二、数组的内存预分配
1. 给数组预分配内存
可以通过给保存输出结果的数组预分配内存空间来改善代码的运行效率。预分配使得不必在每次数组变大时改变。不同类型的数组使用的预分配函数如下:
数值数组:zeors;
单元数组:cell;
结构数组:struct; repmat
使用大型矩阵时,预分配可以减少内存碎片。MATLAB在给一个变量分配内存时,需要查找连续的内存空间。进行动态的内存分配合取消分配时,内存空间会出现碎片,将导致大量无法使用的闲置内存产生。
2. 给非double型矩阵预分配内存
给double型以外的矩阵预分配一个内存块时,使用repmat函数的效果更佳。
下面的语句使用zeros函数预分配一个unit8型的100×100的矩阵。首先,创建一个double型满秩矩阵,然后把矩阵转换为uint8型。
A = int8(zeros(1000, 1000));
使用repmat函数,只需要创建一个double值,减少了对内存的需求
A = repmat(int8(0), 100, 100);
三、使用MEX文件编写循环代码
如果必须使用循环,则把它写成mex文件。由于不必再每次运行循环中的语句时都对它们解释,因此运行会更快。
四、变量赋值时注意两点
首先,改变已有的变量的数据类型或数组形状会使程序运行速度减慢,因为这需要额外的时间进行处理。需要保存不同类型的数据时,建议创建新的变量。
其次,如果一个变量已经赋给了实数或复数,现在又赋给它复数或实数会影响运行速度。
五、操作实型数据的函数
MATLAB为操作实型数特意设计了一些函数,包括reallog, reallpow,和realsqrt等。
六、使用合适的逻辑运算符
进行逻辑AND或逻辑OR时,有两种选择
&, | 对数组进行逐元素的逻辑AND或逻辑OR比较
&&, || 对标量进行逻辑AND或逻辑OR比较
在if和while语句中,使用&&, ||更有效。因为在两个运算符不一定计算整个表达式。
七、避免重载内部函数
八、函数比脚本运行更快
每次使用脚本时都要把它装入内存,然后逐行执行;而函数则被编译为P代码,只装入内存一次。
九、将大的GUI应用编译为p代码
MATLAB的建议如下:
MATLAB is very fast at parsing so the pcode function rarely makes much of a speed difference.
One situation where pcode does provide a speed benefit is for large GUI applications. In this case, many M-files must be parsed before the application becomes visible
十、使用load函数和save函数比MATLAB文件I/O过程更好
十一、 在一行m语言中只写一个语句
MATLAB m语言中调用simulink的程序
1. 打开simulink模型的几种方式
% 打开文件对话框
[FileName, PathName, FilterIndex] = uigetfile({'*.mdl','Model-files (*.mdl)'}, '打开');
if FileName ~= 0
% 加载模型
load_system([PathName, FileName]);
end
% 新建一个模型
new_system('untitled', 'Model');
% 打开一个仿真模型
open_system([PathName, FileName]);
2. 获取当前simulink的文件信息并显示
% 获取当前模型名称
set(handles.ModelNameEdit, 'String', get_param(gcs, 'Name'));
% 获取当前模型文件名称即文件路径
set(handles.SourceFileEdit, 'String', get_param(gcs, 'FileName'));
% 获取当前模型创建的时间
set(handles.CreatedOnEdit, 'String', get_param(gcs, 'Created'));
% 获取当前模型最近一次修改的时间
set(handles.LastSaveOnEdit, 'String', get_param(gcs, 'LastModifiedDate'));
% 获取当前simulink的版本
set(handles.VersionEdit, 'String', get_param(gcs, 'Version'));
%获取当前模型的版本
set(handles.ModelVersionEdit, 'String', get_param(gcs, 'ModelVersion'));
3. 查找当前模型的所有block及对应的所有对话框参数
% 查找当前模型中的所有模块,为了方便,首先显示顶层模块,再显示其他层
BlocksTop = find_system(get(handles.ModelNameEdit, 'String'), 'SearchDepth', 1, 'Type', 'block');
BlocksAll = find_system(get(handles.ModelNameEdit, 'String'), 'Type', 'block');
AllBlocks = [BlocksTop; setdiff(BlocksAll, BlocksTop)];
% 显示所有参数,参数名称以struct的数据结构显示
ParameterStruct = get_param(Block,'DialogParameters');
% 参数struct结构体的域,得到参数的名称,以cell的数据结构显示
Parameters = fieldnames(ParameterStruct);
% 获取第一个参数的值
ParameterValue = get_param(Block, Parameters{1});
% 获取参数值类型
ValueStruct = ParameterStruct.(Parameters{1}) ;
ParameterType = ValueStruct.Type;
% 参数值的提示信息
ParameterPrompt = ValueStruct.Prompt;
ParameterEnum = ValueStruct.Enum;
ParameterAttributes = ValueStruct.Attributes;
4. 修改某个参数的值
% 获取编辑框中的修改值
ChangedValue = get(handles.ParameterValueEdit, 'String');
try
% 尝试保存修改
set_param(Block, Parameter, ChangedValue);
catch
% 修改失败,弹出提示信息
errordlg([{['无法将', Block, ' 的 ', Parameter, '参数值修改为 ', ChangedValue]}; {'输入的参数值有误,请重新输入!'}], '错误', 'on');
% 恢复原来的值
set(handles.ParameterValueEdit, 'String', get_param(Block, Parameter));
end
5. 查询模型中某些特点类型的block
% 查找当前模块中的subsystem
SubSystems = find_system(gcs, 'Type', 'block');
% 查找所有的Scope
AllScope = find_system(gcs, 'BlockType', 'Scope');
% 查找所有的ToFile
AllToFile = find_system(gcs, 'BlockType', 'ToFile');
% 查找所有的ToWorkSpace
AllToWorkSpace = find_system(gcs, 'BlockType', 'ToWorkspace');