user309575
user309575

Reputation: 41

Skip step in while loop subject to time constraint

I have code which generates many N sequences and stores them. If I make runs large then the loop can get stuck on the while N[j] > 0: section of the code. What is the best way to include something to skip a step in the while loop, say if time exceeds a few seconds in that step in the loop and move to the next?

runs = 20
Lloc = 1
n0 = 1
#Empty list to store N series
N_array = []
#Empty list to store z series
z_array = []
for r in range(0,runs):
        #Set initial z series values to be zero
        z = [0]
        #Set initial jump process values to be n0
        N = [n0]
        #Set iteration to be zero
        j = 0
        #While
        while N[j] > 0:
            z.append(z[j] + np.random.exponential(Lloc/(2*N[j]**2))) 
            #Pick jump at position j+1 to be N[j] -1 or +1 with prob 1/2
            N.append(N[j] + np.random.choice([-1,1]))
            #Update iteration
            j = j+1
        #Store N,z realisation if sum dz < 10 say
        if sum(np.diff(z)) < 10:
            N_array.append(N)
            z_array.append(z)

        #Completion
        print((r+1)/runs*100,'%')

Upvotes: 1

Views: 313

Answers (2)

kosciej16
kosciej16

Reputation: 7128

You can just measure time by yourself!

from time import perf_counter
       #While
        start = perf_counter()
        while N[j] > 0:
            z.append(z[j] + np.random.exponential(Lloc/(2*N[j]**2))) 
            #Pick jump at position j+1 to be N[j] -1 or +1 with prob 1/2
            N.append(N[j] + np.random.choice([-1,1]))
            #Update iteration
            j = j+1
            if perf_counter() - start > TIMEOUT:
                break

Or even use Context for that:

class Timer:
    def __enter__(self):
        self.start = perf_counter()
        return self

    @property
    def elapsed(self):
        return perf_counter() - self.start

    def __exit__(self, exc_type, exc_value, exc_traceback):
        pass

with Timer() as t:
    while True:
        if t.elapsed > TIMEOUT:
            break

As image357 pointed It's not ideal, as we still need to wait until one loop cycle finish what can last very long, but in your case it should be work as expected.

Upvotes: 2

image357
image357

Reputation: 471

I would use something like this:

import time
import multiprocessing as mp

def loop_body(i):
    print(f"sleeping for {i} seconds")
    time.sleep(i)
    print(f"sleep of {i} seconds done")


max_wait_time = 2.1
i = 1
while i < 4:
    proc = mp.Process(target=loop_body, args=(i,))
    proc.start()
    proc.join(max_wait_time)
    proc.terminate()
    i += 1

The idea is to spawn a separate process and wait for a certain amount of time. If the process isn't finished you can terminate it and move on to the next step.

Upvotes: 2

Related Questions