11-24-2015 12:40 PM
Jim,
Glad you got it figured out (though I must confess I haven't studied your method enough to really understand why you are having so much trouble).
I just built and tested a "Clone Tester". My Clone is a "Clock" that ticks once/second for 10 seconds, then repeats. It has two modes of exiting (it monitors two VIGs called Shutdown and Abort) -- if Shutdown is true, it exits when it finishes the 10 seconds, while if Abort is true, it finishes after the current tick. The Clone monitors the time it starts and exits, and returns its Run Time to the caller (for simplicity, I pass in two Arrays of References, one for the Timers, one for the Run Times -- I'm not using the Output connectors of my Clone).
My tester spins up 8 of these, spacing their creating 0.5 seconds apart. It passes in a reference to an array of 8 "Timers" (I use a Gauge Indicator with numbers 0 through 9 on the face), as well as an array of Run Times.
The Tester is configured as a State Machine, and is largely idle until it tells the Clones to stop. When I send either the Shutdown or Abort command, I wait until all the Clones have stopped before I let the Tester exit. I tried varying the time I check on the Clones from 10 times/second to "as fast as I can do it" (no time-out between calls) -- it didn't seem to influence how long the individual clones ran (as measured by calls to the High Resolution Timer when they start and stop). When I test after running 10-40 seconds, each Clone shows that it ran for 1-3 milliseconds less than an integer number of seconds (e.g. 29.9982).
I tried to test under 8 different conditions (I don't think I managed to do all of them):
All of the tests gave essentially the same results -- all the Clones ran (staggered 0.5 seconds apart), all took about the same time (a few milliseconds shy of a whole second), and it didn't seem to matter which combination of options I used. I'll note that I'm not sure I really understand the 0x140 option, so I might not have been using it properly (my code is otherwise unchanged except for the Execution State of the Clone, the Option Flag in the Clone Launcher, and whether or not I'm running the Executable or native VI).
Wait -- I recall you saying something about the launch times of your Clones -- what happens if each clone needs to "hog" the CPU for a bit when it starts? So I added "Generate an array of a million random numbers" to my Clone before it enters its Ticking Clock loop. I only tested the four Development Mode combinations described above, but all four conditions gave similar times -- the loops now took about 20-22 milliseconds more than an integer number of seconds, and no condition seemed any faster or slower than any other.
What does this mean? Darned if I know. What worked for me in the past, namely Pre-Allocated Clones and not using the "Reentrant" option (which I still don't understand)(I'll look at the Example) is simple to code, simple (for me) to understand, and seems to work.
Bob Schor
11-24-2015 12:53 PM
Aha! Now I get it! The NI example uses a single Reference to the Clone and spins them all up with that Reference. I, not being that clever, allocate separate references for each Clone, and carry them through. It made sense when I started doing this (and I must have missed this example four years ago), and (following my old motto), "If It Ain't Broke, Don't Fix It".
BS
11-24-2015 01:27 PM - edited 11-24-2015 01:28 PM
Hi Bob,
Really appreciate your input.
Using multiple refs isn't "wrong" per se, and I believe NI shows this method in the help file as an alternative. It's just a matter of the context and what you're trying to do. If that method is working for you, I agree, better to not mess with it unless it causes trouble.
In our case, I've noticed that when we call the worker threads over and over again, overhead seems to appear. It doesn't grow or look like a memory leak, it just seems that VI server takes a bit to spin up all of the clones.
Using a single ref seems to ameliorate some of the overhead.
Jim