03-23-2006 10:59 AM
Thank you for the correction Wile-E.!
I appreciate the correction.
For those that have not seen it yet, please read my BLOG entry "he that loveth him chasteneth him "
that can be found in the LabVIEW Champions BLOG page found here.
http://forums.lavag.org/blog/champions/index.php?
Ben
03-23-2006 11:32 AM - edited 03-23-2006 11:32 AM
OK testing indicates that I stay with the LV2 version.
Here is a screen shot of my benchmarking.
Stay tuned!
Ben
Message Edited by Ben on 03-23-200611:33 AM
03-23-2006 12:27 PM - edited 03-23-2006 12:27 PM
Hi Ben, Hi all,
This is what I call a great and very interesting thread... Thanks Ben for
sharing your experience and observations.
What surprises me is that you chose to use a global (wich in my opinion is not
the appropriate tool for this) just because of speed conciderations, am I wrong
?
And now, you aparently decided to come back to FGV - but still because of speed
conciderations...
Is you application such time critical that you need to worry about a fistfull
of u-seconds ?
I am not sure about how works global variables but I assume that it is
duplicated many times in memory and so I am not surprised that problems occur
when you read it from many different parts of your app.
Only concidering the description of your "stop process" I would have
chosen a notifier or queue, I think an empty queue would be nice in terms of
"coding style", no ?
An queue queue read in all your loop, with a "preview queue" to read
and get the "timeout" output to know if the loop has to stop ; like
this you can put anything in your queue that doesn't matter since it will never
be read, just the information that "something" is in will be the stop
source.
Message Edité par TiTou le 03-23-2006 07:32 PM
We have two ears and one mouth so that we can listen twice as much as we speak.
Epictetus
03-23-2006 01:03 PM
HI Titou,
See my replies inserted into your text.
--------------------------------------------------------------------------------------------------------
This is what I call a great and very interesting thread... Thanks Ben for sharing your experience and observations.
[Ben] Thank you and you are welcome!
What surprises me is that you chose to use a global (wich in my opinion is not the appropriate tool for this) just because of speed conciderations, am I wrong ?
[Ben] Yes sir! I am devloping a "crazy" application. We are up 30,000 "channels" with sample rates that vary from 1-1000 Hz.
And now, you aparently decided to come back to FGV - but still because of speed conciderations...
Is you application such time critical that you need to worry about a fistfull of u-seconds ?
[Ben] Yes Sir! When completed, this application will have to settle arguements about which part of the system failed to what they were supposed to do and when. Portions of the 30,000 channels will be coming from descrete systems that need to interact with each other as specified. In the final phases all of the contituents of the system I will be monitoring will be syncronized via IRIG-B and crystal clocks.
I am not sure about how works global variables but I assume that it is duplicated many times in memory and so I am not surprised that problems occur when you read it from many different parts of your app.
[Ben] Good observation, stay tuned.
Only concidering the description of your "stop process" I would have chosen a notifier or queue, I think an empty queue would be nice in terms of "coding style", no ?
An queue queue read in all your loop, with a "preview queue" to read and get the "timeout" output to know if the loop has to stop ; like this you can put anything in your queue that doesn't matter since it will never be read, just the information that "something" is in will be the stop source.In addition, with a Release Q with "destroy queue" to false in each loop, you are sure that the queue will be destroyed only after all your VIs have read it... isn't wonderful ?
[Ben] Yes that is a valid approach but again see my comments above on performance. The dynamic loading of components into this application makes that approach a little more cumbersome. The top level VI will at some time become "fixed" while I will have to develop new components at a future date. I can dictate that the "Global stop" wil always be there when I have to deploy future components.
BTW, there are my results... I am really surprised that global are so fast to read and Q so slow...
[Ben] Yes, a factor of 100 can not be ignored. That is why I broke my rule about "not using globals" just to pick up that performance delta. But like I said, stay tuned!
Ben
03-23-2006 02:15 PM
We have two ears and one mouth so that we can listen twice as much as we speak.
Epictetus
03-24-2006 12:05 PM
Final Update (?)
After testing and personally witnessing the results this is what we found.
1) Globals are still evil. Eliminating these got rid of "Finished Late" issue due to dragging windows around. The theory is that the global reads are using the UI thread.
2) One of the 600+ VI's was passing a bad "Period" value into one of the timed loop sub-VI's. This is what caused the "Finished Late" issue when that module was used.
3) The remaining failing module will be restructured to stream line its processing.
General observations:
1)Contrary to the benchmark work that compares the LV2 with the traditional global, there was very little difference between using the two methods. That implies (to me) that vey little of actual processing work involved determining if it is time to shut down. Concidering the problem the globals caused by running in the UI thread (not sure on this detail) the better performance of the globals was of no use.
2)It looks like the "Finished Late", "Expected End" and "Actual End" reflect the results of the previous iteration of the timed loop (This distrurbed the data flow paradigm part of me).
Once again, I thank you for sharing your ideas.
Ben
03-24-2006 04:12 PM - edited 03-24-2006 04:12 PM
Functional global variables can be more efficient than ordinary global variables because they do not use transfer buffers. Functional global variables exist only within the execution thread and do not use transfer buffers, unless you display their values on an open front panel."
For a description of what a "transfer buffer" is and how it is used as LabVIEW switches between the execution and user interface thread, the following was taken from the same source as the quote above:
"Completing user interface actions uses more memory because LabVIEW switches from the execution thread to the user interface thread. For example, when you set the Value property, LabVIEW simulates a user changing the value of the control, stopping the execution thread and switching to the user interface thread to change the value. Then LabVIEW updates the user interface data and redraws the control if the front panel is open. LabVIEW then sends the data back to the execution thread in a protected area of memory called the transfer buffer. LabVIEW then switches back to the execution thread. The next time the execution thread reads from the control, LabVIEW finds the data in the transfer buffer and receives the new value."
For the complete LabVIEW 8 help page from which the quoted information above was taken (and below), here's the title and link:
Title: VI Execution Speed
Link: http://zone.ni.com/reference/en-XX/help/371361A-01/lvconcepts/vi_execution_speed/
Further, I believe the statement "Functional global variables exist only within the execution thread and do not use transfer buffers, unless you display their values on an open front panel." draws the contrast between "things that live in the user interface thread" (in this case local and global variables) and "things that live in the execution thread" (in this case noting functional globals as a relevant contrasting example). Thus, in general we are drawing a distinction between things which live in the UI thread but don't necessarily cause a swap to the UI thread immediately (local and global variables), other things which do cause a thread swap immediately (property nodes), and yet other things which don't cause a thread swap to the UI thread at all (functional globals - assuming a front panel isn't open displaying their values).
Best regards and have a great weekend!
JLS
Message Edited by JLS on 03-24-2006 04:19 PM
03-25-2006 09:19 AM
Thank for that additional inof.
the phrase "The next time the execution thread reads from the control, LabVIEW finds the data in the transfer buffer and receives the new value."
still leave me wondering "in which thread is the 'finding the data in the transfer buffer and recieves the new value' performed.
My experiments mentioned previously seem to confirm that this happen in the UI.
So True or False ?
The UI thread is used to read a global.
Thank you,
Ben
03-25-2006 09:53 AM
03-25-2006 10:45 AM - edited 03-25-2006 10:45 AM
HI Gurdas,
I think I can help with part of your Q's. See my replies inserted in your text.
"
Message Edited by Ben on 03-25-2006 10:46 AM