Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > How to let a loop run for a while before checking for break condition?

Reply
Thread Tools

How to let a loop run for a while before checking for break condition?

 
 
Claudio Grondi
Guest
Posts: n/a
 
      08-27-2006

Sometimes it is known in advance, that the time spent in a loop will be
in order of minutes or even hours, so it makes sense to optimize each
element in the loop to make it run faster.
One of instructions which can sure be optimized away is the check for
the break condition, at least within the time where it is known that the
loop will not reach it.

Any idea how to write such a loop?

e.g.

counter = 2*64

while counter(BUT DON'T CHECK IT THE FIRST ONE HOUR LONG):
... do something ... # and decrease the counter

Thanks for any hint, but in particular if related to timers on the
Windows 2000/XP system I am mainly working with.

What do you think about this idea? Does it make sense?

Claudio Grondi
 
Reply With Quote
 
 
 
 
Diez B. Roggisch
Guest
Posts: n/a
 
      08-27-2006
Claudio Grondi schrieb:
>
> Sometimes it is known in advance, that the time spent in a loop will be
> in order of minutes or even hours, so it makes sense to optimize each
> element in the loop to make it run faster.
> One of instructions which can sure be optimized away is the check for
> the break condition, at least within the time where it is known that the
> loop will not reach it.
>
> Any idea how to write such a loop?
>
> e.g.
>
> counter = 2*64
>
> while counter(BUT DON'T CHECK IT THE FIRST ONE HOUR LONG):


now = time.time()
while time.time() - now < 3600.0 or some_other_condition:
...


The short circuiting of the or will prevent the execution of
some_other_condition.

> ... do something ... # and decrease the counter
>
> Thanks for any hint, but in particular if related to timers on the
> Windows 2000/XP system I am mainly working with.
>
> What do you think about this idea? Does it make sense?



What idea?

Diez
 
Reply With Quote
 
 
 
 
Claudio Grondi
Guest
Posts: n/a
 
      08-27-2006
Diez B. Roggisch wrote:
> Claudio Grondi schrieb:
>
>>
>> Sometimes it is known in advance, that the time spent in a loop will
>> be in order of minutes or even hours, so it makes sense to optimize
>> each element in the loop to make it run faster.
>> One of instructions which can sure be optimized away is the check for
>> the break condition, at least within the time where it is known that
>> the loop will not reach it.
>>
>> Any idea how to write such a loop?
>>
>> e.g.
>>
>> counter = 2*64
>>
>> while counter(BUT DON'T CHECK IT THE FIRST ONE HOUR LONG):

>
>
> now = time.time()
> while time.time() - now < 3600.0 or some_other_condition:
> ...
>
>
> The short circuiting of the or will prevent the execution of
> some_other_condition.
>
>> ... do something ... # and decrease the counter
>>
>> Thanks for any hint, but in particular if related to timers on the
>> Windows 2000/XP system I am mainly working with.
>>
>> What do you think about this idea? Does it make sense?

>
> What idea?

This one you haven't probably got from what I have written.
I thought, that the introductory text gives enough context to be able to
see what I mean, but I was apparently wrong.

The idea is to speed up a loop by using a timer interrupt interfering
with the loop, so that only after the timer interrupt would occur, the
loop will start to check its break condition in each iteration.
No checking of any kind in the loop should happen up to that time to
minimize the number of operations in each iteration within the loop
itself (i.e. the loop more or less won't know, that there is a timer on
its way to change the loops behavior at a later time).

I hope this above helps to understand what I would like to achieve.

Claudio Grondi
 
Reply With Quote
 
Diez B. Roggisch
Guest
Posts: n/a
 
      08-27-2006
> The idea is to speed up a loop by using a timer interrupt interfering
> with the loop, so that only after the timer interrupt would occur, the
> loop will start to check its break condition in each iteration.
> No checking of any kind in the loop should happen up to that time to
> minimize the number of operations in each iteration within the loop
> itself (i.e. the loop more or less won't know, that there is a timer on
> its way to change the loops behavior at a later time).


A while loop has a condition. period. The only thing to change that is
to introduce a uncoditioned loop, and use self-modifying code to make it
a while-loop after that timer interrupt of yours.

But of course that whole thing is a moot point - if shaving mu-secs on
that level is needed for your application, use C or assembly instead.


Diez
 
Reply With Quote
 
Tal Einat
Guest
Posts: n/a
 
      08-27-2006

Diez B. Roggisch wrote:
> > The idea is to speed up a loop by using a timer interrupt interfering
> > with the loop, so that only after the timer interrupt would occur, the
> > loop will start to check its break condition in each iteration.
> > No checking of any kind in the loop should happen up to that time to
> > minimize the number of operations in each iteration within the loop
> > itself (i.e. the loop more or less won't know, that there is a timer on
> > its way to change the loops behavior at a later time).

>
> A while loop has a condition. period. The only thing to change that is
> to introduce a uncoditioned loop, and use self-modifying code to make it
> a while-loop after that timer interrupt of yours.
>

True. Still, if checking the condition is slowing down the loop,
perhaps it could be optimized somewhat by having a timeout set a
boolean flag, thus having the loop check a simpler condition, which may
be faster.

You can have a separate thread time.sleep() for as long as you want,
and then set the flag which the loop's condition checks. This way you
don't call time.time() on every iteration.

Another approach could be partial loop nesting/unrolling, if the
condition doesn't necessarily have to be checked on every iteration.
Just have an outer loop checking the condition, and an inner loop
(possibly unrolled) doing whatever it is your loop does, several times
(2-1000000, optimize for your needs). This just lets you check the
condition less often.

> But of course that whole thing is a moot point - if shaving mu-secs on
> that level is needed for your application, use C or assembly instead.
>

I agree, though those aren't the only alternatives - you could also try
going "half-way" with Pyrex.

- Tal Einat
reduce(lambda m,x:[m[i]+s[-1] for i,s in enumerate(sorted(m))],
[[chr(154-ord(c)) for c in '.&-&,l.Z95193+179-']]*1[3]

 
Reply With Quote
 
Fredrik Lundh
Guest
Posts: n/a
 
      08-27-2006
Diez B. Roggisch wrote:

> A while loop has a condition. period. The only thing to change that is
> to introduce a uncoditioned loop, and use self-modifying code to make it
> a while-loop after that timer interrupt of yours.


or use a timer interrupt to interrupt the loop:

import signal, time

def func1(timeout):

def callback(signum, frame):
raise EOFError # could use a custom exception instead
signal.signal(signal.SIGALRM, callback)
signal.alarm(timeout)

count = 0
try:
while 1:
count += 1
except EOFError:
for i in range(10):
count += 1
print count

for an utterly trivial task like the one in that example, the alarm
version runs about five times faster than a polling version, on my test
machine (ymmv):

def func2(timeout):

gettime = time.time
t_limit = gettime() + timeout

count = 0
while gettime() < t_limit:
count += 1
for i in range(10):
count += 1
print count

</F>

 
Reply With Quote
 
Claudio Grondi
Guest
Posts: n/a
 
      08-27-2006
Diez B. Roggisch wrote:
>> The idea is to speed up a loop by using a timer interrupt interfering
>> with the loop, so that only after the timer interrupt would occur, the
>> loop will start to check its break condition in each iteration.
>> No checking of any kind in the loop should happen up to that time to
>> minimize the number of operations in each iteration within the loop
>> itself (i.e. the loop more or less won't know, that there is a timer
>> on its way to change the loops behavior at a later time).

>
>
> A while loop has a condition. period. The only thing to change that is
> to introduce a uncoditioned loop, and use self-modifying code to make it
> a while-loop after that timer interrupt of yours.
>
> But of course that whole thing is a moot point - if shaving mu-secs on
> that level is needed for your application, use C or assembly instead.


Going to C or assembly addresses the speed, but does not address the
question asked, as the problem of checking a condition in a loop remains
the same (even if at another speed level).

Here some more context to put more light into what I would like to know
about:
any program runs within an operating system and this system (and in
particular Microsoft Windows) does many, many things beside running the
program. The idea is to use the resources wasted in cycles of the CPU
spent on processing the other things anyway for the program itself.
I have only a vague draft of what I would like to achieve so please
don't get what I write here about how I imagine it should be done too
seriously:
I think, that the application can start with an unconditional loop
and tell the operating system to stop this loop and provide a response
when e.g. one hour is over. When that happens a pre-prepared conditional
loop will start (which was waiting to be awoken) assuming the same
environment (values of variables will be preserved, so it is clear where
to continue) as the previous one.

As an intermediate quick and dirty solution for practical use there is
the possibility to let the Python script run into an error or to break
its run with Ctrl+C if it is apparent it is ready (e.g. the first
approach has just saved me 20 CPU minutes of a four CPU hours needing
script and the condition was checking only the value of an iteration
counter so was not a very time consuming one).

Just thought that for sure someone had already the same/similar idea and
might share here an elegant Pythonic solution addressing this issue.

Claudio Grondi
 
Reply With Quote
 
Claudio Grondi
Guest
Posts: n/a
 
      08-27-2006
Fredrik Lundh wrote:
> Diez B. Roggisch wrote:
>
>> A while loop has a condition. period. The only thing to change that is
>> to introduce a uncoditioned loop, and use self-modifying code to make
>> it a while-loop after that timer interrupt of yours.

>
>
> or use a timer interrupt to interrupt the loop:
>
> import signal, time
>
> def func1(timeout):
>
> def callback(signum, frame):
> raise EOFError # could use a custom exception instead
> signal.signal(signal.SIGALRM, callback)
> signal.alarm(timeout)
>
> count = 0
> try:
> while 1:
> count += 1
> except EOFError:
> for i in range(10):
> count += 1
> print count
>
> for an utterly trivial task like the one in that example, the alarm
> version runs about five times faster than a polling version, on my test
> machine (ymmv):
>
> def func2(timeout):
>
> gettime = time.time
> t_limit = gettime() + timeout
>
> count = 0
> while gettime() < t_limit:
> count += 1
> for i in range(10):
> count += 1
> print count
>
> </F>
>


This above is exactly what I am looking for, except it does not work in
Microsoft Windows where the signal.alarm() function is not available.

So now the only thing I would like to know is how to achieve the same
functionality when running Python on a Microsoft Windows box.

Claudio Grondi
 
Reply With Quote
 
Diez B. Roggisch
Guest
Posts: n/a
 
      08-27-2006
Fredrik Lundh schrieb:
> Diez B. Roggisch wrote:
>
>> A while loop has a condition. period. The only thing to change that is
>> to introduce a uncoditioned loop, and use self-modifying code to make
>> it a while-loop after that timer interrupt of yours.

>
> or use a timer interrupt to interrupt the loop:
>
> import signal, time
>
> def func1(timeout):
>
> def callback(signum, frame):
> raise EOFError # could use a custom exception instead
> signal.signal(signal.SIGALRM, callback)
> signal.alarm(timeout)
>
> count = 0
> try:
> while 1:
> count += 1
> except EOFError:
> for i in range(10):
> count += 1
> print count
>
> for an utterly trivial task like the one in that example, the alarm
> version runs about five times faster than a polling version, on my test
> machine (ymmv):


No doubt that changing the flag asynchronously is a gain by delegating
the timing code to the OS. Yet the while loop still has a condition - so
you could as well set a flag in the signal handler an do it like this:

def func3(timeout):
global flag
flag = True
def callback(signum, frame):
global flag
flag = False
signal.signal(signal.SIGALRM, callback)
signal.alarm(timeout)

count = 0

while flag or True:
count += 1


for i in range(10):
count += 1
print count

This is on my machine about 1.5 times slower than func1, but much more
readable especially wrt the OPs request of a condition being evaluated
after a certain timeout, as you don't repeat any code.

And apart from that, the overall gain of performance diminishes the very
moment anything non-trivial occurs in the loops body anyway.

Diez
 
Reply With Quote
 
Fredrik Lundh
Guest
Posts: n/a
 
      08-27-2006
Diez B. Roggisch wrote:

> No doubt that changing the flag asynchronously is a gain by delegating
> the timing code to the OS. Yet the while loop still has a condition -
> you could as well set a flag in the signal handler an do it like this:


if the OP is obsessed with performance, why are you arguing that he
"could as well" use a slower solution ?

> This is on my machine about 1.5 times slower than func1, but much more
> readable


polling a global state flag being "much more readable" than handling an
exception in the usual way? surely you're joking.

are you sure you're posted the code you're writing about, btw. that "or
True" looks a bit suspicious.

</F>

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Triple nested loop python (While loop insde of for loop inside ofwhile loop) Isaac Won Python 9 03-04-2013 10:08 AM
How to let a loop run for a while before checking for break condition? Sorin Schwimmer Python 2 08-29-2006 04:20 AM
How to let a loop run for a while before checking for break condition? Sorin Schwimmer Python 1 08-28-2006 06:03 PM
while loop in a while loop Steven Java 5 03-30-2005 09:19 PM



Advertisments