LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Removing excessive CPU usuage...

It seems that my application is total CPU hog, the panel screen freezes while the acquistion takes place. Any ideas??
0 Kudos
Message 1 of 7
(5,910 Views)
Fix the problem.

Without seeing the code, noone can know what the problem is. There are probably hundreds of possible causes for this.

Run your code in Highlight Execution debug mode, this may give you a clue.

Be aware of loops without delays in them.

If you can't figure it out, post your code.
0 Kudos
Message 2 of 7
(5,910 Views)
If you are doing buffered acquisition, your tread will wait on AI Read.vi until the desired number of scans to read are in the buffer. I've seen that one happen many times. However, it is not clear exactly what is causing your panel to freeze during an acquisition, that is just one suggestion.

Daniel L. Press
PrimeTest Corp.
www.primetest.com
0 Kudos
Message 3 of 7
(5,910 Views)
Posting an example would definately help us help you.

In the process of creating an exaple, you may end up figuring it out.


First thing, comment out ( put case statement around with a constant feeding the do-nothing case) all of your I/O and see how things run.

If it is not I/O try the number crunching stuff.

If not that then display updates.

If I/O is issue try reducing your acq rate.

Figure out what part is the culprit and we will help you figure out how to kill it.

Ben
Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 4 of 7
(5,910 Views)
Attached is the vi. It seems hog 100% of the CPU utilization, also becasue of this it seems to generate error codes (-10401). Also is the the best solution to display, chart, and soon to be write to file the process?
0 Kudos
Message 5 of 7
(5,910 Views)
The VI in question is using a 100ms delay, where as you are scanning 4 seconds of data at a time.

I would suggest that you reconsider your method for retrieving data.

My first recommendation is to use DAQ Occurrences, if they are supported by your hardware. This ensures synchronous data retrieval (you will only retrieve the data when it has been acquired.)

You can also try increasing your delay to about 4 seconds, this may help. Also, look at the DAQ examples on buffered acquisition. You can try using a circular buffer, but this depends on your implementation.

This should explain why your program is hogging CPU time, you are reading the data as fast as the program will allow it, and not allowing time for the data to be acquired into the buffer (
displaying the data probably takes more than 100ms. So as a first shot remedy, try increasing your delay to 3000 or 3500ms. This will significantly improve performance, but MAY not guarantee data won't be missing.

Good luck
0 Kudos
Message 6 of 7
(5,910 Views)
Christian:

This is a tough one given that you aren't giving us any details or
clues as to what is eating up CPU.

Here are some general rules of thumb to help you improve program
performance:

1) Use the VI profiler to determine where your application is using
the most time. Look for VI's that are called many times and VI's that
use a lot of time per execution. These are the areas of code that you
will want to improve.

Another reason to use sub-vis: If you do not use many sub-vi's it will
be difficult to isolate the particular portion of your code that is
using the largest portion of CPU time.

2) Use the task manager to determine CPU usage patterns. If
multiprocessor, are both CPU's being level loaded or is all the load
on 1 CPU. Does the % usage curve look more or less even or does it do
a lot of spiking?

3) Polled I/O tasks traditionally use the most CPU. If your
application is using polling try to replace this with a DAQ event or
with the Wait for SRQ, or generally with some sort of interrupt driven
scheme. This way CPU usage can go to zero while it's waiting.

4) If you are doing serial communications, don't wait for a message
that is N bytes long to come back from the serial port. Instead
create a serial server while loop that retrieves however many bytes
are currently available in the serial port and dumping this into a
message processing queue. You can then have a separate loop
processing the queue to look for valid messages/data packets. The
message processing queue can be signalled by the actual serial port
loop to determine if a valid message exists using occurrences.

If you put a small time delay in the serial port loop say 10-20 mS and
you allocate a large serial port buffer and you use a 250 mS timeout
on your wait for occurrence, this serial port scheme can run with a
very reasonable CPU% versus waiting for a particular number of bytes
to come through which will peg your CPU until it does or it times out.

5) Try to break up and parallelize your program architecture. Make
sure that unrelated functionalities don't have to wait on each other.
Look at using dynamically launched VI's, parallel while loops, using
queues, notifiers, and occurrences. This will help your code by
allowing each individual functionality to run as fast as it can
without having to wait on other parts.

You must use resource locks and/or semaphores to protect critical
sections of your code when you make it truly multi-threaded. An
example of a critical section may be access to a particular piece of
hardware that can only be controlled by one thread at a time like a
serial port.

You should use occurrences or notifiers to signal between threads
rather than polling. This way you can use a wait on notifier or wait
on occurrence to process new information rather than a tight polling
loop which burns up CPU.
Wait on occurrence and wait on notifier make the thread "sleep" at 0%
CPU while they are waiting. Also signalling using wait on occurrence
or wait on notifier is instantaneous or "atomic" in nature and avoids
the possibility of race conditions occurring between threads.

6)Similar to what is described in #4), make any type of I/O happen
only in it's own while loop if possible and put the results into a
queue or notifier. This way, the hardware I/O will happen at it's
fasted natural speed under LV without interference by unrelated
functionalities. Also, this will simplify the management of the I/O
resource. It should make it possible to avoid using semaphores or
resource locks in many cases.

Example, if you have an image acquisition card, have a loop that just
does capture and sticks the images into a notifier so that all parts
that need a copy of the latest image can use it without interfering
with each other. Don't let different parts of your code call the
image acquisition card because sooner or later, one part will have to
wait on the other part to finish.

You could also do the same example but with a DAQ card or other I/O
type.

7)Look for tight polling loops in your code in general. Any while or
for loop in LabVIEW should have at least a 10mS wait timer in it if
not more. Don't make any loop run any faster than it has to run.
This will leave more CPU available for other loops that have to run
the fastest.

8)A simple thing you can do to improve performance: Get more memory.
Memory is dirt cheap. My home system has 1.5GB that cost me $160
dollars. Stack your test system out as far as the BIOS will allow.
This will reduce memory paging and with enough installed RAM you
should be able to disable virtual memory which will reduce CPU% a fair
amount because the computer won't be swapping pages to disk any more.

9) Another simple thing is to get a faster PC. IBM and Dell are
offering dirt cheap desktops these days that are in the 1.5GHz+ range.
If you have an old 300MHz or worse, it may well be worth a faster PC
vs. your software development cost to optimize the code. Hardware is
almost always cheaper than software.

10) Avoid manipulating large arrays dynamically. Avoid building arrays
in while and for loops. Avoid shift register arrays and strings.
This types of data manipulations are CPU expensive. Pre-allocate
arrays outside of for and while loops and then work on individual
elements. (It would be nice if LV would let you work on arrays with
pointers like you can in C/C++.)

11) Avoid doing unnecessary ANYTHING inside of for or while loops.
Any math or array creation or string manipulation or anything that is
inside a for or while loop will take up many many more times the CPU
total execution time than if it could just be done once before or
after the loop execution.

12) Use consistent data types throughout your diagram. Avoid coercion
dots. These dots occur when LabVIEW if forced to "coerce" your data
from one type to another and it involves extra data manipulation. If
necessary, explicitly convert data types, this is still better than an
implicit coercion. Particularly expensive is coercion of an array.

13) Separate the user interface/graphics display loop from actual
processing, I/O. The update rate for human beings is between 4 and 20
times a second. Any slower and the operator will notice. Any faster
is a waste of processing time because the operator will not see it.
PAL video uses 24 frames a second. NTSC video uses 30 frames/second.

Fancy graphs and charts use a lot of CPU. Don't use anything fancier
than the minimum you need to get your point across.

Use the new event structure that they have for handling button presses
etc. rather than a timing loop. This should use 0% CPU except when
handling an actual event.

14) Disk I/O is another case where you can decouple using queues and
while loops. I discussed this topic in detail in an earlier
discussion thread. To recap, write data in 65536 Byte chunks only.
Use a separate file I/O loop to do this. Create a file queue to dump
data frames into. In the file I/O loop pull out 64K blocks at a time
to write to disk. At the end write the leftover fragment of 64K frame
to disk once. Don't do a lot of little writes to disk. This really
burns up CPU. Exact 64K blocks seem to really improve throughput as
they seem to be the optimum size for DMA moves.

Implementing disk I/O in this asynchronous manner will also help you
greatly if you are writing to disk.

15) To improve disk I/O hardware wise and reduce CPU you can get
faster SCSI hard-drives, and dedicated RAID array controllers to use
with them. Buffer memory for these controllers will also help reduce
CPU usage.

16) If it is possible to perform I/O with your test instrument in such
a way as to make fewer reads or writes and retrieve larger data
buffers each time, then do it. The overhead associated with each I/O
call is much less this way.

17) Some portions of your code may need to be rewritten in C. If you
have done your best to optimize the code but profiling is still
showing certain parts are still using too much time, then look at
recoding them in C. Often times you can gain a 2000% improvement in
performance by recoding in C.

18) Look at string and array manipulations carefully. Often times
there are multiple ways to implement the same task using different
LabVIEW functions. Test the different algorithms using the profiler.
Often you will find that there is a distinct advantage to using one or
another method.

19) Avoid sequence diagrams in your code. This forces LabVIEW to
execute your code in a serial manner which will slow it down. Also it
makes your code much more difficult to understand.

20) Look at ways to combine/simplify operations. Use the complex math
function to perform combined multiplies/divides or adds/subtracts or
logical ANDs or logical ORs. Use array mathematics to perform an
array subtract, add, multiply, divide, OR, or AND, etc. ONCE outside a
loop rather than many times on individual elements inside a loop.

21) Avoid using transcendental functions (log, exp, sin, cosine, x^y,
x^1/y, tan, sec, csc, cot, sinh, tanh, etc.) wherever possible,
especially in loops.

Use a lookup table instead if you know that only discrete angles are
possible.

If given a choice between writing x*x or writing x^2, x*x is much
better because to perform x^2, the computer will first have to
calculate the log of x which involves a polynomial series which will
cost at least 10 to 15 multiplies and then it will have to multiply
the log by 2 and then it will have to perform an exp which will cost
it another 10 to 15 multiplies.

22) Apply "Horner's" algorithm to nested mathematical computations to
reduce the number of multiplies and divides that need to occur. E.g:

1+2x+x^2 =1+2*x+x*x could also be written y=x+1, y2=y*y. In this
simple example 2 adds and 2 multiplies becomes 1 add and 1 multiply.

23) Look for better algorithms for mathematical functions especially
for array mathematics. Usually there is a faster way to do whatever
array math that you are doing.

24) Use integer math wherever possible instead of floating point math.

25) Learn to use boolean math efficiently wherever possible for bit
masks, etc, etc. A lot of people implement this type of code
inefficiently.

Douglas De Clue
LabVIEW developer (now job hunting.. 😞
ddeclue@bellsouth.net


ChristianRoth wrote in message news:<50650000000800000037540000-1027480788000@exchange.ni.com>...
> It seems that my application is total CPU hog, the panel screen
> freezes while the acquistion takes place. Any ideas??
Message 7 of 7
(5,910 Views)