Dynamically parallel

Hi Folks,

I’m doing some tests of how quickly CAN functions execute in parallel as opposed to series.
I’d like to be able to execute a variable-sized array of commands in parallel just as easily as I would in series. This is what I’m having trouble with.

Here’s how I’m trying to execute them in parallel:

I have a reference to a VI (in this example, the VI just pops up a dialog box and waits for a rendezvous). I’m using the rendezvous to make sure that all the instances have finished executing before I measure the time elapsed.

The trouble I’m having is that LabVIEW won’t execute more than one instance of the VI simultaneously. It is a reentrant VI.

parallel test.zip (24.7 KB)


parallel test.zip (24.7 KB)

Marshall -

Someone once told me that you shouldn’t use a 20 pound speedometer to measure how fast a chicken can run. Are you sure you want to do it this way? Hardcoding it isn’t as pretty, but it will be a more accurate measurement of time.

In order to dispatch in parallel, you need to prepare the VI for re-entrant execution when you load it. This is done by passing “8” to the options input on Open VI Reference. I think you will need to open a reference for every copy you want running in parallel, but I’m not positive.

Sure, I get what you’re saying. I was thinking this would make the code more flexible and easier to maintain, but it may not be worth it.

Any idea what the overhead would be?

I don’t have any hard numbers, but it shouldn’t be that bad. In fact, I use almost exactly this method in a program that I’m working on now. To me, it just isn’t an accurate representation of a typical use case for FRC.

Also, if this method is used incorrectly, it can force LabVIEW to set up and tear down the VI each time the command is called. These are advanced functions, and shouldn’t be thrown around without reason.

As for maintainability, I think it would be much more legible to explicitly have all the VIs plopped down in parallel.

Is the purpose of this to get an idea of the concurrent processing overhead? … or something else?

**

Hi, You only have one VI ref here. You will need a new ref for each VI instance that you want to run. Secondly, you specify to open as a re-entrant VI as the option when opening the reference.
<Hint>Open VI Reference primitive</hint>

Edit: While this is “legal” LabVIEW code, I would recommend against it if you can avoid it. There is some overhead when opening VI’s in this manner. (Dynamic calling) If calling parallel code statically, (IE. Specifying at edit time on the block diagram) the overhead is very minimal.

As others have mentioned, you need to get a new vi ref for each run. What I’d recommend is to in advance, loop through doing the opens and putting the refs into an array, same size as the CAN IDs. Then your timing will not include data space cloning and mgmt overhead. Personally, I’ve only used this a few times, and for profiling, tend to drop the reentrant code N times. If much code is involved, I wrap it into another reentrant subVI. If I need hundreds, I drop ten, make a subVI, and drop ten of those, etc.

Greg McKaskle

Hi again. I just want to add an extra note. The performance of parallel code will greatly depend upon the target. Single core targets will likely not benefit from parallel code. (Massively multi-core targets obviously benefit greatly) The exception would be if a piece of code must wait for a response from another device, then parallel coding MAY benefit. Usually LabVIEW’s compiler can generate more efficient code that is serial then code that is parallel, and therefore, parallel code may potentially be worse in terms of performance. There are a number of articles on the NI site that describe this. Parallel “engines” like what I think you are trying to build can introduce race conditions.