原文地址:http://www.bfcat.com/index.php/2012/11/speed-up-app/

这篇文章原文是matlab网站上的,我把它翻译过来同时自己也学习一下。原文见这里

这篇文章主要使用到了如下几种加速方法:

这篇文章原文是matlab网站上的,我把它翻译过来同时自己也学习一下。原文见这里

这篇文章主要使用到了如下几种加速方法:

  • 预分配空间
  • 向量化
  • 移除重复运算

我们要加速的程序是这样的。代码首先生成一个
x1 x2为横纵坐标的2D网格. 这个程序是要循环遍历所有初始和终止点的组合。给定一组位置,程序计算一个指数,如果这个指数小于阈值gausThresh,那么这个值就用于计算 out. subs变量保存所有点的位置坐标。

最初的程序如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53
% Initialize the grid and initial and final points

nx1 = 10; nx2 = 10;

x1l = 0; x1u = 100;

x2l = 0; x2u = 100;



x1 = linspace(x1l,x1u,nx1+1);

x2 = linspace(x2l,x2u,nx2+1);



limsf1 = 1:nx1+1; limsf2 = 1:nx2+1;



% Initalize other variables

t = 1;

sigmax1 = 0.5; sigmax2 = 1;

sigma = t * [sigmax1^2 0; 0 sigmax2^2];

invSig = inv(sigma);

detSig = det(sigma);



expF = [1 0; 0 1];

n = size (expF, 1);

gausThresh = 10;



small = 0; subs = [];
vals = [];



% Iterate through all possible initial

% and final positions and calculate

% the values of exponent and out

% if exponent > gausThresh.



for i1 = 1:nx1+1

for i2 = 1:nx2+1

for f1 = limsf1

for f2 = limsf2



% Initial and final position

xi = [x1(i1) x2(i2)]';

xf = [x1(f1) x2(f2)]';



exponent = 0.5 * (xf - expF * xi)'...

* invSig * (xf - expF * xi);



if exponent > gausThresh

small = small + 1;

else

out = 1 / (sqrt((2 * pi)^n
* detSig))...

* exp(-exponent);

subs = [subs; i1 i2 f1 f2];

vals = [vals; out];

end



end

end

end

end

下面是一个图形表示的可视化(nx1=nx2=100). 因为数据非常稠密,所以我们只显示其中一部分。红线链接的就是指数计算结果小于阈值的部分,线的粗细反应了数值大小。

这个程序在一个T60 Lenovo dual-core laptop 上面,开启了多线程以后,运行时间如下

1

2

3

4
displayRunTimes(1)

nx1 nx2 time

50 50 296 seconds

100 100 9826 seconds

M-Lint 的建议

第一步,也是最简单的一步就是根据 M-Lint 的建议修改,
这是matlab自带的静态代码分析工具。在editor里面就可以看到这些建议内容,不过也可以自己写一个函数让建议内容更加集中的显示一下。例如

1

2
output = mlint('initial.m');

displayMlint(output);

'subs' might be growing inside a loop. Consider preallocating for speed.

'vals' might be growing inside a loop. Consider preallocating for speed.

根据建议,第一步是要给一些数组预分配空间。这样做是因为matlab使用的内存中连续的块,因此,如果在循环里不断改变数组大小,matlab就要不断寻找合适大小的内存片段并把数据移动过去。如果分配了一个比较大的空间,matlab就可以一直在这个连续空间工作。

但是,目前我们不知道 subs和vars的个数,如果要预分配,我们得分配最大可能的空间。那就是100^4,我们来试试:

1

2

3

4

5
try

zeros(1,100^4)

catch ME

end

display(ME.message)

Out of memory. Type HELP MEMORY for your options.

看来不行啊。太大了。

因此,我们只能通过分块分配空间来实现,每次分配一个可以接受的大小,并设置一个计数器,当这块空间满了的时候,再分配一个块。这样,内存移动的次数大大得到了降低。

(bfcat注: 这种不知道数组大小的时候,还有一个方法就是使用cell。我没有仔细分析cell的原理,但是我觉得它像是一个链表,因此cell里面的每一个元素不需要在连续的内存空间。因此,当我们执行类似 M{end+1} = m 的时候,matlab也不需要将M 中已有的元素都拷贝一次。这样,虽然Mlint还会提示让我们为cell预先分配空间,但是没关系,不分配对速度影响也不大。当循环结束以后,执行类似
M = cat(1, M{:}) 这样的语句就可以将其变回数组了。)

预分配空间后的代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52
% Initialization

nx1 = 10;

nx2 = 10;



[x1,x2,limsf1,limsf2,expF,gausThresh,small,invSig,detSig,n]= ...

initialize(nx1,nx2);



% Initial guess for preallocation

mm = min((nx1+1)^2*(nx2+1)^2, 10^6);

subs = zeros(mm,4);

vals = zeros(mm,1);



counter = 0;



% Iterate through all possible initial

% and final positions

for i1 = 1:nx1+1

for i2 = 1:nx2+1

for f1 = limsf1

for f2 = limsf2



xi = [x1(i1) x2(i2)]'; %%
Initial position

xf = [x1(f1) x2(f2)]'; %%
Final position



exponent = 0.5 * (xf - expF * xi)'...

* invSig * (xf - expF * xi);



% Increase preallocation if necessary

if counter == length(vals)

subs = [subs; zeros(mm, 4)];

vals = [vals; zeros(mm, 1)];

end



if exponent > gausThresh

small = small + 1;

else

% Counter introduced

counter=counter + 1;

out = 1 / (sqrt((2 * pi)^n
* detSig))...

* exp(-exponent);

subs(counter,:) = [i1
i2 f1 f2];

vals(counter) = out;

end



end

end

end

end



% Remove zero components that came from preallocation

vals = vals(vals > 0);

subs = subs(vals > 0);
1

2

3

4
displayRunTimes(2)

nx1 nx2 time

50 50 267 seconds

100 100 4228 seconds

运行速度变快了一些,但是还是不够理想。

向量化

因为matlab是基于矩阵的语言,因此,我们最好尽量用向量代替循环。尤其是多重循环嵌套的时候更要注意速度问题。对于这个代码,我们主要进行以下两种改动

  • 向量化里面的两个循环
  • 向量化里面的三个循环

尝试1: 向量化两个内循环

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47
% Initialization



nx1 = 10;

nx2 = 10;



[x1,x2,limsf1,limsf2,expF,gausThresh,small,invSig,detSig,n]= ...

initialize(nx1,nx2);



vals = cell(nx1+1,nx2+1); %
Cell preallocation

subs = cell(nx1+1,nx2+1); %
Cell preallocation



[xind,yind] = meshgrid(limsf1,limsf2);

xyindices = [xind(:)'
; yind(:)'];



[x,y] = meshgrid(x1(limsf1),x2(limsf2));

xyfinal = [x(:)'
; y(:)'];



exptotal = zeros(length(xyfinal),1);



% Loop over all possible combinations of positions

for i1 = 1:nx1+1

for i2 = 1:nx2+1



xyinitial = repmat([x1(i1);x2(i2)],1,length(xyfinal));



expa = 0.5 * (xyfinal - expF * xyinitial);

expb = invSig * (xyfinal - expF * xyinitial);

exptotal(:,1) =
expa(1,:).*expb(1,:)+expa(2,:).*expb(2,:);



index = find(exptotal < gausThresh);

expreduced = exptotal(exptotal < gausThresh);



out = 1 / (sqrt((2 * pi)^n
* detSig)) * exp(-(expreduced));

vals{i1,i2} = out;

subs{i1,i2} = [i1*ones(1,length(index)) ; ...

i2*ones(1,length(index));
xyindices(1,index); ...

xyindices(2,index)]'
;



end

end



% Reshape and convert output so it is in a

% simple matrix format

vals = cell2mat(vals(:));

subs = cell2mat(subs(:));



small = ((nx1+1)^2*(nx2+1)^2)-length(subs);

这个向量化效果非常明显

1

2

3

4
displayRunTimes(3)

nx1 nx2 time

50 50 1.51 seconds

100 100 19.28 seconds

这里主要使用了下面几个向量化的手段

  • 使用 meshgrid 和 repmat 创建矩阵
  • 使用向量和矩阵操作
  • 尽量直接使用向量元素操作
尝试2: 向量化三个内循环
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45
% Initialization

nx1 = 10;

nx2 = 10;



[x1,x2,limsf1,limsf2,expF,gausThresh,small,invSig,detSig,n]= ...

initialize(nx1,nx2);



limsi1 = limsf1;

limsi2 = limsf2;



% ndgrid gives a matrix of all the possible combinations

[aind,bind,cind] = ndgrid(limsi2,limsf1,limsf2);

[a,b,c] = ndgrid(x2,x1,x2);



vals = cell(nx1+1,nx2+1); %
Cell preallocation

subs = cell(nx1+1,nx2+1); %
Cell preallocation



% Convert grids to single vector to use in a single loop

b = b(:); aind = aind(:);
bind = bind(:); cind = cind(:);



expac = a(:)-c(:); %
Calculate x2-x1



% Iterate through initial x1 positions (i1)

for i1 = limsi1



exbx1= b-x1(i1);

expaux = invSig(2)*exbx1.*expac;

exponent = 0.5*(invSig(1)*exbx1.*exbx1+expaux);



index = find(exponent < gausThresh);

expreduced = exponent(exponent < gausThresh);



vals{i1} = 1 / (sqrt((2 * pi)^n
* detSig))...

.*exp(-expreduced);



subs{i1} = [i1*ones(1,length(index));

aind(index)' ; bind(index)';...

cind(index)']';



end



vals = cell2mat(vals(:));

subs = cell2mat(subs(:));



small = ((nx1+1)^2*(nx2+1)^2)-length(subs);

现在运行时间更短了:

1

2

3

4
displayRunTimes(4)

nx1 nx2 time

50 50 0.658 seconds

100 100 8.77 seconds

最后,简化一些计算,让其只算一次

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70
nx1 = 100; nx2 = 100;

x1l = 0; x1u = 100;

x2l = 0; x2u = 100;



x1 = linspace(x1l,x1u,nx1+1);

x2 = linspace(x2l,x2u,nx2+1);



limsi1 = 1:nx1+1;

limsi2 = 1:nx2+1;



limsf1 = 1:nx1+1;

limsf2 = 1:nx2+1;



t = 1;



sigmax1 = 0.5;

sigmax2 = 1;



sigma = t * [sigmax1^2 sigmax2^2];

detSig = sigma(1)*sigma(2);

invSig = [1/sigma(1) 1/sigma(2)];



gausThresh = 10;

n=3;

const=1 / (sqrt((2 * pi)^n
* detSig));



% ndgrid gives a matrix of all the possible combinations

% of position, except limsi1 which we iterate over



[aind,bind,cind] = ndgrid(limsi2,limsf1,limsf2);

[a,b,c] = ndgrid(x2,x1,x2);



vals = cell(nx1+1,nx2+1); %
Cell preallocation

subs = cell(nx1+1,nx2+1); %
Cell preallocation



% Convert grids to single vector to

% use in a single for-loop

b = b(:);

aind = aind(:);

bind = bind(:);

cind = cind(:);



expac= a(:)-c(:);

expaux = invSig(2)*expac.*expac;



% Iterate through initial x1 positions



for i1 = limsi1



expbx1= b-x1(i1);

exponent = 0.5*(invSig(1)*expbx1.*expbx1+expaux);



% Find indices where exponent < gausThresh

index = find(exponent < gausThresh);



% Find and keep values where exp < gausThresh



expreduced = exponent(exponent < gausThresh);



vals{i1} = const.*exp(-expreduced);



subs{i1} = [i1*ones(1,length(index));

aind(index)' ; bind(index)';...

cind(index)']';

end



vals = cell2mat(vals(:));

subs = cell2mat(subs(:));



small = ((nx1+1)^2*(nx2+1)^2)-length(subs);

最终的运行时间

1

2

3

4
displayRunTimes(5)

nx1 nx2 time

50 50 0.568 seconds

100 100 8.36 seconds
  • 预分配空间
  • 向量化
  • 移除重复运算

我们要加速的程序是这样的。代码首先生成一个
x1 x2为横纵坐标的2D网格. 这个程序是要循环遍历所有初始和终止点的组合。给定一组位置,程序计算一个指数,如果这个指数小于阈值gausThresh,那么这个值就用于计算 out. subs变量保存所有点的位置坐标。

最初的程序如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53
% Initialize the grid and initial and final points

nx1 = 10; nx2 = 10;

x1l = 0; x1u = 100;

x2l = 0; x2u = 100;



x1 = linspace(x1l,x1u,nx1+1);

x2 = linspace(x2l,x2u,nx2+1);



limsf1 = 1:nx1+1; limsf2 = 1:nx2+1;



% Initalize other variables

t = 1;

sigmax1 = 0.5; sigmax2 = 1;

sigma = t * [sigmax1^2 0; 0 sigmax2^2];

invSig = inv(sigma);

detSig = det(sigma);



expF = [1 0; 0 1];

n = size (expF, 1);

gausThresh = 10;



small = 0; subs = [];
vals = [];



% Iterate through all possible initial

% and final positions and calculate

% the values of exponent and out

% if exponent > gausThresh.



for i1 = 1:nx1+1

for i2 = 1:nx2+1

for f1 = limsf1

for f2 = limsf2



% Initial and final position

xi = [x1(i1) x2(i2)]';

xf = [x1(f1) x2(f2)]';



exponent = 0.5 * (xf - expF * xi)'...

* invSig * (xf - expF * xi);



if exponent > gausThresh

small = small + 1;

else

out = 1 / (sqrt((2 * pi)^n
* detSig))...

* exp(-exponent);

subs = [subs; i1 i2 f1 f2];

vals = [vals; out];

end



end

end

end

end

下面是一个图形表示的可视化(nx1=nx2=100). 因为数据非常稠密,所以我们只显示其中一部分。红线链接的就是指数计算结果小于阈值的部分,线的粗细反应了数值大小。

这个程序在一个T60 Lenovo dual-core laptop 上面,开启了多线程以后,运行时间如下

1

2

3

4
displayRunTimes(1)

nx1 nx2 time

50 50 296 seconds

100 100 9826 seconds

M-Lint 的建议

第一步,也是最简单的一步就是根据 M-Lint 的建议修改,
这是matlab自带的静态代码分析工具。在editor里面就可以看到这些建议内容,不过也可以自己写一个函数让建议内容更加集中的显示一下。例如

1

2
output = mlint('initial.m');

displayMlint(output);

'subs' might be growing inside a loop. Consider preallocating for speed.

'vals' might be growing inside a loop. Consider preallocating for speed.

根据建议,第一步是要给一些数组预分配空间。这样做是因为matlab使用的内存中连续的块,因此,如果在循环里不断改变数组大小,matlab就要不断寻找合适大小的内存片段并把数据移动过去。如果分配了一个比较大的空间,matlab就可以一直在这个连续空间工作。

但是,目前我们不知道 subs和vars的个数,如果要预分配,我们得分配最大可能的空间。那就是100^4,我们来试试:

1

2

3

4

5
try

zeros(1,100^4)

catch ME

end

display(ME.message)

Out of memory. Type HELP MEMORY for your options.

看来不行啊。太大了。

因此,我们只能通过分块分配空间来实现,每次分配一个可以接受的大小,并设置一个计数器,当这块空间满了的时候,再分配一个块。这样,内存移动的次数大大得到了降低。

(bfcat注: 这种不知道数组大小的时候,还有一个方法就是使用cell。我没有仔细分析cell的原理,但是我觉得它像是一个链表,因此cell里面的每一个元素不需要在连续的内存空间。因此,当我们执行类似 M{end+1} = m 的时候,matlab也不需要将M 中已有的元素都拷贝一次。这样,虽然Mlint还会提示让我们为cell预先分配空间,但是没关系,不分配对速度影响也不大。当循环结束以后,执行类似
M = cat(1, M{:}) 这样的语句就可以将其变回数组了。)

预分配空间后的代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52
% Initialization

nx1 = 10;

nx2 = 10;



[x1,x2,limsf1,limsf2,expF,gausThresh,small,invSig,detSig,n]= ...

initialize(nx1,nx2);



% Initial guess for preallocation

mm = min((nx1+1)^2*(nx2+1)^2, 10^6);

subs = zeros(mm,4);

vals = zeros(mm,1);



counter = 0;



% Iterate through all possible initial

% and final positions

for i1 = 1:nx1+1

for i2 = 1:nx2+1

for f1 = limsf1

for f2 = limsf2



xi = [x1(i1) x2(i2)]'; %%
Initial position

xf = [x1(f1) x2(f2)]'; %%
Final position



exponent = 0.5 * (xf - expF * xi)'...

* invSig * (xf - expF * xi);



% Increase preallocation if necessary

if counter == length(vals)

subs = [subs; zeros(mm, 4)];

vals = [vals; zeros(mm, 1)];

end



if exponent > gausThresh

small = small + 1;

else

% Counter introduced

counter=counter + 1;

out = 1 / (sqrt((2 * pi)^n
* detSig))...

* exp(-exponent);

subs(counter,:) = [i1
i2 f1 f2];

vals(counter) = out;

end



end

end

end

end



% Remove zero components that came from preallocation

vals = vals(vals > 0);

subs = subs(vals > 0);
1

2

3

4
displayRunTimes(2)

nx1 nx2 time

50 50 267 seconds

100 100 4228 seconds

运行速度变快了一些,但是还是不够理想。

向量化

因为matlab是基于矩阵的语言,因此,我们最好尽量用向量代替循环。尤其是多重循环嵌套的时候更要注意速度问题。对于这个代码,我们主要进行以下两种改动

  • 向量化里面的两个循环
  • 向量化里面的三个循环

尝试1: 向量化两个内循环

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47
% Initialization



nx1 = 10;

nx2 = 10;



[x1,x2,limsf1,limsf2,expF,gausThresh,small,invSig,detSig,n]= ...

initialize(nx1,nx2);



vals = cell(nx1+1,nx2+1); %
Cell preallocation

subs = cell(nx1+1,nx2+1); %
Cell preallocation



[xind,yind] = meshgrid(limsf1,limsf2);

xyindices = [xind(:)'
; yind(:)'];



[x,y] = meshgrid(x1(limsf1),x2(limsf2));

xyfinal = [x(:)'
; y(:)'];



exptotal = zeros(length(xyfinal),1);



% Loop over all possible combinations of positions

for i1 = 1:nx1+1

for i2 = 1:nx2+1



xyinitial = repmat([x1(i1);x2(i2)],1,length(xyfinal));



expa = 0.5 * (xyfinal - expF * xyinitial);

expb = invSig * (xyfinal - expF * xyinitial);

exptotal(:,1) =
expa(1,:).*expb(1,:)+expa(2,:).*expb(2,:);



index = find(exptotal < gausThresh);

expreduced = exptotal(exptotal < gausThresh);



out = 1 / (sqrt((2 * pi)^n
* detSig)) * exp(-(expreduced));

vals{i1,i2} = out;

subs{i1,i2} = [i1*ones(1,length(index)) ; ...

i2*ones(1,length(index));
xyindices(1,index); ...

xyindices(2,index)]'
;



end

end



% Reshape and convert output so it is in a

% simple matrix format

vals = cell2mat(vals(:));

subs = cell2mat(subs(:));



small = ((nx1+1)^2*(nx2+1)^2)-length(subs);

这个向量化效果非常明显

1

2

3

4
displayRunTimes(3)

nx1 nx2 time

50 50 1.51 seconds

100 100 19.28 seconds

这里主要使用了下面几个向量化的手段

  • 使用 meshgrid 和 repmat 创建矩阵
  • 使用向量和矩阵操作
  • 尽量直接使用向量元素操作
尝试2: 向量化三个内循环
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45
% Initialization

nx1 = 10;

nx2 = 10;



[x1,x2,limsf1,limsf2,expF,gausThresh,small,invSig,detSig,n]= ...

initialize(nx1,nx2);



limsi1 = limsf1;

limsi2 = limsf2;



% ndgrid gives a matrix of all the possible combinations

[aind,bind,cind] = ndgrid(limsi2,limsf1,limsf2);

[a,b,c] = ndgrid(x2,x1,x2);



vals = cell(nx1+1,nx2+1); %
Cell preallocation

subs = cell(nx1+1,nx2+1); %
Cell preallocation



% Convert grids to single vector to use in a single loop

b = b(:); aind = aind(:);
bind = bind(:); cind = cind(:);



expac = a(:)-c(:); %
Calculate x2-x1



% Iterate through initial x1 positions (i1)

for i1 = limsi1



exbx1= b-x1(i1);

expaux = invSig(2)*exbx1.*expac;

exponent = 0.5*(invSig(1)*exbx1.*exbx1+expaux);



index = find(exponent < gausThresh);

expreduced = exponent(exponent < gausThresh);



vals{i1} = 1 / (sqrt((2 * pi)^n
* detSig))...

.*exp(-expreduced);



subs{i1} = [i1*ones(1,length(index));

aind(index)' ; bind(index)';...

cind(index)']';



end



vals = cell2mat(vals(:));

subs = cell2mat(subs(:));



small = ((nx1+1)^2*(nx2+1)^2)-length(subs);

现在运行时间更短了:

1

2

3

4
displayRunTimes(4)

nx1 nx2 time

50 50 0.658 seconds

100 100 8.77 seconds

最后,简化一些计算,让其只算一次

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70
nx1 = 100; nx2 = 100;

x1l = 0; x1u = 100;

x2l = 0; x2u = 100;



x1 = linspace(x1l,x1u,nx1+1);

x2 = linspace(x2l,x2u,nx2+1);



limsi1 = 1:nx1+1;

limsi2 = 1:nx2+1;



limsf1 = 1:nx1+1;

limsf2 = 1:nx2+1;



t = 1;



sigmax1 = 0.5;

sigmax2 = 1;



sigma = t * [sigmax1^2 sigmax2^2];

detSig = sigma(1)*sigma(2);

invSig = [1/sigma(1) 1/sigma(2)];



gausThresh = 10;

n=3;

const=1 / (sqrt((2 * pi)^n
* detSig));



% ndgrid gives a matrix of all the possible combinations

% of position, except limsi1 which we iterate over



[aind,bind,cind] = ndgrid(limsi2,limsf1,limsf2);

[a,b,c] = ndgrid(x2,x1,x2);



vals = cell(nx1+1,nx2+1); %
Cell preallocation

subs = cell(nx1+1,nx2+1); %
Cell preallocation



% Convert grids to single vector to

% use in a single for-loop

b = b(:);

aind = aind(:);

bind = bind(:);

cind = cind(:);



expac= a(:)-c(:);

expaux = invSig(2)*expac.*expac;



% Iterate through initial x1 positions



for i1 = limsi1



expbx1= b-x1(i1);

exponent = 0.5*(invSig(1)*expbx1.*expbx1+expaux);



% Find indices where exponent < gausThresh

index = find(exponent < gausThresh);



% Find and keep values where exp < gausThresh



expreduced = exponent(exponent < gausThresh);



vals{i1} = const.*exp(-expreduced);



subs{i1} = [i1*ones(1,length(index));

aind(index)' ; bind(index)';...

cind(index)']';

end



vals = cell2mat(vals(:));

subs = cell2mat(subs(:));



small = ((nx1+1)^2*(nx2+1)^2)-length(subs);

最终的运行时间

1

2

3

4
displayRunTimes(5)

nx1 nx2 time

50 50 0.568 seconds

100 100 8.36 seconds

本文引用地址:http://blog.sciencenet.cn/blog-791749-636039.html 转载请注明来自科学网博客,并请注明作者姓名。

[转载]高效使用matlab之四:一个加速matlab程序的例子的更多相关文章

  1. 如何加速MATLAB代码运行

    学习笔记 V1.0 2015/4/17 如何加速MATLAB代码运行 概述 本文源于LDPCC的MATLAB代码,即<CCSDS标准的LDPC编译码仿真>.由于代码的问题,在信息位长度很长 ...

  2. 利用Matlab生成一个网格化的三维球面(生成直角坐标)

    利用Matlab生成一个网格化的三维球面,分别对径向方向.经度方向和纬度方向进行网格化,代码如下: %生成一个笛卡尔坐标系下球面网格的x,y,z坐标 %r为球面距离 %nJingdu,nWeidu分别 ...

  3. Matlab获取一个文件夹下所有文件名

    Matlab获取一个文件夹下所有文件名: fileFolder=fullfile('D:\MATLAB\bin\trc'); dirOutput=dir(fullfile(fileFolder,'*. ...

  4. Matlab高级教程_第二篇:一个简单的混编例子

    1. 常用的混编是MATLAB和VS两个编辑器之间的混编方式. 2. 因为MATLAB的核是C型语言,因此常见的混编方式是MATLAB和C型语言的混编. 3. 这里介绍一个简单的MATLAB语言混编成 ...

  5. 相机标定过程(opencv) + matlab参数导入opencv + matlab标定和矫正

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 辛苦原创所得,转载请注明出处 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ...

  6. MATLAB生成exe脱离matlab运行可执行程序

    https://blog.csdn.net/u013007900/article/details/53485204 侵权即删. ———————————————— 版权声明:本文为CSDN博主「小木匠_ ...

  7. [python][matlab]使用python调用matlab程序

    问题引入 在做实验的时候,需要用到python和matlab工具来进行不同的处理,比如在run神经网络的时候,需要使用pytorch框架得到网络的各个参数,在得到参数后需要使用matlab进行聚类规划 ...

  8. 面向对象:MATLAB的自定义类 [MATLAB]

    https://www.cnblogs.com/gentle-min-601/p/9785812.html 面向对象:MATLAB的自定义类 [MATLAB]   这几天刚刚开始学习MATLAB的面向 ...

  9. $ 一步一步学Matlab(2)——Matlab基本通用操作

    在上一篇中对Matlab做了一个初步的了解,本文继续来零距离亲身体验Matlab,来感受一下Matlab的一些基本.通用的操作. 命令行窗口 一打开Matlab就能看到命令行窗口,在我所用的这个精简版 ...

随机推荐

  1. C# 单点登录 MVC

    实现sso系统的主要难点: 1:不能直接访问数据库,有安全隐患,而且还容易乱套. 2:多个系统需要进行单点登录,逻辑需要严谨,能支持N多系统.而不只是少数几个系统. 3:代码不能过于复杂,需要简洁,灵 ...

  2. eclipse(adt-bundle)的Android SDK Manager下载不了谷歌的东西怎么办?

    那就是换镜像! 腾讯镜像:android-mirror.bugly.qq.com 端口:8080 腾讯镜像使用方法:http://android-mirror.bugly.qq.com:8080/in ...

  3. yield(C# 参考)

    yield(C# 参考) 在语句中使用 yield 关键字,表示在该关键字所在的方法.运算符或 get 访问器是迭代器.   通过使用 yield 定义迭代器,可在实现自定义集合类型的 IEnumer ...

  4. Android中对JSONArray数组的指定项进行删除,更新。

    首先假设有这么一个JSONArray JSONArray Array1;JSONArray ITEM = new JSONArray(); name为你获取要删除的字段名称,IETM就是你删除后得到的 ...

  5. Win7上防火墙开放FTP服务以及ping解决方案(zz)

    1.windows 防火墙开放ftp服务 The following 4 steps will allow both non-secure and SSL FTP traffic through fi ...

  6. [CareerCup] 3.2 Min Stack 最小栈

    3.2 How would you design a stack which, in addition to push and pop, also has a function min which r ...

  7. HoloLens开发手记 - Unity之World Anchor空间锚

    World Anchor空间锚提供了一种能够将物体保留在特定位置和旋转状态上的方法.这保证了全息对象的稳定性,同时提供了后续在真实世界中保持全息对象位置的能力.简单地说,你可以为全息物体来添加空间锚点 ...

  8. 阿里客户端工程师试题简析——Android应用的闪退(crash)分析

    1. 问题描述 闪退(Crash)是客户端程序在运行时遭遇无法处理的异常或错误时而退出应用程序的表现,请从crash发生的原因分类与解决方法.在出现crash后如何捕捉并分析异常这两个问题给出自己的解 ...

  9. powerdesigner 绘制表关系和导出sql

    1.生成图(A图,B图) 2.创建关系(palette工具栏里有个线条,主表子表关系连接即可,拖动是由顺序的,一对多即从A表往B表连接) 3.这里小说一下   一开始是CDM模式,可以在软件最顶层看到 ...

  10. Android--TextView 文字显示和修改

    一. 新建一个Activity 和 Layout 首先在layout文件夹中新建一个activity_main.xml,在新建工程的时候一般默认会新建此xml文件,修改其代码如下: <Relat ...