Matlab系列之运行程序的分析+程序调试+程序优化

程序分析

前言

不知道大家对System Generator系列中的资源分析以及时序分析的功能是否还有印象,这两个分析功能会将各模块所消耗的资源以及耗时都展现出来,用于资源或时序的优化,本篇将要记录的内容也与之有点相似,使用特定的功能或者语句对程序进行分析,然后得到各函数的耗时以及被调用次数等信息,最后再根据这些信息对程序进行优化,接下来就使用MATLAB提供的这两种方法来进行程序分析,下一篇再对程序优化和程序调试做介绍。

 

第一种方法

使用一个工具——Profiler,这个工具是MATLAB中的一个图形用户接口,可以用于分析程序运行时各个部分所消耗的时间,可以从以下几个方面提供程序运行信息:

1)避免由于疏忽造成的非必要操作。

2)替换运行较慢的算法,选择快速算法。

3)通过存储变量的方式避免重复计算。

接下来说下使用Profiler进行程序运行分析的步骤:

1)查看Profiler生成的通体报告,查找运行时间最多的函数或调用最频繁的函数。

2)查看这些函数的详细报告,查找其中运行时间最多的语句或调用最频繁的语句。

3)确定运行时间最多的函数或代码是否存在改进的可能。

4)单击界面链接,打开相应文件进行修改。

5)重复进行上述的分析、修改,直至优化出满意的结果。

 

Profiler的使用介绍

1)打开方式

第一个打开的地方在主页->代码->运行并计时。

Matlab系列之运行程序的分析+程序调试+程序优化_第1张图片

第二个打开的地方在编辑器->运行->运行并计时,要看到这个功能的前提就是需要打开一个M文件。

Matlab系列之运行程序的分析+程序调试+程序优化_第2张图片

第三个打开方式就是直接在命令行窗口输入:profile viewer

以上的三种打开方式都可以打开一个探查器的窗口,也就是Profiler的界面,在“运行此代码”中输入需要分析的命令或表达式,然后点“启动探查”,就会开始对其进行分析。

Matlab系列之运行程序的分析+程序调试+程序优化_第3张图片

使用一串代码进行探查测试:[t,y] = ode23('lotka',[0 2],[20;20])

点击开始探查后,会出现如下结果,红色框中的就是所探查的程序运行的信息名称:

Matlab系列之运行程序的分析+程序调试+程序优化_第4张图片

单击图中的蓝色字体,点的是红色框所选择的名称则会进行排序,点的是函数名称一栏中的函数,则会进入其内部观察更加详细的分析报告,这份报告中含有该函数中的每行代码的被调用次数和运行时间,以及子函数、函数列表等等,可以简单看下图的内容,此外,如果点击图中红色框里的蓝色字体,则会将此时的结果保存至新的窗口(该窗口会自动弹出),可以用于程序优化后与之对比,然后分析得到较优的结果。

Matlab系列之运行程序的分析+程序调试+程序优化_第5张图片

=============================

注意:如果你一直点开始探查,在命令行窗口也有运行代码,但是就是没探查摘要出来,别慌,跟着下面的几张图改一下字体的预设即可解决。

Matlab系列之运行程序的分析+程序调试+程序优化_第6张图片

================================

第二种方法

这个方法可以说是更加简单易懂,直接在需要计时的部分前后放置计时函数的开始和结束即可,即:计时器的开始—tic,计时器的结束—toc。

因此使用的语法就是这样子的了:

tic

       %需计时的程序代码

toc

t=toc%将记得的时间进行保存

注:如果计时的程序过于简单,计时误差会相对比较大,大家可以自己使用该种方法,然后对比结果分析下。



Matlab系列之运行程序的分析

更多精彩等你发现!



程序优化

一般来说,实现同样的功能,可以采用不同的编程方法,而这些不同的编程方法也可能有着不同的运行速度,因此很多时候需要找到较优的那种方法,从而提高代码的运行效率,本篇将要记录的是一些提供M文件执行速度、优化内存管理的常用方法,具体的记录两个很实用的方法,然后简单再说下其他的方法,在平常编程的时候注意并学会使用这些方法,请往下慢慢看~

第一种

不知道你们在使用MATLAB进行循环计算的时候,有没有感觉到过,对矩阵的单个元素作循环相比将其转化成向量的形式进行运算的速度要慢很多,如果没太理解这句话,可以看以下的代码,然后再回过来理解:

%程序1,矩阵的元素作循环

clear all

clc

tic

x=1;

for k=1:1001

    y(k)=log10(x)

    x=x+0.01;

end

toc

结果:

Matlab系列之运行程序的分析+程序调试+程序优化_第7张图片

 

%程序2,矩阵元素向量化

clear all

clc

tic

x=1:0.01:11;

y=log10(x)

toc

结果:

Matlab系列之运行程序的分析+程序调试+程序优化_第8张图片

 

以上这两个代码只是分别对x进行循环累加以及直接向量化赋值给x,但是得到的运行速度却相差如此之大,当然这也是因为我把结果打印在了命令行窗口中,不然第一种的速度也还会快很多,那样的说服力显然没有这个强了,所以,你get到这个优化程序的操作了吗?

 

第二种

此处要记录的第二种方法很好理解,可以这样想象,一个人去做一件事,这件事是他从未接触过的,其结果也是无法预测的,那么他会感觉到实现起来很困难,最终实现的时间也是漫长的,但是如果这个人很清楚的知道自己要做的事,知道实现的方法,那么就可以很高效的完成这件事。

类推,在for循环和while循环中,一个数组的大小随着循环不断的增加,很显然这会影响内存的使用效率,因为只要数组的维度变了,就要找到更大的连续内存区域,用于存放新的数组,就像是那个做事的人在不断尝试不同的方法去实现要做的事,很费时间,但是我们在最开始就给数组设置好一个它最终结果所需的恒定维度,也就是提前分配内存,这样就可以很好的提高内存使用效率,相当于直接给了做事的人一个正确的方法,他只需要照着做就行,很显然效率要高很多。

 

接下来上几个简单的代码,来进一步加深内存预分配的印象:

%原始代码

x=0;

for k=2:1000

    x(k)=x(k-1)+6;

end

%预分配内存后的代码

x=zeros(1,1000);

for k=2:1000

    x(k)=x(k-1)+6;

end


不知道你们发现没有,在编完原代码后,MATLAB其实会提醒你需要预分配内存,把鼠标移到x的波浪线上,就会出现:

Matlab系列之运行程序的分析+程序调试+程序优化_第9张图片

 

预分配内存的方法,本处代码使用的是zeros函数,将x的所有元素都赋值为0,这样节约了重新分配内存的时间,从而提高程序的效率,除了这个函数以外,还有cell函数也可以,不过这两个分别用于对数值数组和单元数组进行内存分配,不过要注意一点,使用zeros函数为数组分配内存时,如果数组类型要的不是double,则需要做些改变,可以使用下面的语句进行分配:

A=zeros(100,’int8’);

%这个就相当于为A分配了100*100的int8类型的内存。

A=int8(zeros(100));

%这个更好理解,就是生成了一个100x100的double类型的内存,再使用int8函数将其转化为int8的类型。

 

其他方法

这部分的方法都是比较好理解的,在平常编程前,记住这些要点,然后编写的时候应用上,可以简单有效的对程序进行优化。

1)数组赋值时,避免数组类型的改变、以及第二种方法说的数组大小改变

2)对实数进行操作,尽量避免对复数操作,复数也可以分实部虚部分别进行处理。

3)合理使用逻辑运算符

4)避免重载MATLAB中的内置函数和操作符

5)通常情况下,函数的运行效率要高于脚本文件

6)load和save函数效率要高于文件写和读取的操作

7)多重循环的时候,可以在外运行循环次数少的,在内运行循环次数多的



Matlab系列之程序优化

 



程序调试

学完了程序优化,再来个程序调试,关于MATLAB的编程基础我觉得也就差不多可以了,之后应该就是对数组、矩阵进行更加具体的操作,对数学函数进一步的了解等等,之后可以算是对MATLAB的进阶了吧,突然有点期待之后的记录了,不过先把本篇做好记录更重要点。

正文

程序为何需要调试呢?不知道你们想过这个问题没有,或者说遇到相关的处理时,有没有将其归类于程序调试。MATLAB程序中的错误包括语法错误和逻辑错误,语法错误是编译器会自动检测的,特别是代码标红处,就是代码对应的位置有红色波浪线的下划线,将鼠标光标移到标红处,可以显示出错误内容的提示,还有一种就是橙色的波浪形下划线,这种代表此处语法正确,但是,其他位置的代码有可能会因此产生错误,所以产生了橙色的下划线用于警示。在编程的时候,注意编译器的提示,可以避免大部分的语法错误,特别是函数名错误或者变量名错误之类的,这些在运行的时候更是直接在窗口提示错误,直接更改后就可重新运行。

 

以上讲的都是关于语法的错误,修改起来也比较方便,但是逻辑错误就比较麻烦了,调试也会困难很多,因为它的影响因素有点多,有可能是算法本身的问题,也可能是指令使用不当造成的运行结果错误。但是相比于盲目的去更改自我认为的“错误”,使用一些调试的方法去检测并修改错误的代码块,不香吗?

 

所以开始本篇的正题,讲讲程序调试的方法,通常是有两种方法:直接调试法和利用MATLAB调试工具进行调试。

1、直接调试法

直接调试法比较适用于简单的程序,或者说是简洁的程序,在调试的时候,程序运行中的变量的值是一个很重要的线索,但是在函数调用时只返回最后的输出变量,而不返回中间变量,所以可以采用以下的几种方法将中间变量显示出来进行查看:

1)通过简单的分析,将可能出错的语句后面的分号“;”删掉,使得该行的结果可以直接显示在命令行窗口中,与期望值进行比较。

2)直接使用disp函数显示中间变量的值

3)在程序中合适的位置加keyboard指令,可以使得MATLAB运行到该处的时候,会暂停,直到使用者做出反应,在暂停的时候,命令行窗口原本的“>>”会变成“K>>”,使用者可以查看此时工作区的变量,可以改变变量的值,也可以输入return指定返回程序(用于函数),继续执行。

4)在调试单独的函数时,可以先将函数弄成脚本文件,直接对输入变量赋值,然后运行M文件,这样的话,可以将中间变量都保存在工作区,然后运行完,能够查看全部中间变量的值,从而分析结果,找到错误的位置。

 

2、工具调试法

刚刚讲到的调试方法对简单的程序比较适用,当程序的规模比较大的时候,就可以使用MATLAB自带的调试工具进行调试,从而提高编程的效率,我的是MATLAB R2019b的版本,调试的工具栏,也就是打开M文件时,显示的编辑器的右边的部分。

Matlab系列之运行程序的分析+程序调试+程序优化_第10张图片

注意的调试操作如下:

1)设置或清除断点,可以单击“断点”按钮,然后进行相应的操作,也可以直接单击需要设置断点的位置的左侧行号旁边的“-”,然后会出现一个红色的圆点,再次点击就可以删除该断点。

2)设置或修改条件断点,条件断点是一种特殊的断点,只有当满足了指定的条件时,程序执行到此处就会暂停,但是条件不满足,程序就会继续运行,就比如if-else-end的语句,如果满足if的条件,就会进入if下的代码区,如果此区域有断点,就会在断点处停下,如果不满足就跳过,因此if下代码区的断点就不会影响程序的运行。

3)启用或禁用当前行的断点,如果当前行不存在断点,则设置当前行为断点;如果当前行为断电,就改变当前的断点的状态为禁用状态,这个时候的断点会有个叉叉在红色圆圈上,在调试的时候,被禁用的断点将会被忽略。

此外,在调试的时候,变量的值因为是找错误的重要线索,所以需要知道调试过程中,查看变量值的方法:

(1)在编辑器中,将鼠标光标移到待查看的变量上,然后此处就会显示该变量的值。

(2)在工作区查看该变量的值。

(3)在命令行窗口输入该变量的名称,然后其值就会打印到窗口中。

总之,在实际编程的时候,根据不同的情况,有针对性的使用这些功能,可以很大的提高调试效率以及编程效率。



Matlab系列之程序调试

更多精彩等你发现!



 

你可能感兴趣的:(MATLAB)