The MacView

Virtual Instrumentation from a Mac perspective

Thursday, April 01, 2010

Threading using Queues

I found something unexpected today. I had written a VI to generate a report of the linkages between files in the LabVIEW distribution. It was a quick and dirty VI that basically did the following:

1. Find all the VIs, Controls, Classes, Libraries, Projects, etc. in the LabVIEW distribution

2. Read the linkage information from the file

3. Write out a report on the file

Here is a simplified version of what I was doing:

With this method, LabVIEW pegged the CPU at 100%. Well, LabVIEW pegged one of my four CPUs at 100%. That's great because I can do other things, but I'd like this to finish as soon as possible. So I broke the three tasks into three separate loops that communicate through Queues. Below is the code:

My code went from using 100% CPU to 250% to 270% CPU.

To use Queues to increase your threading, you need to be able to break up your code into tasks that can be run simultaneously. Usually if you are waiting for I/O, that is a good task. Here I have three disk operations (Directory Listing, Read From File, Write To File). It turns out the slowest of these is reading the linkage information from the file. So much so that the Queue of Paths stays full and the Queue of information to write remains close to empty. To help improve performance in a case like this, you can set a maximum Queue size (on the Path Queue in my case). I set the maximum size to 1,000 Paths. So the Read Link loop would always have no more than 1,000 Paths waiting for it. When it takes a Path from the Queue, the Directory Listing loop wakes up and puts another Path in the Queue.

One trick is to figure out how to end the loops. With many of the LabVIEW APIs, you can loop until the Read operation returns an error, and in the Write loop, just close the reference. With Queues that doesn't work because you may close the Queue with data still in it (1,000 Paths, for instance). So instead we send some invalid data that we would not otherwise send (Not A Path in the Path Queue instance). When each loop finishes stuffing data into the Queue, it puts an invalid element in the Queue. Then the loops that read from the Queue know to stop when they see invalid data.

I hope using this can improve the performance of your VIs. If you have any questions or improvements, please leave them in the comments.

Labels: , , , , ,


Blogger Mathieu said...

Might not make sense, but what if you would have two loops, therefore use 2 CPU to compute each half of the linkage information. Would that be even faster?

Thursday, April 01, 2010 1:17:00 PM  
Blogger Marc said...

If you can break a step into two steps, it might improve performance. Some things in LabVIEW force you to go to the User Interface Thread, so if you have two tasks that are almost exclusively UI Thread actions, you won't really get any additional threading. That happens to be the case for me.

I'd say, save a copy of your VI off somewhere (or in source code control) and then try it. If it improves performance, keep it. If not, revert to your backup.

Thursday, April 01, 2010 1:25:00 PM  
Blogger Jim said...


You might know this, but the technical term for this is "pipelining". There's a good article on optimizing FPGA code that talks about this.

One thing worth noting is that you don't really need queues to implement pipelining. You can simply use a shift register or, better, a feedback node (which doesn't even break up the dataflow). The only complicated part of using SRs or FBNs is that you have to ignore outputs until the loop has iterated the number of times as the number of parallel steps.



Friday, April 02, 2010 11:24:00 AM  
Anonymous Anonymous said...

IS VERY GOOD..............................

Tuesday, April 20, 2010 5:16:00 AM  
Blogger Ivan said...

Hi Marc,

the 64-bit version for Mac is really nice.

I started using it and it makes a difference for large datasets, that simply do not fit in memory with the 32-bit version (reconstructing high resolution 3D volumes from projection scans).

However, I coud not shift all my projects to 64-bit, and the reason is one basic feature is still missing on Mac: basic video input.

So far I relied on the library developed by Christophe Salzmann, QTLIB, which is based on QuickTime. QuickTime is 32-bit, and has been replaced by AV Foundation, thus it will not evolve to 64-bit. There is no chance this solution will ever work on 64-bit Labview. On the other hand I guess it is now high time for Labview to offer basic video features in the standard dev package, just as jpeg or png read/write have been added some time ago.

I would like to promote adding functions such as video read/write with standard codecs for a future version of Labview on Mac. QTLib could serve as a template for developing the basic VIs for handling video (open, close, read frame by frame, append one frame, grab from webcam), which constitute a minimal subset of NI vision library. Such feature could be put forward in the next release of Labview, since there are so many applications nowadays with video. I mean video has become as widespread as PNG and JPEG images, it is really time to catch up.



Wednesday, February 17, 2016 3:06:00 AM  

Post a Comment

<< Home

The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.