Array cross correlation


Recommended Posts

Hello,

Im trying to calculate crosscorrelation between sine signal (base with 1/rev frq) and vibration signal to get vibration response for the 1/rev (unbalance calculation), the vibration signal is very noisy, therefore crosscorrelation is used. 

The code is very simple, see bellow. But it is very slow, it takes around 1s to calculate it within my application. Is there any faster way?

The number of loops is maxci*Vibe_Window_Skut   in my case it is approx 20*100=2 000. The CorrBase is sine function with -1 to 1 amplitude. The  testVibes is also in the range around -1 to +1.

 

Code>>>>>>>>>>>>>>>>>>>>

for (ci=0, ci<= maxci, ci++)
      for (cj=0, cj<=(Vibe_Window_Skut-1), cj++)
         ck = ci+cj
         if (ck > Vibe_Window_Skut)
            ck=ck-Vibe_Window_Skut-1 ///pri preteceni okna se zacne brat od zacatku
         endif  
         Vibe_CrossCorr[ci] = Vibe_CrossCorr[ci] + testVibes[cj]*CorrBase[ck]   ///vypocet krosskorelace
      endfor
   endfor
   Vibe_CrossCorr = Abs(Vibe_CrossCorr)
   v.Vib1rev.AddValue=Max(Vibe_CrossCorr)*Corr_Koef*KoefAkcelerometru  

Link to comment
Share on other sites

DAQFactory scripting, as an interpreted language, is quite slow, however, individual math functions, which are done at a low level, are quite fast.  For example:

for (i = 0, i < numrows(y), i++)
   y[i] += 5
endfor

would be the normal way, in a language like C, to add 5 to every element in the array "y".  However, in DAQFactory this would be quite slow, as you have seen.  Fortunately, in DAQFactory you can do this math with a single line:

y += 5

and DAQFactory will apply it to every element in y and do so very rapidly (sub-millisecond, even for thousands of array elements).

So, the trick is to find ways to avoid the loops.  This sometimes requires some creative functions and/or boolean math.  For example, if I wanted to add 5 to y, but only where y was less than 10, it'd be:

y += (5 * (y < 10))

(y<10) is a Boolean expression and in DAQFactory, like C, evaluates to 1 if true, and 0 if false.  y is an array, so y<10 will return an array of 1's and 0's depending on the corresponding element of y.  When multiplied by 5, this results in an array of 5's and 0's which get added to the original y.  Of course adding 0 does nothing, so the result is adding 5 to y wherever y < 10.

So, to make things faster you need to think about whether you can remove one or both of your loops and replace it will a simpler, single line expression.

That all said, if you have to have loops, consider two things, both of which apply to all programming languages:

1) optimize the innermost loop first as it runs the most times

2) try and remove anything from in the loop that can be precalculated

In DAQFactory, also know that every line takes time, even an if()/endif, so, for example, a simple optimization I'd do is to replace that internal if():

if (ck > Vibe_Window_Skut)
   ck=ck-Vibe_Window_Skut-1 ///pri preteceni okna se zacne brat od zacatku
endif  

with:

ck = iif(ck > Vibe_Window_Skut, ck-Vibe_Window_Skut-1, ck)

iif() is an inline if and returns the 2nd parameter if the first is true, and the 3rd if it is false.

I would then take that further and drop ck altogether since it is only used in one place, and put the expression there. 

 

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.