Re: millisecond scheduler and CPU usage
Hi Chris,
Thanks for your answer. I've no idea how to run a process as RTPRIO... But
every tests I did with priorities don't change significantly the results I
got. In the example 1, even with the highest priority, the resolution stays
- as you say - around 10ms.
But when I set the timeout to a interval less than 1ms (example 2), it seems
that a very important change occurs in the way the OS deal with my process.
But how exactly, it's a mystery... Do you thing that there is something to
do with RTPRIO ? Is it a way to check this ?
Regards
Denis
Le 5/01/07 15:25, « [NOM] » <[ADRESSE]> a écrit :
>
> Hi Denis,
>
> I assume, that you run your tests as a process with priority within
> normal scheduling range - not RTPRIO - so your process is subject to
> normal scheduling under the OS (with the resolution somewhere around
> 10ms). On the other hand running app as RTPRIO might cause your
> system stop to respond to other events. I would say, that best
> solution for handling such jobs is to write kernel driver for the
> MIDI device
>
> regards
> Chris
>
> On Jan 5, 2007, at 1:56 PM, Denis Pousseur wrote:
>
>>
>> Hello,
>>
>> Trying to make a real-time scheduler to deal with musical (MIDI)
>> sequencing,
>> I encounter this problem :
>>
>> Basically, my goal is to build a scheduler with a precision of
>> millisecond.
>> Here is two simple test versions of the loop to explain the problem
>> (the
>> test run for 5 seconds) :
>>
>> 1) first, I tried with a timeout of 0.001 second :
>>
>> (defvar *countIterations* 0)
>>
>> (defun run ()
>> (loop with delta = (get-internal-real-time)
>> do
>> (mp:process-wait-with-timeout "" 0.001)
>> (let ((ms (- (get-internal-real-time) delta)))
>> (incf *countIterations*)
>> (when (>= ms 5000)
>> (return)
>> ))))
>>
>> (defun startChrono ()
>> (setf *countIterations* 0)
>> (mp:process-run-function "Chrono" nil #'run))
>>
>> #|
>> RUN =>
>> (startChrono)
>> RESULT (after 5 seconds) =>
>> (values *countIterations*)
>> |#
>>
>> Here I get something like 100 steps by second (*countIterations* is
>> ± 530)
>> when I need 1000... (In fact, with a timeout of 0.01 or 0.001 the
>> result is
>> practically the same)
>>
>> 2) Secondly, I tried with a timeout less than 0.001 second :
>> suddenly, the
>> accuracy becomes really higher but the consumption of CPU resource
>> becomes
>> also very high... (note that the result will be exactly the same
>> with a
>> timeout of 0.00099 or with a timeout of 0.0001).
>>
>> (defvar *countMS* 0)
>> (defvar *bag* nil)
>>
>> (defun run ()
>> (loop with delta = (get-internal-real-time)
>> with prev = 0
>> do (mp:process-wait-with-timeout "" 0.00099)
>> (let* ((ms (- (get-internal-real-time) delta))
>> (interval (- ms prev)))
>> (incf *countIterations*)
>> (when (> interval 0)
>> (setf prev ms)
>> (incf *countMS*)
>> (when (> interval 1) (push interval *bag*))
>> (when (>= ms 5000) (return) ) ) )))
>>
>> (defun startChrono ()
>> (setf *countMS* 0 *countIterations* 0 *bag* nil)
>> (mp:process-run-function "Chrono" nil #'run))
>> #|
>> RUN =>
>> (startChrono)
>> RESULT (after 5 seconds) =>
>> (values *countIterations* *countMS* (reverse *bag*))
>> |#
>>
>> Here the *countIterations* is ± 146.000 (almost 30 iterations for a
>> millisecond) and the *countMS* is ± 4980. Witch means that the
>> millisecond
>> resolution is perfectly correct for more than 99.5% of the time
>> (this is
>> acceptable for what I have to do with).
>> In the *bag* variable you can observe the granularity : the most
>> significant
>> interval is often at the start of the loop (something like 10 or 15
>> ms),
>> after that, the granularity stays in a very acceptable range (most
>> of the
>> time less than 5ms).
>>
>> ****
>>
>> The codes I run with a version derived of this loop give me a very
>> good
>> result. Even when the scheduler is running and has a lot of tasks
>> to do, I
>> can make real-time manipulation of the running sequence,
>> interaction with
>> the CAPI interfaces and menu, generally without serious alteration
>> of the
>> scheduler regularity.
>>
>> The only problem is the consumption of CPU resources : For an Intel
>> Imac
>> dual-core of 1.8 Ghz, something like 30 a 40% of the CPU for the
>> user and ±
>> 50% for the system (as you can see in the Mac activity monitor),
>> just for
>> the loop running without any task...
>>
>> There is something I misunderstand : Why do a simple loop like this
>> consume
>> so many resources ? Is there any solution to limit the CPU usage ?
>> Because
>> the timeout seems not to be the solution, witch other parameter may
>> I adjust
>> ?
>>
>> Any advice greatly appreciated. Thanks !
>>
>>
>> Denis
>>
>>
>>
>>
>>
>> -------------------------------------------------------
>> Denis Pousseur
>> 70 rue de Wansijn
>> 1180 Bruxelles, Belgique
>>
>> Tel : 32 (0)2 219 31 09
>> Mail : denis.pousseur@compositeurs.be
>> Website : http://compositeurs.be/Pousseur
>> -------------------------------------------------------
>>
>>
>>
>>
>>
>>
>
>
>
>
>
-------------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles, Belgique
Tel : 32 (0)2 219 31 09
Mail : denis.pousseur@compositeurs.be
Website : http://compositeurs.be/Pousseur
-------------------------------------------------------
Re: millisecond scheduler and CPU usage
--- Denis Pousseur <denis.pousseur@compositeurs.be> wrote:
>
> Hi Chris,
>
> Thanks for your answer. I've no idea how to run a process as RTPRIO... But
> every tests I did with priorities don't change significantly the results I
> got. In the example 1, even with the highest priority, the resolution stays
> - as you say - around 10ms.
>
> But when I set the timeout to a interval less than 1ms (example 2), it
> seems
> that a very important change occurs in the way the OS deal with my process.
> But how exactly, it's a mystery... Do you thing that there is something to
> do with RTPRIO ? Is it a way to check this ?
>
> Regards
>
> Denis
Hi Denis,
The problem is that there are at least four timers in PC hardware. See
http://www.microsoft.com/whdc/system/CEC/mm-timer.mspx for a discussion of
the issues. Under Windows, the High Performance Event Timer (HPET), is used
for accurate sub-millisecond timing events.
>From your results, it appears that Lispworks is using the default
millisecond-and-above timer, which doesn't have good resolution, until you
specify sub-millisecond timings. Lispworks then appears to shift to a
different method for producing the events. I've used HPET calls under
Windows, under their former guise as MM (Multimedia) timer calls, and I don't
recall them introducing the OS and CPU overheads you've observed.
You may try finding the corresponding high-precision timing calls on each
platform you use and make OS-specific FFI calls from your code. I don't know
if that will cause any undesired interactions with Lispworks code, are you
using native threads in your version of Lispworks, and is the Lispworks
threading model robust enough that problems won't result? I don't know but it
may work out OK. Perhaps you could make the HPET calls in a native C thread
and perform Lispworks callbacks from there.
Alternatively, perhaps Lispworks may be persuaded to change their code to use
HPET equivs, at least on the platforms you need, if they are not doing so
now.
Jeff Caldwell
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com