Showing results for 
Search instead for 
Did you mean: 

Synchronised finite duration analog input and output DAQ in nested for loops too slow

Go to solution

Hi all - first time posting here so I hope I'm following the protocol.


What I want to do: capture the acoustic pressure distributed an area by using LabVIEW to repeatedly: 1. move a robot arm into position then, 2. transmit a number of sinusoidal signals at different frequencies and, 3. capture the transmitted signal with a microphone (attached to the robot arm).


A material will be placed between the transducer and the microphone and the result of the test will be the effect of the material on the pressure field spatial distribution as a function of frequency.


What I have: I have two nested for-loops: the outer loop indexes through an array of positional coordinates to control the robot arm while the inner loop indexes through an array of waveforms. Data capture is triggered by the onset of the transmission and both the read and write VIs are set to "Finite sample" mode. The attached VI is a simplified version.


In the complete version a column array is saved to disk in a binary file in the format:

["Position 1 index", "Signal 1 index", "Signal 1", ..., "Signal N index", "Signal N", ..., "Position N index", "Signal 1 index", "Signal 1", ..., "Signal N index", "Signal N"]


The problem: For typical values - number of positions (measNo) = 14641; number of transmitted signals (wavesNo) = 41; sample rate = 100-200 kHz and #s = ~400 - this is taking me ~8 hours despite being <20 minutes of transmission time in total.


I'm sure it's because of the many, many task creations and destructions but I haven't a clue how to proceed.


Can you help me speed things up?


Few things to note:
1. The DAQ in question is USB 6251 with LabVIEW 2018.
2. No data is being saved in my attached version - this isn't the issue and I can write about 1.5 GB of data to disc in <10 s in binary format.
3. Control of the robot isn't the issue either - the robot arm can move to (121 x 121 =) 14641 points in <30 minutes.
4. I've searched the forum and looked at the white papers but I am very new to LabVIEW and any similar solutions I've come across are above my head at the moment. Patience is appreciated here!



0 Kudos
Message 1 of 13

Don't have time to thoroughly look this over, but

  1. Move Task Creation and Clear outside the loop, slow creating and destroying tasks. Reuse the same task.
  2. Don't use so many local variables, connect terminal directly.




Message 2 of 13
Accepted by topic author pauldaly

Here it is cleaned up for you with a couple notes also.

Message 3 of 13

@RavensFan wrote:

Here it is cleaned up for you with a couple notes also.

Excellent - thank you! Looks like this will shave off ~1 hr 15 mins from the complete solution.


I wonder if you could do me another favour and tell me how long it takes to run for you with "measNo = 121" and "wavesNo = 41", and let me know which DAQ model you are using?



0 Kudos
Message 4 of 13

I'm not using any kind of DAQ device.  So there is no way I can run your code and tell you how long it takes.

0 Kudos
Message 5 of 13

@RavensFan wrote:

I'm not using any kind of DAQ device.  So there is no way I can run your code and tell you how long it takes.

Ah! I might make another thread and see if anyone can run it for me.


Thanks again.

0 Kudos
Message 6 of 13
Accepted by topic author pauldaly

I made a few further mods in the interest of speed improvements.  I can probably try them out soon on a desktop PCIe-6341 using your reduced # total waveforms to generate & acquire (121*41).   See code attached.


Key changes:


1. Entirely removed inner loop!  Instead of predefining 41 distinct waveform chunks (400 samples at 200 kHz) and then starting and stopping 41 times, I defined a single waveform of 41*400 samples and start and stop just once.


2. Consequently, the call to DAQmx Write only gets called 1 time ever, outside the outer loop, instead of 

the 121*121*41 times in your original posting.  (~600k)


3. I commit the tasks once before the loop.  This makes stop/restart cycles execute a bit faster.  Search "DAQmx State Model" for more info.


4. Sync is maintained by sharing a sample clock instead of a start trigger.  This should have no effect on execution speed, I just like doing it this way as a habit because it often extends more cleanly to cases where AO and AI operate on different devices.   I further chose "Falling Edge" polarity for the AI task so you shouldn't need to take the 1 extra AI sample.



-Kevin P

Message 7 of 13

When I ran my modified code here on a PCIe-6341 with measNo=121, wavesNo=41, it took about 10 - 10.5 seconds.  That projects out to about 21 minutes to do your original measNo=14641 (a.k.a. 121*121). 


Your USB device will have some extra timing overhead / latency for the stop/restart cycles.  I think I was in a thread once where it was found to be in the realm of 80 msec or so on whatever USB device was discussed at the time.  Not sure what you'll find on your device but another 80 msec overhead times 14641 cycles would add about another 20 minutes to your duration.


You said you could do 121*121 robot arm moves in < 30 minutes, meaning about 100 msec each.  I would expect some overhead for sequencing and coordinating movements with acquisition, allowing time to send commands and receive confirmation of moves being done.  I'd ballpark that at another 100 msec per cycle for another ~30 minutes.


This brings it down from 8 total hours to less than 2.   ~1 hour is pretty definite (movements and signals), the other hour ~1 hour is estimated overhead (USB task stop/starts, robot arm commands & completion confirmation).  



-Kevin P

Message 8 of 13

Thanks Kevin - this is great. It took me about 12 s to run your modified VI so this is a great time saver.


I can't say I fully understand it (yet) as it has a few features and functions I'm not familiar with but it looks to me like it should fit into the larger project with robot control and data capture to disk.


This also means I likely don't need a new DAQ so perhaps NI aren't as grateful as me Smiley Wink

0 Kudos
Message 9 of 13

I mostly used your code, so I suspect the main "new stuff" would be:


1.  the calls to DAQmx Control to "commit" the two tasks before entering the loop where you'll repeatedly stop and restart them.  On desktop boards, this leads to less work for DAQmx to do during a stop/restart cycle, and faster turnaround time.  It saves some modest # of millisec per cycle.  Mainly important for unusual cases (such as yours, with hundreds of thousands of stop/restart cycles).

     With USB devices, I honestly am not sure what the effect will be.  It might be more dramatic, or it might be negligible.  Neither would shock me.  

     [I just ran my example with and without the commit, using measNo=121.  I saved about 700 msec with the commit, or just under 6 msec per cycle.]


2. The time tracking function calls to "High Resolution Relative Seconds".  This wasn't an important change, just another habit.  These functions give finer time resolution than "Get Date/Time in Seconds", but that isn't needed here where your real run times are long enough that you won't need to care about resolution beyond hours and minutes.


That's about it, except the use of internal signal "/Dev1/ao/SampleClock" which I figure you understand since you were already familiar with another internal signal, "/Dev1/ao/StartTrigger".



-Kevin P

0 Kudos
Message 10 of 13