LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Inefficiency in Waveform Generation VIs

Solved!
Go to solution

I am rebuilding the Basic Function Generator.vi to meet the needs of my generic and variable AO Voltage output module and came across this strange bit of code I thought I would throw out to the community and see what people think.

 

Several of the Waveform Generation VIs have a code segment like this one (clipped from the Basic Function Generator.vi):In-Place Waveform generationIn-Place Waveform generation

Is there an advantage I don't see or understand to building a waveform using an "In Place Element Structure" and "Swap Values"?  Anybody see any issue with just using the "Build Waveform"?

 

FYI, I compared the two methods of injecting the data into a waveform.  When the number of samples in "Y" is 100k, the difference in execution time is 4 orders of magnitude in favor of just using the Build Waveform.

 

 

0 Kudos
Message 1 of 23
(3,205 Views)

You raise a good point.  I did my own test, and with LabVIEW 2018, the Swap method is only 50 times slower (not quite two orders of magnitude) with 100k samples, and with smaller sample sizes, the speeds become less than an order of magnitude (about 1.4 with 100 samples).  Might have something to do with memory management, or else "clever" code that got overlooked ...

 

Bob Schor

0 Kudos
Message 2 of 23
(3,185 Views)

Oh, dear, I'm ashamed to admit it, but when I timed the two methods of adding a large Array into a Cluster (Build Waveform vs In-Place Element Swap with an Empty Waveform), I labeled the two Time Indicators backwards!  The (admittedly-weird-looking) "Swap" method is always faster than Build Array, a Trivial Amount for modest sized Arrays (less than an order of magnitude), but approaching two orders of magnitude when the Array is on the order of 100k elements!

 

Most of the time, it may not matter, but I guess the people who Program LabVIEW for NI's Living really do know what they are doing!!  So the title of this Post should be "An Unusual Efficiency Hidden in the Waveform Generation VIs".

 

Bob Schor

0 Kudos
Message 3 of 23
(3,132 Views)

Hi Bob,

Well now I am curious.  I attached the VI I used to test the efficiency.  I am using the same method used in the Waveform Generation VIs and calling it the swap time. Then I took the exact same inputs and fed them to a Build Waveform cluster.  Each is nestled in a For loop for better averaging.

build waveform.png

Note that I am not appending a waveform.  I am only creating a waveform like the Basic Function Generator.vi.

...Ben

0 Kudos
Message 4 of 23
(3,128 Views)

Here's my version, very similar (I think) to yours, except I do repeats (to try to get out of the "tick noise" of the clocks.  My code is in LabVIEW 2018 -- I'm posting a "visible Snippet", and also the VI.

Build Waveform Test (BS)Build Waveform Test (BS)

Bob Schor

0 Kudos
Message 5 of 23
(3,121 Views)

Hmm -- our code looks suspiciously "the same", except I use a generated array of random numbers, while you use a fixed array of zeros.  I wonder if the LabVIEW Compiler is "optimizing" your code in some way.  I have found (to my chagrin) that designing a benchmark that measures what you want to measure (as opposed to what you told it to measure) can be a bit tricky ..

 

Bob Schor

0 Kudos
Message 6 of 23
(3,117 Views)

Hi Bob,

 

Logically your loops will create similar outputs.  But, I think because the individual loop times are so short (on my computer swap 10^-5s, and build 10^-9s) on average, the OS will not provide you an accurate measure when only measuring a single iteration.  Looping the same function multiple times and measuring the accumulated time will have less error.  

 

Say the measurement of the function is "T" and the error in the High Resolution Relative seconds is "dt", where the value measured is T +/- 2*dt ("2*dt" because there are two High Res readings per  measurement) . Your method adds up N(T +/- 2*dt) and then normalizes to remove N: N(Tswap +/- 2*dt)/N(Tbuild +/- 2*dt).  However, your method assumes T to be much greater than 2*dt.  Unfortunately, I doubt that is the case.  

 

My method only reads the High Resolution Relative Seconds twice per N loops.  My measured time is N*T +/- 2dt.  Divide by the number of iterations and this method results in a timing error per loop of 2*dt/N.  Given large N, the error will be much smaller than T. 

 

I switched mine to use random numbers and still get the same results.

 

Cheers...

0 Kudos
Message 7 of 23
(3,111 Views)

@hieyequeue @bobSchor

Hi Bob,

 

 


Switch the order of operations and see if your benchmarks change. I have seen this effect when I try to benchmark. Or make separate VIs.

 

mcduff

0 Kudos
Message 8 of 23
(3,106 Views)

Hi mcduff,

 

I have witnessed that too.  I had originally swapped the order a couple times and not gotten any different results.

 

I tested one last time.  This time creating a separate set of random number arrays each 100k samples in length for each loop iteration. 

build waveform2.png

With only 16GB of memory I was a bit limited in the number of loops possible since the sample data set data was now so large.  I then set the execution of this VI to match the Waveform Generation VIs and nested it in an external loop for even more iterations.  Even though I saw a small, ~5%, faster performance with the build vs swap, it was not statistically significant irregardless of the order I performed the loops.

 

These results are far from the 4 orders of magnitude I saw initially using a single data array.   It is possible that the auto indexing of the large arrays is the bottle neck here or there is some under the hood optimization when repeatedly building the waveform with the same data.  It is apparent that it is difficult to isolate the build waveform functionality.

 

Since the single array performed much faster in the build method I am sticking with that for my solution.

0 Kudos
Message 9 of 23
(3,078 Views)

@hieyequeue wrote:

Hi mcduff,

 

I have witnessed that too.  I had originally swapped the order a couple times and not gotten any different results.

 

I tested one last time.  This time creating a separate set of random number arrays each 100k samples in length for each loop iteration. 

build waveform2.png

With only 16GB of memory I was a bit limited in the number of loops possible since the sample data set data was now so large.  I then set the execution of this VI to match the Waveform Generation VIs and nested it in an external loop for even more iterations.  Even though I saw a small, ~5%, faster performance with the build vs swap, it was not statistically significant irregardless of the order I performed the loops.

 

These results are far from the 4 orders of magnitude I saw initially using a single data array.   It is possible that the auto indexing of the large arrays is the bottle neck here or there is some under the hood optimization when repeatedly building the waveform with the same data.  It is apparent that it is difficult to isolate the build waveform functionality.

 

Since the single array performed much faster in the build method I am sticking with that for my solution.


I have not installed 2019 yet to test, but can you try the following

  1. Make an indicator for your 2D array after the last frame. (Pass the wire through the last frame and create indicator outside of Flat Sequence.)
  2. Repeat 1 for the two waveforms coming out of the for loop.

Sometimes there are weird compiler optimizations if no wires connected.

 

mcduff

 

EDIT: Just saw this was 2018, we try some things.

0 Kudos
Message 10 of 23
(3,072 Views)