d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > 10-50fg For Matlab Code Reduction
Add Reply New Topic New Poll
Member
Posts: 33,701
Joined: Jul 17 2006
Gold: 1,990.00
Jul 18 2012 05:15pm
need help with reducing the time it takes to run this code. it has a lot of nested for loops and concatenating (which prevents preallocations) so i just need some tips on how to reduce the time it takes for the program to run. currently it takes about 1 second to run through each time, however it runs over the course of an audio signal so it loops a thousand times. i basically need help for replacing redundancies, pre-allocations which i have not seen or done, switch vs if-else, built in functions to improve time etc
on the computer im currently on it takes 960 seconds to run and im willing to pay 10-50 fg for useful time-saving improvements.
please note the improvement needs to make a difference. if its technically a time savor but only shaves off .5 seconds out of 960seconds, then its not an improvement worth paying for.


the formulas are given on page 2 of this link if you need it (and can understand what its doing)
http://www.eurasip.org/Proceedings/Ext/SPECOM2006/papers/066.pdf

R2b and R3b are given by equations 4 which comprise the b vector
R2, R3, and R4 are given by equations 5
the h vector is comprised of h1 and h2 and are the solutions to R*h=b (of the form Ax = b where all are matrices) where R is the super matrix formed by the quadrants Q1, Q2, Q3 (=Q2'), and Q4

the predicted sample ps1 and ps2 are given by equation 3

Code
clear all

%Volterra speech filter using covariance extension of linear LMS filter for
%audio compression utilizing periodic delay for long term prediction

%overall goal of the design is to measure the energy of the speech signal in blocks of .02*Fs and for various delay values.
%the energy of these delay blocks are compared in order to find which delay produces
%the minimum energy. This delay block is selected and used to generate a predicted signal
%if the predicted signal has a lower energy of the original signal and the signal generated
%by a linear filter in an acceptable amount of time, then adequate signal
%compression is achieved.

[input_signal,Fs] = wavread('female_german');   %load audio file @8kHz

   %Define filter parameters
   
window = Fs*.02;                                %window size is determined by the number of samples taken in 20 milliseconds
reps = floor(length(input_signal)/window);      %determine number of repitions required to evaluate the entire signal

s = input_signal(1:reps*window);                   %signal with adjusted length
M = 3;                                          %order of the filter
D = 150;                                        %Maximum delay of the signal

   %energy parameters
Eplot_s = s(161:length(s)).*s(161:length(s));
Energy_s = sum(Eplot_s);
error = [];
tdelay = [];
Eplot = [];

tic
for c = 1:reps-1;                               %repeat script to cover the entire length of the signal in blocks of length(window) samples

   %construct R covariance matrices
e = [];
sample = s(1+window*(c-1):window*(c+1));        %sample portion of the file
N = length(sample);                             %number of samples being analyzed

   %the R matrices are derived using the Covariance method of the Volterra
   %series expansion formulas
for d = 10:D
R2 = zeros(M+1,M+1);
R3 = zeros(M+1,M+1,M+1);
R4 = zeros(M+1,M+1,M+1,M+1);
R3b = zeros(1,M+1,M+1);

for i = 1+d:M+1+d
   for l = 1+d:M+1+d
       R2(i-d,l-d) = sum(sample(1+(M+1)+N/2-i:(N)-i).*sample(1+(M+1)+N/2-l:(N)-l));
   end
end

for k = 1+d:M+1+d
   for j = k:M+1+d
       for l = 1+d:M+1+d
           R3(k-d,j-d,l-d) = sum(sample(1+(M+1)+N/2-k:(N)-k).*sample(1+(M+1)+N/2-j:(N)-j).*sample(1+(M+1)+N/2-l:(N)-l));
       end
   end
end

for k = 1+d:M+1+d
   for j = k:M+1+d
       for p = 1+d:M+1+d
           for q = p:M+1+d
               R4(k-d,j-d,p-d,q-d) = sum(sample(1+(M+1)+N/2-k:(N)-k).*sample(1+(M+1)+N/2-j:(N)-j).*sample(1+(M+1)+N/2-p:(N)-p).*sample(1+(M+1)+N/2-q:(N)-q));
           end
       end
   end
end        


   %Construct Q quadrants for R super matrix. Note: when constructing matrices
   %the first value is ommited. eg R2(i,j) --> R(0,:) and R(:,0) are not used
   %for constructing the super matrix. furthermore Q2 = Q3'

Q1 = R2(2:M+1,2:M+1);
Q2 = [];

Q4 = [];
Q4vert = [];


for x = 2:M+1
   q2 = [];    
   
   switch x
   
       case M+1                                %m = sum(i) for i = 1:M-1
   q2(:,:) = R3(x,x,2:M+1);                    %switch statements required to retain column/row form for concatenation
   Q2 = horzcat(Q2,q2);            
   
       otherwise
   q2(:,:) = R3(x,x:M+1,2:M+1);    
   Q2 = horzcat(Q2,q2');                       %concatenate q2 to form Quandrant 2 matrix. size is M x m
   end
   
   for y = 2:M+1
       
       if (y == M+1)|| (x == M+1)              %if else statements in place to retain orientation for concatenation
           q4 = [];
       q4(:,:)=R4(x,x:M+1,y,y:M+1);
       Q4vert = vertcat(Q4vert,q4);
       
       else
       q4 = [];
       q4(:,:)=R4(x,x:M+1,y,y:M+1);    
       Q4vert = vertcat(Q4vert,q4');  
       end
   end
   
   
   Q4 = horzcat(Q4,Q4vert);                    %horizontally concatenate Q4horz M times. this creates the Quadrant 4 matrix of size (M^2) x (M^2)
   Q4vert = [];
end

Rtop = horzcat(Q1,Q2);                          %concatenate first two quadrants, creating the top half of super matrix R
Rbot = horzcat(Q2',Q4);                         %concatenate last two quadrants, creating the bottom half of super matrix R
R = triu(vertcat(Rtop,Rbot));                   %concatenate both halves to form Super matrix R

   %Construct b vector


for i = 1+d:M+1+d
   R2b(i-d,1) = sum(sample(1+(M+1)+N/2-i:(N+1)-i).*sample((M+1)+N/2:(N)));
end



for j = 1+d:M+1+d
   for l = 1+d:M+1+d
       R3b(1,j-d,l-d) = sum(sample((M+1)+N/2:(N)).*sample(1+(M+1)+N/2-j:(N+1)-j).*sample(1+(M+1)+N/2-l:(N+1)-l));
   end
end
   
   
b2 = [];
b1 = R2b(2:M+1,1);                              %first portion of b vector is equal to R2(0,:) and is a column vector

for i = 2:M+1
   for j = i:M+1
   b2_R3(:,:) = R3b(1,i,j);                    %Define subvector such that b2 will retain Mx1 size
   b2 = vertcat(b2,b2_R3);                     %concatenate to construct the rest of the b2 subvector which is equal to R3(0,1,:) ... R3(0,M,:)
   end
end

b = vertcat(b1,b2);                             %concatenate R20 and R30 portion of b vector

   %system is in Ax=b format where A = R, x = h, and b = R0 vectors

h = R\b;                                        %construct h vector


h1 = h(1:M);
hid = M+1;
h2 = zeros(M,M);

for i = 1:M
   for j = i:M
       h2(i,j) = h(hid);                       %split h vector into linear and quadratic sections to derive predicted sample
       hid = hid+1;
   end
end


ps2 = zeros(N+M,1);
ps1 = zeros(N/2,1);

   %perform convolution of h with s to obtain the predicted sample

csample = padarray(sample(N/2+1:N),M,'pre');    %pad convolution sample to account for first M samples

for n = M+1:N/2+M
   ps1(n,1) = sum(h1(1:M).*csample(n-1:-1:n-M)); %linear predicted sample
end

for n = M+1:N/2+M
   for i = 2:M+1
       for j = i:M+1
           ps2a = (h2(i-1,j-1).*csample(1+n-i).*csample(1+n-j));   %quadratic predicted sample
           ps2(n,1) = ps2(n,1) + ps2a';
       end
   end
end
       
psample = ps1(M+1:N/2+M)+ps2(M+1+N/2:N+M);      %predicted sample block

e_block = sample(1+N/2:N)-psample;              %windowed error signal to be concatenated

e = horzcat(e,e_block);                         %concatenate the error block
end

energy_block = e.^2;                            %create energy block for delay minimization
[min_E delay] = min(sum(energy_block(:,:)));    %sum and minimize energy plot and record which delay vector is minimal
tdelay = vertcat(tdelay,delay+10);              %(opional) used to view which delays were sampled for the error signal
error = vertcat(error,e(:,delay));              %construct the error signal using smallest energy vector
Eplot = vertcat(Eplot,energy_block(:,delay));   %construct energy plot using smallest energy vector
countdown = reps-c
end

toc

%generate total Gain of signal given by Energy(s[n])/Energy(e[n])
Energy_e = sum(Eplot);
Gain = sum(Energy_s/Energy_e)              
Gaindb = 10*log10(Gain)
Member
Posts: 32,925
Joined: Jul 23 2006
Gold: 3,804.50
Jul 18 2012 05:27pm
1. do you already know there can be significant time improvement? eg it has to run in under x seconds to get a good grade on an assignment. or are you just hoping it'll go faster for your purposes?
2. have you used a profiler to determine where your bottle necks are?

you're not offering enough for me to go learn your specialized stuff, but if you can narrow down where the problem is, I can try to help you get around it.

This post was edited by carteblanche on Jul 18 2012 05:30pm
Member
Posts: 33,701
Joined: Jul 17 2006
Gold: 1,990.00
Jul 18 2012 05:55pm
Quote (carteblanche @ Jul 18 2012 04:27pm)
1. do you already know there can be significant time improvement? eg it has to run in under x seconds to get a good grade on an assignment. or are you just hoping it'll go faster for your purposes?
2. have you used a profiler to determine where your bottle necks are?

you're not offering enough for me to go learn your specialized stuff, but if you can narrow down where the problem is, I can try to help you get around it.


1) no. ive been programming in matlab for a while now but ive never used it to make programs that take a long time to execute. ive proofed it and found places where i can do matrix multiplication in order to get rid of a for loop and replaced an if else chain with a switch statement, but im not sure if theres any other places which can reduce time. also this is not a graded assignment with an answer im trying to reach. i wrote all of this but because i know i will be programming codes which takes minutes to execute in the future, i need to know tips and changes to my coding habits which can reduce time in my code.

2) no, i dont even know what that is. the code takes most of the time in the second for loop "for d = 10:D" because it runs 100 times in that loop, which is then run 1000 times in the loop above it.

also i added the link incase you wanted to know what was going on but didnt expect anyone to keep up with what im doing here. im more concerned with people understanding the operations the code is doing.

for instance this line: ps2(n,1) = ps2(n,1) + ps2a';

is like the c operator ps2 += ps2a'. to my knowledge matlab doesnt have that operation so instead i used the above line. because pre-compiled built in functions execute faster, id prefer to use it. im mostly asking for corrections like this which i have not implemented or do not know about.
does that make sense?

This post was edited by Kamikizzle on Jul 18 2012 05:56pm
Member
Posts: 32,925
Joined: Jul 23 2006
Gold: 3,804.50
Jul 18 2012 07:12pm
960s = 16 minutes. what you've been referring to (switch instead of if, compound concatenation, etc) are referred to as micro-optimizations. do not worry about that since it'll only increase your speed a few milliseconds, if at all. the interpreter/compiler might auto-optimize it for you and you won't see any benefits at all.

Profiling tools will give you a breakdown and tell you what % of execution time is spent in different functions. this is incredibly vital information if you can't tell what takes time just by eyeballing it. i strongly recommended looking into it.

i dont know anything about the algorithm/math stuff you're using and i dont really care enough to, so i'm only gonna offer some general guidelines:

use the native library functions when possible since they use precompiled C instead of the interpreted matlab.
use a variable to avoid recalculations if possible
determine if everything must be done in sequence or not. if the latter, you can parallelize them in separate threads to utilize multiple processors better. this won't really help if you have a shared bottleneck, but it will help tremendously if you don't

This post was edited by carteblanche on Jul 18 2012 07:12pm
Member
Posts: 9,099
Joined: Nov 23 2002
Gold: 2,911.26
Jul 29 2012 12:56am
A lot of time if you are doing intense computations you run into these time constraints... A lot of time you can save seconds here and there, but if the code requires a lot of computations such as solving ODE's then there is not much you can do. As for the switching and using matrix multiplication MATLAB will still usually use code similar to the ones that you wrote.

With something like this the final goal is voice recognition (not a very streamlined processes) and comparing 2 samples is all they can do in a lab. If it could be speed up they would have a database just like finger prints, but they do not, so i doubt you will be able to speed this up anymore.
Go Back To Programming & Development Topic List
Add Reply New Topic New Poll