12-05-2011 01:35 PM
Hello all,
In another thread somehwere on here I talked about getting the smallest buffers possible in order to reduce latency when reading and writing to the DAQ card in a loop. The "10% rule" came up (i.e. setting the I/O buffer size to 10% of the sample rate, for 100ms per buffer) and while this seems to work well on most systems, on some systems I can do significantly better than this, reliably: I can do full Visual Studio 2010 builds while in this loop, using just 20ms buffer sizes, without a single underflow error. This was all on a PCI-6251.
I decided to see if I could do better using a PCIe-6351 board, hoping any latency issues would be lessened by the PCI express bus. Unfortunately, things got much worse. On the same system where using 20ms buffers (at 100kHz sampling) was bullet proof; i.e. I could not get it to fail no matter what load I put on the CPU (a quad core hyperthreaded Xeon), using the same code with the PCIe-6351 could not even get past the startup of my I/O loop without encountering numerous underflow errors. I increased the buffer sizes to 100ms (as recommended by the rule of thumb) but still got occasional underflow errors, even with virtually no load on the PC.
One other issue I noticed when going to the 6351 which surprised me was synchronization; a different application depends greatly on syncronizing the input and output buffers; this worked fine on the 6251, taking into account delay caused by the buffering. The same code fails on the 6351; not with an error code, but the buffers are not syncronized. I haven't done an extensive analysis of this yet (I've been focusing on the first problem above), but it appears the I/O may be out of sync by a partial buffer; at any rate, the behavior is quite different, though querying the cards reports the same size physical buffer in each case, using DAQmxGetBufOutputOnbrdBufSize.
I'm not sure what my question is, other than, "Huh?" The biggest difference I could find on the spec sheets is that the 6351 has more DMA channels, which could only help (though I don't think I need more than what's on the 6251). If anyone could shed any light on this, I'm all ears.
(This was all done using the 9.3.5 drivers that came with the PCIe-6351; I haven't had the time to go through the pain and suffering that is upgrading NI-DAQ drivers yet -- my company has limited bandwidth and, let's face it, 1.3 GB for a simple driver update is ludicrous, not to mention the time it takes to actually install it.)
Solved! Go to Solution.
12-06-2011 02:14 PM
Hi JSA,
Taking a look at your other thread, my first suggestion is to disable regeneration on your output task. In C#, you would use the following:
myTask.Stream.WriteRegenerationMode = WriteRegenerationMode.DoNotAllowRegeneration;
Warning 200015 can only come when you are using regeneration, and it occurs when you write data to the same portion in the output buffer that the device is currently reading from. It does not necessarily indicate that an underflow would occur with regeneration disabled. If you have regeneration enabled (which is the default) then the device will attempt to keep its onboard FIFO (8191 samples) filled with the data that is currently in the output buffer, so you could get extra data transferred to the device before you have the chance to overwrite the previous buffer.
Also, you mentioned that "the I/O may be out of sync by a partial buffer". While I don't have too much to go on here, I wouldn't be surprised if disabling regeneration fixed this problem as well. If you were to transfer a partial buffer of data to the device and then write new data, your output waveform might appear out of synch with where you expected it to be. It's best to just disable regeneration altogether, in which case the output buffer is treated like a FIFO rather than a circular buffer, so you will never output more than expected.
Once you disable regeneration, you will no longer receive Warning 200015 and I believe you potentially will no longer see the synchronization problem. If the write loop cannot keep up with the generation, you will now see error -200290, which is a true underflow error (i.e. no data is present in the on-board FIFO at the time the sample clock is received). If you do encounter error -200290 at rates and buffer sizes that you think are unreasonable, please do post back and I'll be happy to take a look at your code to see if what you are seeing makes sense.
Best Regards,
12-06-2011 03:28 PM
Thanks for the reply John. I'm using C++ so trying the function call DAQmxSetWriteRegenMode(*task, DAQmx_Val_DoNotAllowRegen)has had some positive effect. I'm in the early stages of testing. I'm running everything in loopback mode now; I did have it fail once with no error code; which was odd, but was probably some issue in my code's error handling, and I was trying unrealistically small buffers to try and force the error.
I guess my big misunderstanding was that I didn't know using regeneration increased the chance of an underflow (I've had it enabled for years -- this project goes back many generations, to the old 6036E card). In some situations we don't mind having a buffer repeated; it's better than aborting the task. But if this reduces or eliminates our underflows, disabling regeneration is probably the better alternative.
Thanks again; I'll check the synchronization issue next.