LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Parallel .NET nodes not actually running in parallel unless inside loops

Hi, I'm trying to call two simultaneous .NET calls at the same time from a DLL provided by a 3rd party to interface with their software.  When I called them in parallel (two instances on the block diagram), it would run one, then the other.  These calls took around 20 seconds each so I was trying to halve my wait time.  The vendor assures me that simultaneous calls should work.

 

I've managed to reproduce the problem using standard .NET system calls, so it proves it's not a problem with the vendor DLL, but rather a problem with LabVIEW.  Perhaps some compiler weirdness?  This is LabVIEW 2018 and Windows 10, so it's not an old version of any kind.

 

Here's a screenshot:

Parallel NET call problem.PNG

You can see that the two "Sleep" calls that are on the diagram "plain" take 2 seconds to run, but if I give them each their own FOR loop, they run at the same time for a total of just 1 second.

 

I've replicated this with While loops as well, but other structures don't seem to work (case structures, etc.).

 

Is there any reason this shouldn't be considered a bug inside of LabVIEW?

(VI to demo attached, 2018)

Message 1 of 19
(3,005 Views)

Not that this helps with a solution, but I wanted to confirm I see the same thing in LabVIEW 2019 and Windows 10, and that moving the calls into subVIs and altering reentrancy or execution system didn't change anything for me (although I didn't test all combinations).


GCentral
Message 2 of 19
(2,979 Views)

I recreated this in LabVIEW 2012 and I see the same thing.  Sometimes, the older versions work properly and something gets broken in newer versions but that doesn't seem to be the case here. 

 

I'm not sure if this is a bug or not.  It's definitely weird behavior, to say the least.  I tried putting the Thread.Sleep into a separate VI, changed the execution system, etc.  Nothing made a difference.  I tried putting a for loop around the "plain" nodes.  With a for loop around one of the nodes, still no difference.  Only when both of the nodes have a separate for loop around them do they actually run in parallel.  I wonder if this is more of a .NET issue, maybe a conflict between LabVIEW thread versus .NET thread? 

aputman
------------------
Heads up! NI has moved LabVIEW to a mandatory SaaS subscription policy, along with a big price increase. Make your voice heard.
0 Kudos
Message 3 of 19
(2,858 Views)

Well, it's nice to know it's not just me or my specific version that has the issue.

 

I expect I shall be sending this to NI support and seeing if they deem it CAR-worthy.

0 Kudos
Message 4 of 19
(2,832 Views)

@aputman wrote:

I recreated this in LabVIEW 2012 and I see the same thing.  Sometimes, the older versions work properly and something gets broken in newer versions but that doesn't seem to be the case here. 

 

I'm not sure if this is a bug or not.  It's definitely weird behavior, to say the least.  I tried putting the Thread.Sleep into a separate VI, changed the execution system, etc.  Nothing made a difference.  I tried putting a for loop around the "plain" nodes.  With a for loop around one of the nodes, still no difference.  Only when both of the nodes have a separate for loop around them do they actually run in parallel.  I wonder if this is more of a .NET issue, maybe a conflict between LabVIEW thread versus .NET thread? 


Just guessing here, this is really @rolfk territory.

 

A long time ago I remember reading about LabVIEW's compiler. In short, I recall it stating that it broke down the block diagram into independent "clumps" that could be assigned their own thread. In this strange case presented, it looks like the compiler is only recognizing a specific case(two independent For loops) as separate clumps, and thus, this is the only case that gets its own threads. My money is on some strange compiler optimization.

 

Look inside the old error handler code for this nugget (may no longer be valid.)

Why does this subVI exist?
================
The property nodes for VI Server (used to programmatically control VIs and the value of controls) execute in the User Interface (UI) thread. An optimization in LV's compiler causes a case structure to execute entirely in the UI thread if any case of the case structure uses the UI thread and nothing in the other cases is explicitly unable to run in the UI thread.

 

 

mcduff

0 Kudos
Message 5 of 19
(2,823 Views)

Those .NET nodes execute in the same thread as the calling VI.

 

If you use a CurrentThread property, and than a ManagedThreadID before or after those nodes, you'll get the same thread ID for the first two nodes, and a different one for one of the loops. I get 5\5 15\5. Note though that CurrentThread is static, so it won't be the same thread that the Sleep is running in per se. But CurrentThread seems to be treated the same as the Sleep, so coincidentally it gives some insight.

 

You can pull a few tricks. The VI preferred execution system can be set on a per VI basis. So you can put a copy of the stuff in sub VI's set to Other 1 and Other 2.

 

A timed loop makes the code inside it run in another (new) thread. So you can use that as well to make the parallel stuff run in separate threads.

 

I did not know a simple loop could force a new thread. That's actually not good in my situation...

0 Kudos
Message 6 of 19
(2,795 Views)

I realise reading back that my post was pretty sparse on details, but I tried this


wiebe@CARYA wrote:

Those .NET nodes execute in the same thread as the calling VI. [...]

 

You can pull a few tricks. The VI preferred execution system can be set on a per VI basis. So you can put a copy of the stuff in sub VI's set to Other 1 and Other 2.


with no effect.


GCentral
0 Kudos
Message 7 of 19
(2,785 Views)

@cbutcher wrote:

I realise reading back that my post was pretty sparse on details, but I tried this


wiebe@CARYA wrote:

Those .NET nodes execute in the same thread as the calling VI. [...]

 

You can pull a few tricks. The VI preferred execution system can be set on a per VI basis. So you can put a copy of the stuff in sub VI's set to Other 1 and Other 2.


with no effect.


Same here.

 

I've recently looked into threading, but with a different angle. I give a thread authorization\credentials of another user. It will be my NIDays2019 presentation.

 

Threading is a bit of a mystery. For instance, I found file IO to run in the same thread as the VI. DLL's run in that thread as well (or in the UI thread). But when file IO runs in a VI parallel to a DLL, in uses another (not specified) thread.

 

In this particular example (and a few other), it's definitely weird. Calling the same function might be a factor (or not).

 

I wander if anyone has enough of both high level and low level knowledge of all aspects to completely understand this. And make us understand of course. 

0 Kudos
Message 8 of 19
(2,764 Views)

wiebe@CARYA wrote:

In this particular example (and a few other), it's definitely weird. Calling the same function might be a factor (or not).

Here's a new one...

 

So I put one Sleep in a VI, running in Other 1. Another in Other 2. Parallel execution still takes 2 seconds.

 

Than I replaced one .NET sleep with a Wait (ms). It still takes 2 seconds!

 

So the .NET sleep even competes with the LV wait.

Sleep.PNG

0 Kudos
Message 9 of 19
(2,759 Views)

I think McDuff is correct about clumping.  I think the LabVIEW compiler doesn't have information about the execution time of the .NET nodes, and (thinking they execute quickly) clumps them together so they execute serially.

0 Kudos
Message 10 of 19
(2,741 Views)