通过矢量化符号优化程序

时间:2014-02-23 18:51:21

标签: performance matlab optimization performance-testing

大家好我正致力于图像处理,并在 MATLAB 中编写了一小段代码。代码很慢。

我在这里提供我的代码片段

for i=1:10
    //find c1,c2,c3
    //c1 c2 and c3 change at each iteration

    u = (1./((abs(P-c1))^m) + 1./((abs(P-c2))^m) + 1./((abs(P-c3))^m));
    u1 = 1./((abs(P-c1))^m)./u;
    u2 = 1./((abs(P-c2))^m)./u;    
    u3 = 1./((abs(P-c3))^m)./u;
end

让我在这里解释变量:

P,u,u1,u2 and u3 are all matrices of size 512x512
c1,c2 and c3 are constants of dimension 1x1
m is a constant with value = 2

我想在循环中重复这个操作(比方说10次)。但是我的代码很慢。

剖析器的结果如下:

该计划的总运行时间为4.6秒。然而,上面列出的四个步骤本身占80%的时间。

enter image description here

所以我想让我的代码运行更快我的第一次编辑

我更改的代码段

for i=1:10

    //find c1 and c2
    //c1 and c2 changes at each iteration

    a=((abs(P-c1))^m); 
    b=((abs(P-c2))^m); 
    c=((abs(P-c3))^m);

    x=1./a; y=1./b; z=1./c;
    u = (x + y + z);
    u1 = x./u;
    u2 = y./u;    
    u3 = z./u;
end

现在程序在2.47秒内计算上述步骤的计算时间如下:

enter image description here

所以这比我的第一种方法快得多。

第二次修改     因为我= 1:10         //找到c1,c2,c3         // c1 c2和c3在每次迭代时都会发生变化

    a=(P-c1).*(P-c1); 
    b=(P-c2).*(P-c2); 
    c=(P-c3).*(P-c3);

    x=1./a; y=1./b; z=1./c;
    u = (x + y + z);
    u1 = x./u;
    u2 = y./u;    
    u3 = z./u;
end

现在程序计算时间为0.808秒。

上述四个步骤非常快速地计算出来。

enter image description here

我相信它可以做得更快。你能帮助我进一步优化 我的代码。 对于大于512的矩阵,如1024,2048或类似物,它将非常有用。

提前致谢。

2 个答案:

答案 0 :(得分:1)

第一个建议是:

如果 m = 2 并且没有变化,为什么不尝试这些替代方案:

A*A

如果 m = 2 ,那么你真的需要 abs 吗?

你正在做的这部分

1./a

a.^(-1)

所以我认为这部分没有更好的选择。

你可以尝试的另一件事就是这个。而不是:

x=1./a; y=1./b; z=1./c;
    u = (x + y + z);
    u1 = x./u;
    u2 = y./u;    
    u3 = z./u;

你可以拥有:

    u = (x + y + z);
    u1 = 1./(a.*u);
    u2 = 1./(b.*u);    
    u3 = 1./(c.*u);

这种方式我想通过删除3个变量来加快一点。但代码变得不那么可读了。

答案 1 :(得分:1)

您当前的代码是:

a=((abs(P-c1))^m); 
b=((abs(P-c2))^m); 
c=((abs(P-c3))^m);

x=1./a; y=1./b; z=1./c;
u = (x + y + z);
u1 = x./u;
u2 = y./u;    
u3 = z./u;

首先,要认识到绝对值函数是乘法的。所以|AB| = |A|x|B|。现在,abs(P-C1)^m相当于abs( (P-C1)^m )

初步看一眼它表明瓶颈中的一些计算可以重复使用。具体来说,由于c1c2c3是常量,如果您尝试重用它们(以牺牲额外内存为代价),计算可以加快一点。

temp_P2 = P*P;
temp_PCA = P*ones(size(P));
temp_PCB = ones(size(P))*P;

a = abs(temp_P2 - c1*temp_PCA - c1*temp_PCB + c1^2 * length(P))

temp_PCAtemp_PCB的计算也可以避免,因为乘以常数矩阵总是等于构造具有常数行或列的秩1矩阵。

我并不认为任何这些修改都会加快您的代码速度,但绝对值得尝试。