03-15-2010 09:06 AM
Hi,
I am setting up a program that communicates with six logic controllers and has to read the system status every 100 ms. We are using OPC datasockets for this, and they appear a little slow.
I have created a uniform comm. method for all controllers, and now I find myself programming this method six times to communicate with each system. I am wondering if this could be done more elegant using the parallel for loop, in which case I would program an exchange once and then have six workers running simultaneously. Since a picture is more clear that a thousand words, what I am asking is this:
Is it possible to replace something like
by
and have this for loop running these tasks in parallel (on different cores / in different threads)?
I have configured the loop to create 8 instances at compile, so I would have 2 instances surplus available at runtime if I find I need an additional system.
The benefits of the method show in the second picture to me are:
* takes less space
* modifications have to be made only once
* less blocks, wires and stuff makes it more clear what's going on.
* flexibility in the actual number of tasks running (8 instances available at runtime)
* if more tasks are required, I need only to update the maximum number of instances and recompile, i.e. no cutting and pasting required.
Unfortunately, I don't have those system available yet, so there's no way to test this. Yet, I would like to know if the above works as I expect - unfortunately the labview help is not completely clear to me on this.
Best regards,
Frans
Solved! Go to Solution.
03-15-2010 01:54 PM
03-15-2010 02:32 PM
Here's how I have approached that:
1... Create a controller (state machine) that handles one device. Everything is stored in shift registers in that VI.
2... Make that controller RE-ENTRANT.
3... Make a copy of that and call it the master.
4... Remove all the code from the master, but keep the front panel as is.
5... Add a DEVICE # to the front panel, to distinguish among the devices.
6... In the diagram of the master, have a CASE structure, based on the DEVICE #.
7... Inside the case, have one of the re-entrant controllers (call it the SLAVE).
8... Pass all inputs from the master terminals, thru the CASE, and into the slave.
9... Pass all outputs form the slave, thru the CASE, and into output indicators.
10... Duplicate the CASE as many times as you need, one for every physical device.
DO NOT CALL the slaves directly from anywhere else. Call ONLY the master, and tell it which slave to operate.
Here is an article which touches on that architecture:
http://culverson.com/state-of-the-machine/
Blog for (mostly LabVIEW) programmers: Tips And Tricks
03-16-2010 04:20 AM
Hi Mark,
I also prefer your preferred method, and I think that's what I have done - but correct me if I am wrong.
My configuration is read from a database and stored in an array; additional devices can be added to the database and the program is created such that after adding a device it rereads the total configuration. As said, the config. info is stored in an array, so the number of rows in this array corresponds to the number of tasks that are required to run in parallel - this number I wire to the "P" terminal of the for loop, which determines the number of workers at run time.
The only thing that you cannot dynamically alter is the number of for loop instances that are available, since this is determined at compile time. Therefore, I set this number a bit higher (now: 😎 that the expected number of tasks (now: 6), so I can add two devices without having to recompile the code.
I hope someone with experience on for loops can comment if this strategy works the way the two of us think.
-----
Hi Steve,
I think I grasp the concept of your solution, however, it is not clear to me how the master can run different tasks in parallel, or would that be accomplished by simply calling the master in parallel several times? If so, then that would still require copy pasting of the master.
Also I appears to me that adding an additional devices requires adjustment in the code, which I think is not a nice thing. I would prefer a solution that allows me do add/remove devices dynamically, at run time... at least up to a certain level. If your solution could do this, then let me know, because as said I do not see how it can at this time.
Thanks for your replies!
Regards,
Frans
03-16-2010 05:26 AM
Here's the actual code which calls four of the devices - yes, there's a loop for each one, but the code here is simple enough that the copy-paste idea is feasible.
If the occurrence is triggered, the loops end, otherwise each loop waits a given time - the time it waits is determined by the state machine itself.
Each loop calls the MASTER. The master, in turn calls a specific instance of the slave.
The slaves are RE-ENTRANT, and return quickly, no matter what they're doing.
If the master is re-entrant also, then the whole system can overlap, although, if the slaves are written well, that is not essential (in my case, anyway).
In my case, there is a max of four devices. You call the master with various other commands to initiate a CAL sequence, for example (not shown). These loops just service the state machine.
Yes, there is waste if they only use 1 device, but the slaves have an IDLE state, and if a slave is in IDLE, it asks to be called every 1000 mSec. The ones that are busier can get called faster if they like - each slave tells it's caller how soon to call back.
Whether this fits your needs, I don't know, but it's an idea.
Blog for (mostly LabVIEW) programmers: Tips And Tricks
03-16-2010 09:36 AM
03-16-2010 09:52 AM
Adding to Steve and Marks postings.
If you can understand what Steve is doing, then you may want to review my Nugget on generating Occurences where i posted demo code that launches a bunch of background threads toward the end goal being able to reacreate a real-world version of an Animusic video.

The narative in that Nugget touches on launching background threads programajicly re-entrancy etc.
Under most situation I use queue to comunicate to/from background threads and have delivered apps that used more than 100 background threads.
Have fun,
Ben
03-16-2010 12:44 PM
03-17-2010 04:31 AM
Dear mfletcher,
First of all: thanks for confirming that my intuition was right in this case.
As for your question on the help: below is a copy/paste from the help on the 'configure parallelism dialog box'
The reason for me doubting if what I programmed would work the way I intended lies in the fact that the help only mentions processors here, which would be interpreted as actual cores. Thus on a dual core machine, the number should be 2.
I think it would be helpful to mention something about threads here, because in some case one would like to have more parallel threads than there are cores in a system.
In mu case I would like to create six threads, which on my dual core processor would be spread over only two cores. Then these six threads run in parallel.I know that in case of heavy math that would not help, but since I am doing communications, which have timeouts and such, and that probably runs smoother in six parallel tasks even though I only have two cores.
Hope this helps in improving the help of the for loop.
Regards,
Frans
03-17-2010 10:35 AM
Frans,
Thanks for your feedback on the help. I should clarify what I said about threads. If the LabVIEW execution system only has four threads, the six loop instances will cooperatively use those four threads. You can configure LabVIEW to use additional threads in your ini file through a utility VI (see below), but you should see how your program performs before changing the number of threads. More threads isn't always better.
Mary Fletcher
LabVIEW R&D
How to change the number of threads in the execution system:
If you are curious, you can look in your ini file to see what was added.