相见恨晚的Matlab编程小技巧(3)-程序运行太慢了咋解决——合理使用循环语句(1)

简介: 相信大家在使用matlab时候经常会收到程序运行太慢的困扰,当程序比较复杂时,常常需要很长时间等待。我有个朋友就是这样,每次debug都要很长时间,等着的时候就想耍会手机,结果耍完一抬头发现程序运行结束了,但时间已经过去半天了。        一般来说,程序运行太慢都是因为循环的存在,使用双层甚至多层循环会使得程序运行效率极低。这篇博客将重点介绍如何在Matlab中避免使用循环语句并提高程序效率。我们将深入讨论向量化运算、预分配空间和相关函数(cellfun、arrayfun和structfun等)的用法,同时配有详细的示例代码和解释,帮助大家更好地掌握这些技术和优化方法。

       相信大家在使用matlab时候经常会收到程序运行太慢的困扰,当程序比较复杂时,常常需要很长时间等待。我有个朋友就是这样,每次debug都要很长时间,等着的时候就想耍会手机,结果耍完一抬头发现程序运行结束了,但时间已经过去半天了。

       一般来说,程序运行太慢都是因为循环的存在,使用双层甚至多层循环会使得程序运行效率极低。这篇博客将重点介绍如何在Matlab中避免使用循环语句并提高程序效率。我们将深入讨论向量化运算、预分配空间和相关函数(cellfun、arrayfun和structfun等)的用法,同时配有详细的示例代码和解释,帮助大家更好地掌握这些技术和优化方法。

1.记录程序运行时间

       为了比较使用循环语句与否对程序运行时间的影响,我们需要用到matlab中的tic,toc语句,tic函数表示开始计时。执行tic语句后,程序就会记录下当前时间。接下来的代码运行时,而程序会在toc函数调用时输出自tic函数到当前时刻所经过的时间。例如:

tic    % 开始计时
% 模块代码
x = 1:10000000;
y = sin(x);
disp(y(1:10));
toc    % 打印出程序自tic调用以来经过的时间

image.gif

       运行结果:

image.gif

        如果你不想在命令行输出运行时间,也可以将程序运行时间存在变量中,避免在命令行输出,例如:

tic    % 开始计时
% 模块代码
x = 1:10^8;
y = sin(x);
time0=toc;    % 将程序自tic调用以来经过的时间存在变量time0中

image.gif

image.gif

2.向量化运算

       为了提高程序性能,我们可以使用向量化运算来避免循环,同时实现对向量中所有元素的操作。向量化运算是一种在Matlab中广泛使用的高效操作方式,它可以对整个向量或矩阵进行运算,而不需要使用循环。具体来说,向量化运算使用内部优化的编译器,通过单个指令完成多个元素的处理,因此能够大大提高程序的效率。在Matlab中,常用的向量化运算符包括 .*, ./, .^, .', .*,等。具体的用法如表1所示:

表1 向量化运算符号的用法

运算符 用法 说明
.* A .* B A 数组和 B 数组中对应元素逐个相乘
./ A ./ B A 数组和 B 数组中对应元素逐个相除
.^ A .^ B A 数组和 B 数组中对应元素逐个做幂运算
.* A .* B B 对应 A 的每一列进行元素相乘运算

       首先举一个简单的例子来介绍如何使用向量化运算来代替循环语句。假设有两个矩阵 x 和 y,都包含500×500×500个元素,现在你想将它们每个元素相乘,然后将乘积相加。如果如果使用循环语句,可以这样写代码:

tic
x=rand(500,500,500);
y=rand(500,500,500);
c = 0;
for k = 1:500
    for kk = 1:500
        for kkk = 1:500
            c = c + x(k,kk,kkk) * y(k,kk,kkk);
        end
    end
end
toc

image.gif

       运行时间需要11.25秒。

image.gif

       如果你使用向量化操作,代码会更加简单,运行时间也会更短:

tic
x=rand(500,500,500);
y=rand(500,500,500);
c = sum(x(:) .* y(:));
toc

image.gif

image.gif

        运行只要2.46秒,快了不止一点点,在这个例子中,x(:)和y(:)表示将矩阵x用一维向量的形式表示。x(:) .* y(:)表示将一维向量化之后的 x 和 y 中对应元素相乘,并得到一个新的向量化,然后使用 sum 函数对这个新向量求和,从而得到我们想要的结果。显然,使用向量操作代替循环,代码更简洁、更易读、更易扩展。当处理大型数据集时,向量操作也可以大大提高程序运行速度。

3.预分配空间

       大家在使用Matlab编程时应该都看到过类似这样的警告:

image.gif

       这是在Matlab中,如果你想把一个新的元素添加到数组中,并且数组的大小没有指定或无法确定时,Matlab会重新分配整个数组并复制现有元素,这个过程会导致程序效率下降。当我们不得不使用循环语句时,我们也需要在使用变量前预分配空间。如果我们想在循环中构建一个数组时,你可以在循环之前预先分配数组空间,然后在循环中直接修改数组元素。这样做可以大大减少程序的运行时间和内存消耗。例如:

tic
x=rand(2000,2000);
y=rand(2000,2000);
for k = 1:2000
    for kk = 1:2000
        c(k,kk) = x(k,kk) * y(k,kk);
    end
end
toc

image.gif

        上面的代码没有预分配内存,所需运行时间为4.45秒。如果在for循环之前初始化变量c,代码这样写:

tic
x=rand(2000,2000);
y=rand(2000,2000);
c=zeros(2000,2000);
for k = 1:2000
    for kk = 1:2000
        c(k,kk) = x(k,kk) * y(k,kk);
    end
end
toc

image.gif

image.gif

        运行时间变成了0.2秒。一个不起眼的变量初始化,可以让代码运行速率快这么多。所以,之后编程的过程中,只要遇到循环语句,一定要确保循环内部用到的变量都是预分配内存的。

       这篇博客就先介绍这两种比较常用的方法,还有另一种使用相关函数的方法,我们将在下一篇博客单独进行介绍。

相关文章
|
1月前
|
存储 算法 数据可视化
基于 MATLAB的GUI信号处理界面设计 源码+运行截图
基于 MATLAB的GUI信号处理界面设计 源码+运行截图
58 2
|
1月前
|
监控 算法 数据安全/隐私保护
基于三帧差算法的运动目标检测系统FPGA实现,包含testbench和MATLAB辅助验证程序
本项目展示了基于FPGA与MATLAB实现的三帧差算法运动目标检测。使用Vivado 2019.2和MATLAB 2022a开发环境,通过对比连续三帧图像的像素值变化,有效识别运动区域。项目包括完整无水印的运行效果预览、详细中文注释的代码及操作步骤视频,适合学习和研究。
|
6月前
|
编解码 算法 异构计算
基于FPGA的NC图像质量评估verilog实现,包含testbench和MATLAB辅助验证程序
在Vivado 2019.2和Matlab 2022a中测试的图像质量评估算法展示了效果。该算法基于NC指标,衡量图像与原始图像的相似度,关注分辨率、色彩深度和失真。提供的Verilog代码段用于读取并比较两个BMP文件,计算NC值。
|
2月前
|
监控 算法 安全
基于颜色模型和边缘检测的火焰识别FPGA实现,包含testbench和matlab验证程序
本项目展示了基于FPGA的火焰识别算法,可在多种应用场景中实时检测火焰。通过颜色模型与边缘检测技术,结合HSV和YCbCr颜色空间,高效提取火焰特征。使用Vivado 2019.2和Matlab 2022a实现算法,并提供仿真结果与测试样本。FPGA平台充分发挥并行处理优势,实现低延迟高吞吐量的火焰检测。项目包含完整代码及操作视频说明。
|
4月前
|
数据采集 并行计算 算法
LabVIEW与Matlab联合编程的途径及比较
LabVIEW与Matlab联合编程的途径及比较
74 0
LabVIEW与Matlab联合编程的途径及比较
|
5月前
|
存储 算法 计算机视觉
m基于FPGA的FIR低通滤波器实现和FPGA频谱分析,包含testbench和滤波器系数MATLAB计算程序
在Vivado 2019.2平台上开发的系统,展示了数字低通滤波器和频谱分析的FPGA实现。仿真结果显示滤波效果良好,与MATLAB仿真结果一致。设计基于FPGA的FIR滤波器,利用并行处理和流水线技术提高效率。频谱分析通过离散傅里叶变换实现。提供了Verilog核心程序以示例模块工作原理。
51 4
|
5月前
|
机器学习/深度学习 数据可视化 算法
探索MATLAB世界:掌握基础知识与实用技能(1. MATLAB环境与基本操作 2. 数据类型与变量 3. 条件与循环,1. 数据分析与统计 2. 图像处理与计算机视觉 3. 信号处理与控制系统)
探索MATLAB世界:掌握基础知识与实用技能(1. MATLAB环境与基本操作 2. 数据类型与变量 3. 条件与循环,1. 数据分析与统计 2. 图像处理与计算机视觉 3. 信号处理与控制系统)
53 0
|
6月前
|
机器学习/深度学习 算法
m基于GA-GRU遗传优化门控循环单元网络的电力负荷数据预测算法matlab仿真
在MATLAB 2022a中,一个基于遗传算法优化的GRU网络展示显著优化效果。优化前后的电力负荷预测图表显示了改进的预测准确性和效率。GRU,作为RNN的一种形式,解决了长期依赖问题,而遗传算法用于优化其超参数,如学习率和隐藏层单元数。核心MATLAB程序执行超过30分钟,通过迭代和适应度评估寻找最佳超参数,最终构建优化的GRU模型进行负荷预测,结果显示预测误差和模型性能的提升。
185 4
|
5月前
|
机器学习/深度学习 算法
m基于PSO-GRU粒子群优化长门控循环单元网络的电力负荷数据预测算法matlab仿真
摘要: 在MATLAB 2022a中,对比了电力负荷预测算法优化前后的效果。优化前为"Ttttttt111222",优化后为"Tttttttt333444",明显改进体现为"Tttttttttt5555"。该算法结合了粒子群优化(PSO)和长门控循环单元(GRU)网络,利用PSO优化GRU的超参数,提升预测准确性和稳定性。PSO模仿鸟群行为寻找最优解,而GRU通过更新门和重置门处理长期依赖问题。核心MATLAB程序展示了训练和预测过程,包括使用'adam'优化器和超参数调整,最终评估并保存预测结果。
56 0
|
6月前
|
数据安全/隐私保护
matlab程序,地震波压缩、地震波缩尺、地震波压缩时间,调整时长、时间间隔
地震波格式转换、时程转换、峰值调整、规范反应谱、计算反应谱、计算持时、生成人工波、时频域转换、数据滤波、基线校正、Arias截波、傅里叶变换、耐震时程曲线、脉冲波合成与提取、三联反应谱、地震动参数、延性反应谱、地震波缩尺、功率谱密度