Search code examples
performancematlablabview

Improving speed of Matlab script in Labview


I have an issue with a Matlab script running in Labview: it takes 0.5 seconds to run on Matlab and over 10 seconds if called from Labview. I know it's supposed to be slower but well... Could someone have a look at my code to see if there's a way to improve it? I dread writing it in pure Labview...

clearvars
Size0=1024;
Size1=1280;
r=1;
g=1;
b=1;
RedArray=ones(Size0,Size1);
GreenArray=2*RedArray;
BlueArray=3*RedArray;
G1(Size0,:)=GreenArray(Size0,:);
G2(Size0,:)=GreenArray(Size0,:);
G1(1,:)=GreenArray(1,:);
G2(1,:)=GreenArray(1,:);
G1(:,Size1)=GreenArray(:,Size1);
G2(:,Size1)=GreenArray(:,Size1);
G1(:,1)=GreenArray(:,1);
G2(:,1)=GreenArray(:,1);

for(i=2:Size0-1)
  for(j=2:Size1-1)
    if(abs(GreenArray(i-1,j)-GreenArray(i+1,j))<abs(GreenArray(i,j-1)-GreenArray(i,j+1)))
        G1(i,j)=(GreenArray(i,j)+GreenArray(i-1,j))/2;
        G2(i,j)=(GreenArray(i,j)+GreenArray(i+1,j))/2;
    elseif(abs(GreenArray(i-1,j)-GreenArray(i+1,j))>abs(GreenArray(i,j-1)-GreenArray(i,j+1)))
        G1(i,j)=(GreenArray(i,j)+GreenArray(i,j+1))/2;
        G2(i,j)=(GreenArray(i,j)+GreenArray(i,j-1))/2;
    else
        G1(i,j)=(2*GreenArray(i,j)+GreenArray(i,j+1)+GreenArray(i-1,j))/4;
        G2(i,j)=(2*GreenArray(i,j)+GreenArray(i,j-1)+GreenArray(i+1,j))/4;
    end
  end
end
U=zeros(2*Size0,2*Size1);
U(1:2:2*Size0,1:2:2*Size1)=r*RedArray;
U(2:2:2*Size0,2:2:2*Size1)=b*BlueArray;
U(2:2:2*Size0,1:2:2*Size1)=g*G1;
U(1:2:2*Size0,2:2:2*Size1)=g*G2;

Thanks


Solution

  • Try vectorizing those loops. Loops are usually a performance killer, so if you try and vectorize the loops, you may get a performance boost in LabVIEW.

    The loop code can be replaced with:

    [I,J] = ndgrid(2:Size0-1,2:Size1-1);
    ind1 = sub2ind([Size0, Size1], I-1, J);
    ind2 = sub2ind([Size0, Size1], I+1, J);
    ind3 = sub2ind([Size0, Size1], I, J-1);
    ind4 = sub2ind([Size0, Size1], I, J+1);
    
    g0 = GreenArray;
    g1 = GreenArray(ind1);
    g2 = GreenArray(ind2);
    g3 = GreenArray(ind3);
    g4 = GreenArray(ind4);
    
    b1 = abs(g1 - g2) < abs(g3 - g4);
    G1(b1) = (g0(b1) + g1(b1)) / 2;
    G2(b1) = (g0(b1) + g2(b1)) / 2;
    
    b2 = abs(g1 - g2) > abs(g3 - g4);
    G1(b2) = (g0(b2) + g4(b2)) / 2;
    G2(b2) = (g0(b2) + g3(b2)) / 2;
    
    b3 = abs(g1 - g2) == abs(g3 - g4);
    G1(b3) = (2*g0(b3) + g4(b3) + g1(b3)) / 4;
    G2(b3) = (2*g0(b3) + g3(b3) + g2(b3)) / 4;
    

    The first block of code generates a 2D grid of coordinates that span where you're iterating over each pixel in your image. These generate column major indices that represent the +/- 1 offsets horizontally and vertically. The next batch of code generates 5 matrices that sample your green channel at these locations. I also call GreenArray g0 for ease of typing.

    There are 3 if conditions within your inner most loop. Each triplet of code after the g0...g4 code is essentially computing each if statement. We determine which locations satisfy the first if condition and it is stored as a mask in b1. We then use this mask to index into our green channels we created and compute the correct values and place them into the right spots in G1 and G2. This is repeated for the other two if statements and are seen in b2 and b3, which also mutate G1 and G2 at the right spots.

    The resulting operations should mimic what you were doing in the for loops, but it will be a hell of a lot faster as you're vectorizing and eliminating the loops all together.