05-04-2018 11:51 AM
@ConnerP wrote:
In the case which is discussed in the first link of my original post, I effectively want to utilize a worker thread pool for time critical computation. This involves dequeueing to multiple parallel loops. This can all be handled with a standard old queue setup as detailed in that thread. However, I have come to like the clarity of logic that channel wires offer in regards to passing loop controlling booleans, e.g. last item, abort, etc...
Use a Messenger Channel. Have the Message include the Booleans (Last Item, Abort, etc.) and the Data that you wish to send. Write a sub-VI called "Send Message" that takes the Boolean inputs (with unwired being the default values, of course) and a (required, possibly) Data, which bundles the inputs into the Message Cluster, does a Create Writer, and sends it on its way. I believe I tested that you could send a Message to multiple Listeners and only one would respond (which, as I understand it, is the Behavior you want).
Bob "Channel Wire" Schor
05-04-2018 12:08 PM
Yes, we've seen the other thread, and throwing more and more complex custom code at it is probably not the way to speed things up. Bob already gave you some hints in the other thread. You probably want to rethink this from scratch.
05-07-2018 02:17 AM
@ConnerP wrote:
In regards to the naming, I can only go off of the information that is available to me. The only clear thing is that "Channel Wires" is the all encompassing term for all types of async wires. In the second link within my original post, it states:
The templates that have "Pipe" in their name are non-forkable (except MsgPipe which I hope we rename in the future). All the others can be forked.
This indicates there are two classes of channels: pipes and "not pipes". All of the channel wire templates designed for data transfer (Stream and High Speed Stream) are descendents the more general pipe template. This means they are not forkable, which is the right way to handle things in 99% of the cases. .
You are right, it's not (only) you that caused the naming problem. All confusing was probably my doing. Giving each channel wire a different name (stream, pipe, tag, etc.) is just a terrible idea, especially since each of those names already mean something else. But using only the fist name, pipe, stream, tag, etc., was what made me confused. Anyway, never mind.
@ConnerP wrote:
In the case which is discussed in the first link of my original post, I effectively want to utilize a worker thread pool for time critical computation. This involves dequeueing to multiple parallel loops. This can all be handled with a standard old queue setup as detailed in that thread. However, I have come to like the clarity of logic that channel wires offer in regards to passing loop controlling booleans, e.g. last item, abort, etc...
Since those channel wires are just scripted VI's, with a "special" wire, you can get the exact same clarity of logic (but without the special wire) with a class. You'll lose the automatic type adaption as well, but that should be handled in the engineering phase anyway
.
@ConnerP wrote:
I had hoped there would be a reasonably simple way to modify a Stream or High Speed Stream template to allow forking, so that I could take advantage of the boolean controlling features.
If I had a say in it, those channel wires would have been OO-bases. That way we could have inherited from one of them, and change\enhance\implement our own behavior. But it's not like that (jet anyway).
I'd think those stream channel wires and high speed stream channel wires allow one reader only, because they need to be efficient. So by allowing multiple readers, they would probably need to use entirely different techniques under the hood. This might very well be at the cost of their efficiency.
As you are looking for a multi-listener construction, I'd make something around user events. Mostly because each listener will be a event driven loop. It can also be done with queues or FGV.
05-08-2018 05:50 AM
wiebe@CARYA wrote:As you are looking for a multi-listener construction, I'd make something around user events. Mostly because each listener will be a event driven loop. It can also be done with queues or FGV.
I have a working implenetation with queues using promises as outlined in the other thread. I tried a messenger channel but that has even more lag than doing the FFTs sequentially. I'm happy enough with the function of the promise queue setup even if it isn't the clearest design on the block diagram.
I have yet to play around with LVOOP. Is it possible to split object wires without making a copy? I seem to have gotten that impression somewhere, but it wasn't clear how to implement. Do you have to pack the object in the DVR and use subvis to deref the object and call methods? That sounds like a lot of overhead.
05-08-2018 06:08 AM
@ConnerP wrote:
I have yet to play around with LVOOP. Is it possible to split object wires without making a copy? I seem to have gotten that impression somewhere, but it wasn't clear how to implement. Do you have to pack the object in the DVR and use subvis to deref the object and call methods? That sounds like a lot of overhead.
Splitting wires won't always make a copy, the compiler will prevent that when possible.
The trick is to make the copy cheap. That can be done with DVR's (not recommended). When all the private data of the object is queue references, the copy won't be overhead.
I don't see how in your situation, how the copy would cause overhead. The init method should create queue(s). Then the class wire is split before entering critical loops. The critical loops use send\receive method VI's to get\set stuff on\off the queue. There won't be expensive copies. Except for the VI call overhead (you can make the VI's inlined), the solution would perform exactly the same as using raw queue's. But it will be a lot clearer, since those queue wires are contained in a class wire. It can be made (at least) as efficient as a as a channel wire.
As a bonus (you'll lose the possibility to inline), you could make an interface parent, and multiple children. You can easily switch between different implementations.