大家好,欢迎来到IT知识分享网。
“时问桫椤”公众号,一个不太正式的学术加油站,专为本科生到研究生的你提供“非正式”援助。当你感到迷茫、痛苦,或是被学术大山压得喘不过气时,我们就是你的“学术救生圈”。我们用研究生们的血泪经验,帮你快速适应研究生生活,揭开科研的神秘面纱。祝你一路顺风,科研路上不翻车!
非常感谢各位的点赞,关注和转发,你们的点赞和关注是我更新的动力[1]
技法分享
- 尽量避免使用循环结构
MATLAB变量的基本类型是矩阵,当对矩阵的每个元素循环处理时,运算速度很慢。因此编程时应尽量把数组和矩阵看作一个整体来进行编程,而不是像其他的程序设计语言那样,使用循环结构对矩阵的元素循环进行处理。
利用MATLAB提供的用于矢量化操作的函数,把循环矢量化,这样既可以提高编程效率,也可以提高程序的执行效率。
下面给出一个循环的例子:
i=0; for n =0:0.1:100 i=i+1; y(i)=cos(n) end
上述程序段把数组中的每个元素都进行函数值计算,这样会耗费大量的运算时间,我们可以把数组看作一个整体来处理,计算函数值,可以修改这个程序段如下。
n = 0:0.1:100; y = cos(n)
通过使用MATLAB专门提供的测试程序运行时间的函数,可以发现,把数组看作一个整体,进行操作后,执行效率提高约300倍。
另外,在必须使用多重循环的情况下,建议在循环的外环执行循环次数少的,内环执行循环次数多的,这样也可以显著提高程序执行速度。
- 在使用数组或矩阵之前先定义维数
MATLAB中的变量在使用之前不需要明确地定义和指定维数。
但当未预定义数组或矩阵的维数时,当需赋值的元素下标超出现有的维数时,MATLAB 就为该数组或矩阵扩维一次,这样就会大大降低程序的执行效率。
因此,在使用数组或矩阵之前,预定义维数可以提高程序的执行效率。
- 对矩阵元素使用下标或者索引操作
在MATLAB中,矩阵元素的引用可用两个下标来表示。例如:
A(i,j) 表示矩阵的第i行第j列的元素; A(1:k,j)表示矩阵A的第j列的前k个元素; A(:,j) 表示矩阵的第j列的所有元素。 求矩阵A的第j列元素的平均值的表达式为mean(A(:,j))。
- 尽量多使用函数文件少使用脚本文件
因为每次调用MATLAB的脚本文件都需要将不必要的中间变量加载到内存中,每执行一次,就加载一次。
函数在调用时被编译成了伪代码,只需要加载到内存一次。当多次调用同一个函数时会运行快一些。
因此尽量多使用函数文件而少使用脚本文件,也是提高执行效率的一种方法。
- 在必须使用循环时,可以考虑转换为C-MEX
当必须使用耗时的循环时,可以考虑将循环体中的语句转换为C-MEX。
C-MEX是将M文件通过MATLAB 的编译器转换为可执行文件,是按照 MEX 技术要求的格式编写相应的程序,通过编译连接,生成扩展名为.dll的动态链接库文件,可以在MATLAB环境下直接执行。
这样,循环体中的语句在执行时不必每次都解释(interpret)。一般来说,C-MEX 文件的执行速度是相同功能的M文件执行速率的20~40倍。
编写C-MEX不同于M文件,需要了解MATLAB C-MEX规范。幸运的是MATLAB提供了将M文件转换为C-MEX的工具。
- 内存优化
MATLAB在进行复杂的运算时需要占用大量的内存。
合理使用内存和提高内存的使用效率,可以加快运行速度,减少系统资源的占用。
- 内存管理函数和命令
● Clear variablename:从内存中删除名称为variablename的变量。
● Clear all:从内存中删除所有的变量。
● Save:将指令的变量存入磁盘。
● Load:将save命令存入的变量载入内存。
● Quit:退出MATLAB,并释放所有分配的内存。
● Pack:把内存中的变量存入磁盘,再用内存中的连续空间载回这些变量。考虑到执行效率问题,不能在循环中使用。
- 节约内存的方法
● 避免生成大的中间变量,并删除不再需要的临时变量。
● 当使用大的矩阵变量时,预先指定维数并分配好内存,避免每次临时扩充维数。
● 当程序需要生成大量变量数据时,可以考虑定期将变量写到磁盘,然后清除这些变量。当需要这些变量时,再重新从磁盘加载。
● 当矩阵中数据极少时,将全矩阵转换为稀疏矩阵。
函数式编程
函数式编程是一种编程范式,它强调使用纯函数、不可变数据和高阶函数来构建应用程序。在函数式编程中,我们避免使用副作用和可变状态,而是通过函数来处理数据。以下是一些常见的函数式编程技巧和方法,用于替代传统的循环和条件判断:
- 使用map替代for循环: map函数接受一个函数和一个数组,返回一个新数组,其中的元素是原始数组元素应用给定函数的结果。 // 传统for循环
let numbers = [1, 2, 3, 4];
let squaredNumbers = [];
for (let i = 0; i < numbers.length; i++) {
squaredNumbers.push(numbers[i] * numbers[i]);
}// 函数式编程中的map
let squaredNumbersFunctional = numbers.map(x => x * x); - 使用reduce进行累加或聚合操作: reduce函数接受一个累加器函数和一个初始值,将数组中的所有元素减少到单个值。 // 传统for循环累加
let sum = 0;
for (let i = 0; i < numbers.length; i++) {
sum += numbers[i];
}// 函数式编程中的reduce
let sumFunctional = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); - 使用filter进行条件筛选: filter函数接受一个测试函数和一个数组,返回所有使得测试函数返回true的元素组成的新数组。 // 传统for循环筛选
let evenNumbers = [];
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
evenNumbers.push(numbers[i]);
}
}// 函数式编程中的filter
let evenNumbersFunctional = numbers.filter(x => x % 2 === 0); - 使用find或findIndex寻找满足条件的第一个元素: find返回数组中满足提供的测试函数的第一个元素的值。如果没有这样的元素,则返回undefined。 // 传统for循环查找
let firstEvenNumber;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
firstEvenNumber = numbers[i];
break;
}
}// 函数式编程中的find
let firstEvenNumberFunctional = numbers.find(x => x % 2 === 0); - 使用some或every进行条件检查: some测试数组中是否至少有一个元素满足提供的测试函数。every测试数组中的所有元素是否都满足提供的测试函数。 // 传统if else检查
if (numbers.some(x => x > 10)) {
console.log(“At least one number is greater than 10.”);
}// 函数式编程中的some
numbers.some(x => x > 10) && console.log(“At least one number is greater than 10.”); - 使用compose和pipe进行函数组合: compose和pipe允许你将多个函数组合成一个函数,从而减少嵌套和提高可读性。 // 函数组合
const squareAndAddOne = R.pipe(
R.map(R.add(1)),
R.map(R.multiply(2))
);squareAndAddOne([1, 2, 3]); // [4, 6, 8]
- 使用switch替代多个if else分支: 虽然switch不是函数式编程特有的,但在某些情况下,它可以替代多个if else分支,使代码更加清晰。 // 传统if else分支
if (condition) {
// do something
} else if (anotherCondition) {
// do something else
} else {
// default case
}// 使用switch
switch (condition) {
case ‘case1’:
// do something
break;
case ‘case2’:
// do something else
break;
default:
// default case
break;
}
请注意,这些方法在不同的编程语言中可能有不同的实现方式,但核心思想是相同的。在JavaScript中,你可以使用Ramda库或Lodash库等来实现这些函数式编程模式。在其他语言中,如Haskell或Scala,函数式编程是内置的,并且有更多内置的函数式编程特性。
参考资料
[1]
首发平台: 非常感谢各位的点赞,关注和转发,你们的点赞和关注是我更新的动力。哔哩哔哩,知乎和墨滴平台同名账号。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/94817.html