11-01-2019 03:58 AM
@drjdpowell wrote:
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.
The (brown) "Is Asynchronous?" property gives this information.
This returns "False" for the .NET nodes (probably all .NET nodes).
I think that proves the theory?
11-05-2019 01:30 PM
For the benefit of any future Googlers or forum searchers:
I've received a reply from NI, assigning this a CAR and bug number, 901493. It will be added to the "known issues" list at a later date, so if it's fixed in some future patch or version of LabVIEW you can tell by checking for that number in the notes.
Until then, putting .NET nodes needing parallelism into loops as a workaround will hopefully be enough.
01-09-2020 05:28 PM - edited 01-09-2020 05:51 PM
Actually asynchronous operation is not exactly the same as threading. It is of course related but not the same. An asynchronous node means that LabVIEW can schedule other (asynchronous) code in parallel while it waits for the asynchronous node to finish. It's the parallelization functionality that existed even back in LabVEW 2.x when OS multithreading was far from being common supported functionality.
Mac OS as well as Windows 3.1 had even just cooperative multitasking which meant that applications had to behave properly by calling frequently certain specific OS functions. For both Mac and Windows this were the functions that received the OS events such as mouse and keyboard events, but also things like disk insertion. And an application had no way to allocate threads from the OS to execute certain code in it and let the OS manage fair distribution between them.
Instead LabVIEW nodes can indicate to the compiler if they were asynchronous and the compiler will then create code to start the node and then repeatedly call a HasCompleted? function while executing other "clumps" in between.
It's a bit like the asynchronous VI call with the Start Asynchronous Call node and Wait On Asynchronous Call node, with the Wait having a finite (short) timeout configured and polling the Wait until it returns with another status than timeout, while in the meantime executing other code too.
The Wait methods are for instance asynchronous as well as the TCP IP nodes for instance. Also the VISA read and write nodes can be configured to run asynchronously. The File IO functions in Windows could also be called asynchronous (Windows calls this overlapped) and the old Mac OS also had both synchronous and asynchronous File IO operations but LabVIEW makes no use of that, probably because the Unix Posix file IO API does not have such a mode. The network socket interface on the other hand does have such a mode, which is why the TCP IP nodes can be asynchronous. So asynchronous operation is not equivalent to multithreading but rather in addition to it, or in fact allows LabVIEW to simulate some sort of multithreading even in absence of multithreading support from the OS.
Asynchronous operation in .Net is a feature of the specific .Net API and would need to be implemented by the caller of that API by using asynchronous capable methods. Some APIs support that and in .Net the method for that is called delegate. In LabVIEW this is interfaced with .Net events but LV Register Event Callback can only generate correct callback VIs when the arguments of .NET delegate are of primitive data types, e.g., string, double, etc.
https://forums.ni.com/t5/LabVIEW/Does-LabVIEW-8-support-use-of-net-deligates/td-p/437124
Calling of .Net methods (and property accessors) is always synchronous just as calling shared library functions through the Call Library Node, so the according LabVIEW nodes can NOT implement asynchronous operation itself. Well they could by spawning threads for each call which then waits for the completion but that would cost in most cases more performance than executing them simply synchronously.
01-10-2020 02:59 AM
@rolfk wrote:
...
So, you're saying this can't be fixed? Or shouldn't be fixed?
Or it can be fixed (by making all calls delegates) but this would be undesirable?
01-10-2020 03:35 AM - edited 01-10-2020 03:37 AM
wiebe@CARYA wrote:
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.
Ah yes! This happened to me in a project, i had a simple Wait in a Grab picture loop and the wait was always added to the execution time instead of going in parallel. I don't remember if i got it working with a "Wait until ms-factor" (or whatever it's called) or i actually measured how much time was left in the loop after grabbing the picture and making a Wait on the remainder.
This was in LV2011.
@wiebe if you make a wrapper and have the .net in a sub-vi, does that change the behaviour?
/Y
01-10-2020 04:01 AM
@Yamaeda wrote:@wiebe if you make a wrapper and have the .net in a sub-vi, does that change the behaviour?
/Y
It might, depending on the execution thread of the VI. If it's 'same as caller' perhaps not.
01-10-2020 06:10 AM
Maybe it's enough to set it to reentrant?
/Y
01-10-2020 06:17 AM
@Yamaeda wrote:
Maybe it's enough to set it to reentrant?
/Y
Conceptually, I don't see why that would make a difference. The reentrancy should only provide a DS for each instance, and prevent locking of the execution (e.g. usage of the DS).
But this is complex, the compiler makes choices based on factors and I'm not sure we know them all.
Interesting to toy around with, but I'm over my yak shaving budget for this day (month actually 😁).
01-10-2020 06:56 AM - edited 01-10-2020 07:00 AM
wiebe@CARYA wrote:
@rolfk wrote:
...
So, you're saying this can't be fixed? Or shouldn't be fixed?
Or it can be fixed (by making all calls delegates) but this would be undesirable?
There are several issues here! The fact that .Net nodes seem to be clumped together to always execute in the same thread except with the separate loops is one. This potentially could be fixed but it may have lots and lots of ramifications in the LabVIEW compiler that make it very difficult to solve. The problem of determining if those nodes should be rather parallelized in multiple threads or better be sequentialized is a difficult decision. Generally these nodes should execute quickly so distributing them over multiple threads would often have a negative performance impact on the application. There is no compile time indication from .Net that a method may take longer than a quick invocation so the compiler has to guess if that might be the case but computers are terrible at guessing and that makes this a pretty bad idea.
The fact that .Net nodes are synchronous is not fixable. That's how the beast has to function to be useful. A function call is in terms of threading simply synchronous unless it has special mechanisms such as the overlapped mechanism for certain Windows API functions. Even then the call itself is always synchronous but it will return to the caller before the operation has finished and indicate that in an API specific status. The caller itself is then responsible to do something useful if there is something to do and return back to checking the status later on until the API returns either an error or a successful end of the operation.
.Net methods do not implement such a generic mechanism so LabVIEW can't call them asynchronously. .Net APIs can provide asynchronous functionality in the form of delegates and LabVIEW can interface to a subset of delegates through Event Callbacks. However this is an API specific extension that may or may not (which is for most APIs the case) be present as an optional mechanism. But you have to specifically create the Event Callback VI and call the proper functions to do this kind of asynchronous operation with .Net APIs.