LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Methods to build an array inside a For Loop.

Let me introduce to you my nested For Loops:  

Timing Test 06 beginnings.JPG

They output a 2D boolean array depending on two 1D boolean arrays of different lengths.  This is all well and good however, in another part of my program, I want this to be a 1D array instead.

 

Idea #1:

"I'll just reshape the array at the end. Simples!"

Timing Test 06 idea 1.JPG

Idea #2:

"Hang on, why am I using three primitives outside the loop when I can use just one inside it along with a shift register?"

Timing Test 06 idea 2.JPG

Idea #2.5:

"Oh, wait... I remember reading somewhere about continuously building an array (with concatenate inputs) inside a loop being a bad thing and quite slow. Let me test this."

 

 

Spoiler

Timing Test 06 FP.JPG

Timing Test 06 BD.JPG

 

Idea #3:

 

"Umm... okay, so actually the second way is faster.  I think if I initialize the shift register first then replace subsets of the array, that might also be better."

Timing Test 06 idea 3.JPG

Spoiler

Timing Test 06b FP.JPG

Timing Test 06b BD.JPG

 

Idea #4:

"Yep - seems much better. (Something to do with LabVIEW not having to constantly allocate more memory on every iteration of the loop)  Looking at this closer, I don't actually need the inner For Loop because of the way I'm handling the arrays.  Try again...!"

 Timing Test 06 idea 4.JPG

Spoiler

Timing Test 06c FP.JPG

Timing Test 06c BD.JPG

 

Conclusion(?) #1:

 

"Well I seem to have arrived at something that looks messier, but executes about 6x faster than my initial idea. That said, the difference rapidly increases as the input arrays get much bigger (becoming orders of magnitude different)."

 

  • Is this the most efficient way of doing what I want?  Or is there something even better (and works in LV 8.5)?


Never say "Oops." Always say "Ah, interesting!"

0 Kudos
Message 1 of 9
(4,427 Views)

Hi J.,

 

you know that in your code from start to idea#3 the inner FOR loop can be completely replaced by a single AND function? This may also speed up your code...

 

But well, using a predefined array in a shift register and ReplaceArraySubset is considered a very fast way. No need for memory allocations in the loop...

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
Message 2 of 9
(4,417 Views)

I would say that your select can probably just be replaced with an AND.  It might be a little slower.  Need to benchmark to make sure.  It would be easier to read though.

 

Other than that, it looks like you've hit all of the tricks I can pick off the top of my head.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 3 of 9
(4,413 Views)

Thank you both for the feedback.  It never occurred for me to recheck the logic after I'd initially extracted the nested For Loops, but the AND gate output is obviously the same now that it's been pointed out!

 

Continuing on with Idea #4, I replaced the Select with an AND then compared the times.  (also meant I didn't have to initialize one of the arrays anymore)

Timing Test 06 idea 5.JPG

 

Spoiler

Timing Test 06d FP.JPG

Timing Test 06d BD.JPG

 

It appears that the AND gate was slower but then I tried with different sizes of initial arrays and in one case, the timings were 'reversed'.

This only happened when the top array (the one that is fed into the AND gate whole) was reduced to a length in the region of 5 elements long.

 

Spoiler

Timing Test 06d2 FP.JPG

Timing Test 06d2 BD.JPG

 

Why does this happen?  Is it something to do with the AND gate possibly being optimised for single element operations so smaller arrays are handled better...?

 

 



Never say "Oops." Always say "Ah, interesting!"

0 Kudos
Message 4 of 9
(4,386 Views)

A few points:

 

  1. It's much easier to read and compare results when they're placed in a single table rather than hidden as part of an image in a spoiler tag.
  2. LV 2012 has an even cleaner way - you can set an output tunnel to concatenate, which I believe should result in the same machine code as the build array method. It won't help you in 8.5 and it may not perform as well as you like, but it is less code and I suppose it's possible NI will try to optimize it.
  3. Don't over-optimize. Generally, unless you have a specific need, you should write the code and find the bottlenecks later.
  4. The Code Capture Tool makes it much easier to create images of LV code.

 


___________________
Try to take over the world!
Message 5 of 9
(4,373 Views)

@tst wrote:

[..]2. LV 2012 has an even cleaner way - you can set an output tunnel to concatenate, which I believe should result in the same machine code as the build array method. It won't help you in 8.5 and it may not perform as well as you like, but it is less code and I suppose it's possible NI will try to optimize it.[...]

 


I benchmarked the concatenate option of the tunnel in 2012 for fun and it outperformes "Build Array" by a factor of 2 on my machine (32bit, Win7) using the initial two boolean array the OP has in his screenshots. So i doubt that the internal optimization leads to the same machine code.

But maybe, i only have some wrong settings in my code so the resulting array is different (haven't checked). If so, benchmark results are not comparable....

 

Norbert

 

EDIT: I expect the difference to grow with increasing array size. My feeling tells me that the tunnel option runs linear while build array starts getting exponetial at a certain array size...

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
Message 6 of 9
(4,349 Views)

With LV 2012, you can use the concatenating tunnel mode:

CCT

Message 7 of 9
(4,331 Views)

@J.Mamakos wrote:

Thank you both for the feedback.  It never occurred for me to recheck the logic after I'd initially extracted the nested For Loops, but the AND gate output is obviously the same now that it's been pointed out!

 

It appears that the AND gate was slower but then I tried with different sizes of initial arrays and in one case, the timings were 'reversed'.

This only happened when the top array (the one that is fed into the AND gate whole) was reduced to a length in the region of 5 elements long.

 

Why does this happen?  Is it something to do with the AND gate possibly being optimised for single element operations so smaller arrays are handled better...?


Look carefully: your logic is quite different between the AND case and the Select case once you remove the inner FOR loop.  Without that inner FOR loop, in the Select case you're using a single boolean to determine which of two arrays to use.  In the AND case, the code must visit every element of the array and do an AND operation on it with the single boolean element.

Message 8 of 9
(4,309 Views)

@nathand wrote:
Look carefully: your logic is quite different between the AND case and the Select case once you remove the inner FOR loop.  Without that inner FOR loop, in the Select case you're using a single boolean to determine which of two arrays to use.  In the AND case, the code must visit every element of the array and do an AND operation on it with the single boolean element.

 

Ah, okay.  For some reason I was thinking (perhaps hoping) that the AND function would see a False boolean on the single element input and immediately know that the answer would be False for every element in the array on the other input.  I take it that it actually sweeps through the whole array doing the calculation for each element(?) which does make sense, really.

 


@tst wrote:

A few points:

 

  1. It's much easier to read and compare results when they're placed in a single table rather than hidden as part of an image in a spoiler tag.
  2. LV 2012 has an even cleaner way - you can set an output tunnel to concatenate, which I believe should result in the same machine code as the build array method. It won't help you in 8.5 and it may not perform as well as you like, but it is less code and I suppose it's possible NI will try to optimize it.
  3. Don't over-optimize. Generally, unless you have a specific need, you should write the code and find the bottlenecks later.
  4. The Code Capture Tool makes it much easier to create images of LV code.

 

 Thank you for the suggestions and advice. I will have a look at the Code Capture Tool as I've heard it mentioned before also.  As for over-optimization, I embarked on this particular endeavor partly as an exercise to see what I could come up with, but I do get your point.

 

 


With regard to the Concatenate Node (in LV2012), that was actually the first thing I instinctively looked for!  But alas, my company is sufficiently behind the times for this little gem not to be available to me.  On the flip side, it meant that I went on this little journey and arrived at something faster anyway.

 

I've settled on using Idea #4, and I've ended up putting the code snippet in its own sub-vi to save space on my already cluttered state machine case.



Never say "Oops." Always say "Ah, interesting!"

0 Kudos
Message 9 of 9
(4,289 Views)