Matlab高效编程:向量化(vectorization)、矩阵化、变量预定义

这篇具有很好参考价值的文章主要介绍了Matlab高效编程:向量化(vectorization)、矩阵化、变量预定义。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

0. 前言

1. 变量预定义

2. 向量化,vectorization

3. 矩阵化

3.1 离散化

3.2 双重循环实现

3.3 向量化实现

3.4 矩阵化实现


0. 前言

        本文介绍几个Matlab常用的提高运行效率的编程技巧。

        对一个基于数值化的方式计算一个连续函数的频谱(傅里叶变换)的例子给出了三种实现(双重循环、向量化实现、矩阵化实现)代码,对比了运行时间。

1. 变量预定义

        由于Matlab是解释性执行语言,Matlab不要求变量使用之前进行预定义,也不要求内存的预分配,一切都可以在执行过程中动态分配。这种灵活的方式方便了用户编程,但是同时也带来了潜在的低效率问题。

        以下针对一个简单的计算例子,用几种不同的代码实现方式来比较不同的写法对于运行效率的影响。

        代码中用tic 和 toc这两个matlab的基本的定时器函数,来进行运行时间统计。为了避免已分配内存对运行时间的影响,每次新的实现方式的运行之前都用“clearvars”进行内存清除,当然num和freq不需要清除,所以用-except选项将它们保留。

clearvars;
close all;
clc;

num = 1e6;
freq = 0.01; % Normalized frequency

% case1
tic
for k = 1 : num
    sin(2*pi*k*freq);
end
toc

% case2
clearvars -except num freq;
tic
for k = 1 : num
   x(k) = sin(2*pi*k*freq);
end
toc

% case3
clearvars -except num freq;
tic
x = zeros(1,num);
for k = 1 : num
   x(k) = sin(2*pi*k*freq);
end
toc

% case4
clearvars -except num freq;
tic
x = [];
for k = 1 : num/10
   x = [x sin(2*pi*k*freq)];
end
toc

        运行结果如下(Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz,8GB内存,64比特操作系统):

历时 0.204018 秒。
历时 0.223268 秒。
历时 0.076024 秒。
历时 2.713520 秒。 

        case1和case2(差异在于是否用运算结果对x(k)进行显式赋值)运行时间差异不大,这个虽然看上去略微有点奇怪,但是这只是说明了即便是只计算sin(2*pi*k*freq)不显式地对x(k)进行赋值也是需要动态地分配临时内存以存储计算结果的。

        case3相比case1,2快了30倍左右,仅仅是预先对x进行了定义(相应地进行内存分配)而已,就能够有如此巨大的速度提升,可见变量预定义(尤其是大的数组变量)对于高效的Matlab编程有多么重要!

        case4是为了对比给出的一个更为恶劣的例子(惭愧的是,笔者曾很长时间用这种方式实现动态数组增长,模拟python中的list.append()的行为。。。故此特地将它作为反面教材举出)。主要它在运行循环数是其它几种情况的十分之一的条件下,甚至比case1和case2都还要慢十倍以上,也就是说实际上慢100倍以上!

        Last but not the least, 以上所说的变量预定义所带来的好处当然主要是指向量或者矩阵类型的变量。对于标量(scalar)类型变量则是否进行预定义没有什么影响。 

2. 向量化,vectorization

        向量化是另一个提高Matlab代码运行效率的主要手段。

        与向量化处理相对应的是如上一节所示的for-loop的实现方式。以下用向量化实现方式实现以上相同的处理,直观地感受一下向量化实现对于matlab程序运行效率带来的提升效果。

clearvars;
close all;
clc;

num = 1e6;
freq = 0.01; % Normalized frequency

tic
k = 1 : num;
x = sin(2*pi*k*freq);
toc

        运行结果:

历时 0.015811 秒。 

         运行时间仅为上一节最快的那种的五分之一,5倍速提升,值得你拥有。

3. 矩阵化

        矩阵化其实是向量化从1维向2维的推广而已,本质上是一样的,都是并行处理优化。

        矩阵化实现优化要求编程者将算法实现方式写成基于矩阵运算的方式,算法设计难度也提高了一些,对编程者的算法设计能力要求更高了。但是考虑到算法运行效率提高所带来的好处,这种算法设计技巧值得磨炼。

        以下通过一个用matlab以离散方式近似计算连续信号傅里叶变换的实现来对比三种实现的运行效率(例子取自参考文献[1]):(1) 用二重循环的方式;(2) 向量化 + for-loop;(3) 矩阵化。

        例:求以下矩形脉冲的频谱(即傅里叶变换):

                                                                   (1) 

        根据定义有:

                                 (2) 

        注意,由于采用数值分析的方式进行近似计算,所以必须把积分范围限定在一个有限范围以内。以上假定 代表函数f(t)的主要取值范围,并在这个区间内进行近似计算。

3.1 离散化

        基于数值分析计数计算连续函数积分的第一步就是先将待求式进行离散化。

        令,假定将该区间划分为等间隔的N个区间,每个区间长度为matlab向量化编程方法,Matlab,matlab,矩阵,向量化,vectorization,傅里叶变换.,进行待求积分离散化处理得到以下求和式(N越大,该求和式计算得到的结果就越接近待求式真正的结果):

        matlab向量化编程方法,Matlab,matlab,矩阵,向量化,vectorization,傅里叶变换                              (3) 

         进一步,还需要对频域进行离散化处理。假设为的主要取值区间,并取其中K个离散点进行对应的采样值的计算,令,则有:

        matlab向量化编程方法,Matlab,matlab,矩阵,向量化,vectorization,傅里叶变换    (4)

        

3.2 双重循环实现

        双重循环实现中,用内层循环实现对式(4)右边的累加,用外层循环实现对频域采样点的扫描,示例代码如下:

        

clearvars;
close all;
clc;

N = 2000;                         % number of time-domain sampling points
T = 20;                           % 时域区间长度
t = linspace(-T/2, T/2-T/N, N);   % 时域采样点
f = zeros(1,length(t));
f((t > -1/2) & (t < 1/2)) = 1;    % 定义时域信号

Omega = 16 * pi;                  % 频域区间长度
K     = 1000;                      % 频域采样点数
omg   = linspace(-Omega/2, Omega/2 - Omega/K, K); % 频域采样点
F1     = zeros(1,length(omg));

% 双重循环实现
tic
for k = 1:K
    for n = 1:N
        F1(k) = F1(k) + f(n) * exp(-j * omg(k) * t(n));
    end
    F1(k) = F1(k) * (T/N);
end
toc

3.3 向量化实现

        以上式(4)显然可以看作是两个向量的内积(点积,inner product, dot product),将式(4)改写如下:

matlab向量化编程方法,Matlab,matlab,矩阵,向量化,vectorization,傅里叶变换

(5)

        基于这个表达式可以得到向量化实现,代码如下所示:

% 向量化实现
tic
for k = 1:K
    F2(k) = (T/N) * ( f * exp(-j * omg(k) * t).' );
end
toc

3.4 矩阵化实现

        对式(5)可以进一步进行矩阵化处理可以得到:

matlab向量化编程方法,Matlab,matlab,矩阵,向量化,vectorization,傅里叶变换        (6)

        代码实现如下:

% 矩阵化实现
tic
exp_mat = exp(-j*(kron(t',omg)));
F3 = (T/N) * ( f * exp_mat );
toc

        以上用kron()先计算出式(6)最右边的矩阵。关于张量积(克罗内克积、直积),有兴趣的小伙伴可以参考量子笔记:张量、张量的阶数与向量的维数、外积、张量积,此处不再赘述。

        运行结果:

历时 1.192834 秒。
历时 0.071625 秒。
历时 0.062656 秒。

        可以看到向量化实现相比双重循环实现有17倍的速度提升,相当可观。但是矩阵化相比向量化的提升的效果非常有限,但是矩阵化的代码最为简洁,也有可取之处。

        可以进一步用以下assert语句检查以上三个结果是否完全一致:

assert(isempty(find(abs(F1-F2) > 1e-6)))
assert(isempty(find(abs(F1-F3) > 1e-6)))

        当然也可以用“max(abs(F1-F2))”查询它们相互之间差异最大的元素的绝对值是多少。我的运行结果式10的负十六次方左右,大家可以自行检验。 

【参考文献】

[1] 谷源涛等,信号与系统--Matlab综合实验,高等教育出版社文章来源地址https://www.toymoban.com/news/detail-783542.html

到了这里,关于Matlab高效编程:向量化(vectorization)、矩阵化、变量预定义的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Go 基础篇】Go语言关键字和预定义标识符解析:探索编程的基石与核心要素

    在计算机编程中,(Keywords)和预定义标识符(Predefined Identifiers)是编程语言的核心要素,它们在语法结构和语言功能中起到重要作用。在Go语言(Golang)中,和预定义标识符定义了编程的基本规则和构建块,是实现功能的关键。本篇博客将深入探讨Go语言中的关

    2024年02月12日
    浏览(69)
  • MATLAB 之 数值数据,矩阵的表示和变量及其操作

    MATLAB 数据类型较为丰富,既有数值型、字符串等基本数据类型,又有结构(Structure)、单元(Cell)等复杂的数据类型。 在 MATLAB 中,没有专门的逻辑型数据,而以数值 1 (非零)表示真,以数值 0 表示假。 MATLAB 各种数据类型都以矩阵形式存在,所以矩阵是 MATLAB 最基本的数据

    2024年02月04日
    浏览(47)
  • Matlab如何将变量名和矩阵都保存在excel文件

    Matlab保存数据为excel的函数有很多,但是由于matlab每年都在更新,新的函数不断涌现,极大地方便我们运算矩阵。当我很懒没有更新最新版本的matlab时,有些矩阵运算,就只能用相对原始地方法来做。比如2018版本不能用writecell和writematrix函数直接将数据保存excel文件。 matlab

    2024年02月06日
    浏览(45)
  • 【工业控制】多变量动态矩阵预测控制(DMC)【含Matlab源码 1499期】

    ✅博主简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,Matlab项目合作可私信。 🍎个人主页:海神之光 🏆代码获取方式: 海神之光Matlab王者学习之路—代码获取方式 ⛳️座右铭:行百里者,半于九十。 更多Matlab仿真内容点击👇 Matlab图像处理(进阶版) 路径规划

    2024年04月26日
    浏览(40)
  • Elasticsearch:dense vector 数据类型及标量量化

    密集向量(dense_vector)字段类型存储数值的密集向量。 密集向量场主要用于 k 最近邻 (kNN) 搜索。 dense_vector 类型不支持聚合或排序。 默认情况下,你可以基于 element_type 添加一个 dend_vector 字段作为 float 数值数组: 注意 :与大多数其他数据类型不同,密集向量始终是单值。

    2024年03月23日
    浏览(49)
  • QLoRA:量化 LLM 的高效微调

    此 repo 支持论文“QLoRA:量化 LLM 的高效微调”,旨在使对 LLM 研究的访问民主化。 QLoRA 使用bitsandbytes进行量化,并与 Hugging Face 的PEFT和transformers库集成。QLoRA 由华盛顿大学 UW NLP 小组的成员开发。 我们介绍了 QLoRA,这是一种有效的微调方法,可以减少内存使用量,足以在单个

    2024年02月08日
    浏览(43)
  • MATLAB中CVX工具箱解决凸优化问题的基本知识——语法、变量声明、目标函数、约束条件、cvx编程错误及解决方法

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 本文是在最近学习MATLAB CVX工具箱解决凸优化问题时学到的一些知识点,分享出来供大家参考。 进行CVX编程时,会遇到各种各样意想不到又难以解决的报错问题,如果编程过程中遇到了很多cvx bug和错误,

    2024年02月08日
    浏览(51)
  • 掘金量化—Python SDK文档—3.变量约定

      目录 Python SDK文档 3.变量约定   3.1 symbol - 代码标识     3.1.1交易所代码     3.1.2交易标的代码     3.1.3symbol 示例     3.1.4期货主力连续合约   3.2mode - 模式选择     3.2.1实时模式     3.2.2回测模式   3.3context - 上下文对象     3.3.1context.symbols - 订阅代码集合     

    2024年02月16日
    浏览(44)
  • 「从ES到CK 05」clickhouse高效数据处理工具vector

            在完成将公司日志数据从Elasticsearch(下称ES)转战到Clickhouse后,个人认为有必要将过程记录分享。限于篇幅及便于分类组织,我会以一个系列文章的形式记录: 01 《Elasticsearch vs Clickhouse》 02 《Clickhouse的基础知识扫盲》 03 《​Clickhouse多分片多副本集群部署​》 04

    2024年02月03日
    浏览(42)
  • C++ 科学计算矩阵数学库: Intel MKL+ Dlib +Armadillo 编程环境配置安装以及使用matlab将M文件编译成链接库

    配置时间 2022年11月13日  电脑主机:以下编程环境 只适用于windows 10 操作系统   在线安装Visual Studio 2019编译器环境【MSVC 14.29版本(对应Visual Studio1929 (Version 16.10 + 16.11)】+对应windows SDK10 kit 【版本10.0.19041.0】,注意各个工具的版本。      在线安装VS结束,要手动配置系统环

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包