Performance 大型仿真中Matlab功能的改进
我手上有一个非常大的Matlab仿真项目,我想优化它,因为我多次运行它来调整参数等等 使用Matlab,我确定了一个占用我大部分时间的函数,具体来说是行Performance 大型仿真中Matlab功能的改进,performance,matlab,for-loop,vectorization,Performance,Matlab,For Loop,Vectorization,我手上有一个非常大的Matlab仿真项目,我想优化它,因为我多次运行它来调整参数等等 使用Matlab,我确定了一个占用我大部分时间的函数,具体来说是行输出(I,1)=max(平均值(dens(I+1:a,1)),dens(I+1,1)) 此函数称为批,其中输入是作为参数双重传递的10x1,而输出也是一个10x1向量 function output = my_function(input) a = size(input,1); output = input*0; dens = density(
输出(I,1)=max(平均值(dens(I+1:a,1)),dens(I+1,1))代码>
此函数称为批,其中输入
是作为参数双重传递的10x1
,而输出
也是一个10x1
向量
function output = my_function(input)
a = size(input,1);
output = input*0;
dens = density(input);
% for each i, output(i) is the maximum between output(i+1) and mean(output(i+1:end))
for i = 1:a-1
output(i,1)= max(mean(dens(i+1:a,1)),dens(i+1,1));
end
output(a,1) = dens(a,1);
end
我的想法是:
- 我认为矢量化可能有助于消除循环(?),但我对这项技术一点也不熟悉
- 是否有一种更快/替代的方法来计算
平均值
(可能没有Matlab的内置函数调用?)
编辑
我尝试对函数进行矢量化,得到了以下替代结果,它执行相同的操作:
function output = my_function_vectorized(input)
a = size(input,1);
rho_ref = zeros(size(input));
dens = density(input);
temp_cumsum = flip(cumsum(flip(dens))./(1:1:a)');
output = [max(temp_cumsum(2:end),dens(2:a));dens(a)];
end
我尝试通过以下方式测试这两种功能:
Ts = random('unif',40,80,10,1000);
Results_original = zeros(size(Ts));
Results_vectorized = zeros(size(Ts));
TIMES_original = zeros(size(Ts,2),1);
TIMES_vectorized = zeros(size(Ts,2),1);
for ii = 1:size(Ts,2)
tic;
Results_original(:,ii) = my_function(Ts(:,ii));
TIMES_original(ii) = toc;
end
for ii = 1:size(Ts,2)
tic;
Results_vectorized(:,ii) = my_function_vectorized(Ts(:,ii));
TIMES_vectorized(ii) = toc;
end
res = norm(Res_1 - Res_2);
mTIMES_original = mean(TIMES_original);
mTIMES_vectorized = mean(TIMES_vectorized);
为此,我得到:
res =
3.1815e-12
mTIMES_original/mTIMEZ_vectorized =
3.0279
- 这是否应该与我有关李>
- 我把这个计算值固定了3倍,对吗
将其矢量化
对丹斯的重读才是让你丧命的,而不是你的意思。Mean尽Donald Knuth所能优化
我不知道你的密度函数,所以我不能确定我的索引
伪代码剪接:
%(1)faster predeclaration that shows intent
output=zeroes(size(input))
%(2)vectorize your "mean between here and the end"
b = fliplr(fliplr(cumsum(dens(1:a-1)))./fliplr(1:a-1))
%(3)assemble your interior nX2 matrix
c = [b,dens]
%(4)vectorized max, I think
output = max(c,[],2)
(1) 在速度和效率方面,很难击败内置设备。能够从现在起一年后计算出代码的功能也是很好的。随着时间的推移,我发现自己越来越想成为一名有文化的程序员(),因为从长远来看,这比一年或十年后回来尝试对自己的工作进行反向工程花费的时间要少
(2) 这里的想法是翻转密度向量,然后做一个累积和,然后将反向累积和的每个元素除以输入到其中的点数,然后再次翻转。当你把总数除以计数,它就变成了平均数。我刚刚阅读了说明(链接),有一个内部开关,因此您可以在不使用fliplr的情况下重申这一点,并使其更加快速
b = cumsum(dens(1:a-1),'reverse')./(a-1:-1:1) %this might work
(3) 理论上,当这项工作完成时,你应该有一个两列宽的矩阵,并且有和“dens”一样多的行。调整大小和预缩减可能会很昂贵——因此,如果您经常更改大小,那么您可能希望像(1)一样预先声明它
(4) “max”函数也会很快发出尖叫声。不是你也不是克努斯先生会让它更快。我认为只需要对数组的每个元素进行一次比较(siliconop)和几次洗牌(每个元素少于一次)
这是一个元素方面的最大值(我忘了在中间添加缓冲区)。它已经变得很快,并且它的输出是一个数组。它可能需要一个1而不是2,但是你知道你在那里做什么,并且可以弄清楚
如果对你有效,请告诉我。我猜这可能只会提高5倍
我惊讶地发现LabVIEW可以比MatLab快100倍完成一些基础知识,因为它(总是)经过编译。在MatLab中编译时,必须对类型和值施加许多新的约束,但在LV中,编译基本上是免费的,因为所有这些约束都是初始程序创建的一部分。如果您发现MatLab程序的核心速度不够快,您可以为LV制作一个包装器,并在那里以非常小的速度运行它。LV并没有详细阐述——我们用文本代替图片(或者达芬奇对主题的个性化渲染,作为更正确的隐喻)是有原因的
编辑:(关于速度)
看起来您的速度快了约3倍
编辑:(关于代码,注意我使用的是2014a)
其中:
a =
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
mu =
Columns 1 through 9
8 8.5 9 9.5 10 10.5 11 11.5 12
Columns 10 through 15
12.5 13 13.5 14 14.5 15
所以我做“a”,一个从1开始到15的向量。最后一个值是15。第二个到最后一个值与最后一个值之间的平均值为14.5。最后3个值的平均值为14。数学似乎在这里起作用
编辑:
%(1)faster predeclaration that shows intent
output=zeroes(size(input))
%(2)vectorize your "mean between here and the end"
b = fliplr(fliplr(cumsum(dens(1:a-1)))./fliplr(1:a-1))
%(3)assemble your interior nX2 matrix
c = [b,dens]
%(4)vectorized max, I think
output = max(c,[],2)
一个巨大的加速是关闭了当前基于java的系统。我已经看到代码在2010a版本中运行时获得了很大的(优于3倍)速度提升。一些代码在Java中运行时比在Fortran或基于C的编译库中运行时要慢得多。将其矢量化
对丹斯的重读才是让你丧命的,而不是你的意思。Mean尽Donald Knuth所能优化
我不知道你的密度函数,所以我不能确定我的索引
伪代码剪接:
%(1)faster predeclaration that shows intent
output=zeroes(size(input))
%(2)vectorize your "mean between here and the end"
b = fliplr(fliplr(cumsum(dens(1:a-1)))./fliplr(1:a-1))
%(3)assemble your interior nX2 matrix
c = [b,dens]
%(4)vectorized max, I think
output = max(c,[],2)
(1) 在速度和效率方面,很难击败内置设备。能够从现在起一年后计算出代码的功能也是很好的。随着时间的推移,我发现自己越来越想成为一名有文化的程序员(),因为从长远来看,这比一年或十年后回来尝试对自己的工作进行反向工程花费的时间要少
(2) 这里的想法是翻转密度向量,然后做一个累积和,然后将反向累积和的每个元素除以输入到其中的点数,然后再次翻转。当你把总数除以计数,它就变成了平均数。我刚刚阅读了说明(链接),有一个内部开关,因此您可以在不使用fliplr的情况下重申这一点,并使其更加快速
b = cumsum(dens(1:a-1),'reverse')./(a-1:-1:1) %this might work
(3) 理论上,当这项工作完成时,你应该有一个两列宽的矩阵,并且有和“dens”一样多的行。调整大小和预缩减可能会很昂贵——因此,如果您经常更改大小,那么您可能希望像(1)一样预先声明它
(4) “max”函数也会很快发出尖叫声。不是你也不是克努斯先生会让它更快。我认为对数组的每个元素进行一次比较(siliconop)和几次洗牌(每个元素少于一次)就足够了