From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Change Poll Frequency of DAQmx Wait Until Task Done?

I have a pulse generation task in which I use the DAQmx Wait Until Task Done function to halt execution until the pulse is over. I started noticing that, when generating few-ms pulses, this function runs longer than it needs to. For example, it would wait 16 ms for the end of a 10 ms pulse. My application makes several hundred of these pulse generation tasks, so a 60% overhead is too much.

 

I measured the time consumed for 100 of these tasks as a function of the pulse length and found that the overhead proceeds stepwise with a period of about 10ms (see graph). This suggests that that's the polling frequency used by Wait Until Task Done.

 

I found a previous discussion of this problem, except for that setup the polling frequency was 100ms: http://forums.ni.com/t5/Multifunction-DAQ/DAQmx-Wait-Until-Done-takes-an-extra-100ms/td-p/373882 . In that thread it was stated without citation (in post #2) that the polling rate is 10 Hz and it cannot be changed. In my case the polling rate is apparently 100 Hz but I can't find that stated on a spec sheet anywhere.

 

My question: What imposes this limitation, and can the poll frequency be changed? It's unclear to me from the previous discussion whether it is due to the hardware used, or the version of the software driver, or something else. I am using a PCI-6602 with the BNC-2121 block, and NI-DAQmx version 9.7.

0 Kudos
Message 1 of 4
(4,423 Views)

Baldwint,

 

This VI is used exactly as you expect it however instead of allowing the task to move one as soon as the task is done it does in fact have a polling rate to sample if the task is complete or not, then waits, then checks again. If you know the duration of time for each iteration you could use the wait (ms) timer and just hard time each iteration of the task could you not?

0 Kudos
Message 2 of 4
(4,397 Views)

Hi baldwint,

 

> For example, it would wait 16 ms for the end of a 10 ms pulse. My application makes several hundred of these pulse generation tasks, so a 60% overhead is too much.

 

Are you reusing a single task and using DAQmx Control Task(Commit) to commit the task up front? That should reduce the overhead compared to creating/reserving/committing a new task each time.

 

> What imposes this limitation... It's unclear to me from the previous discussion whether it is due to the hardware used, or the version of the software driver, or something else. 

 

It's due to the hardware. The PCI-6602's NI-TIO ASIC doesn't support generating an interrupt at exactly the right time to signal DAQmx that a pulse generation task is done. It can generate a TC (Terminal Count) interrupt, but a single pulse generates multiple TC interrupts (for the initial delay and high/low time). Short delays/pulses would cause DAQmx to miss interrupts, so task done for NI-TIO based devices is not implemented this way; instead, DAQmx spawns a thread and polls until the counter is disarmed.

 

The DAQ-STC counters on E Series, AO Series, and S Series, as well as the NI-STC2 counters on M Series and cDAQ-9172 have the same limitation.

 

The NI-STC3 counters on X Series, PCIe/PXIe-6612, and all other CompactDAQ chassis have an interrupt that is suitable for signaling task done, so on those devices, DAQmx uses the interrupt and does not spawn a thread to poll for task done.

 

> It's unclear to me from the previous discussion whether it is due ... the version of the software driver

 

The polling strategy used for NI-TIO/NI-STC2 based devices changed between different versions of DAQmx. I think it's roughly like this:

  • NI-DAQmx 8.6 and earlier: poll every 100 ms
  • NI-DAQmx 8.7-9.4: poll every N ms, where N is based on the initial delay and high/low times
  • NI-DAQmx 9.5 and later: wait N ms, where N is based on the initial delay and high/low times, then poll every 1 ms

> ...can the poll frequency be changed? 

 

Not directly, but you can poll DAQmx Channel >> CO.PulseDone from your code instead of using DAQmx Is Task Done / DAQmx Wait Until Done. When you call DAQmx Stop before the task is done, it will return warning 200010, "Finite acquisition or generation has been stopped before the requested number of samples were acquired or generated," so check for that warning and discard it.

 

Brad

---
Brad Keryan
NI R&D
Message 3 of 4
(4,372 Views)

Thank you, Brad, for a supremely informative posting. It is nice to know the origins of the behavior I'm seeing, and also to know which cards have nicer properties (for future purchasing decisions).


For now I will try to get the best performance possible out of the card I already have, and your suggestion to poll the PulseDone property myself is a great start. I had previously tried polling WaitUntilTaskDone with a timeout of 0, without seeing any advantages - apparently the the distinction between "Task Done" and "Pulse Done" is pretty critical.


First, I remeasured the overhead as a function of the pulse length using my old approach (a single call to WaitUntilTaskDone, with 10sec timeout). This result is plotted in the first image. I'm plotting the total time expected for 100 pulses (blue line), the total wall time actually consumed (green line), and the time consumed by the specific line of code that does the waiting (red line).


Then, by repeatedly polling the PulseDone property as you suggest, I measured the overhead again. This is plotted in the second image. Indeed, this approach results in a much reduced time spent waiting for the end of the pulse (red line), but there is still a large tiered behavior in the wall time for my entire routine (green line). I looked into this using a line-by-line profiler and found that, approximately, the extra time previously eaten up by WaitUntilTaskDone is now being eaten up by the call to EndTask.


Basically what this means is that, by polling PulseDone myself, I can get more puncutal notice of when the pulse is over, but I'm still not able to stop/restart the associated task any faster, and my program is still slow.


I found one way around it, though. My program is written in Python, but if I have LabView open while I run the test, the stepped overhead basically disappears (third image). This is not even rewriting my routine in LabView - it's just having it open in the background, with a blank VI, not doing anything.


So, for now, I guess that's what I'll do - the performance is way better. But is there any way to know what voodoo that LabView is imparting to DAQmx that makes it so much faster?


tk


(thanks for your contribution too, Hockeyjim07. Right, I could just sleep for a known amount of time, but I'd rather have some kind of verification from the driver that the pulse finished successfully.)

 

Download All
0 Kudos
Message 4 of 4
(4,311 Views)