0

So I have been searching far an wide for this. I want to run three functions in parallel, when one finishes return this value, stop the two others.

I have tried with asynciop, multiprocess and concurrent.futures, and I still can not get it to work.

As an example I have a function that returns 0 when above a certain threshold, and some number otherwise. To test my implementation I want to return the last non-zero value.

My problem is that regardless of whatever I try, all three methods complete every time. Instead of breaking when a match has been found.

from concurrent.futures import FIRST_COMPLETED, ThreadPoolExecutor, wait


def first_zero(f, values=[10, 10**2, 10**3]):
    for i in values:
        if f(i) == 0:
            return i
    return values[-1]


def bisect_search(f, first, last):

    if f(first) == 0:
        return first

    middle = (last + first) // 2
    while True:

        # print(middle, "bisect")
        if abs(last - first) <= 1:
            return first

        middle = (last + first) // 2
        if f(middle) > 0:
            first = middle
        else:
            last = middle


def linear_search(f, start, stop, increment):
    i = start
    minimum = min(start, stop)
    maximum = max(start, stop)
    if increment < 0:
        while minimum <= i <= maximum:
            if f(i) != 0:
                return i
            i += increment
    else:
        while minimum <= i <= maximum:
            if f(i) == 0:
                return i - increment
            i += increment
    return i


def linear_binary_search(f, start=0):
    stop = first_zero(f)

    tasks = [
        (linear_search, [f, start, stop, 1]),
        (linear_search, [f, stop, start, -1]),
        (bisect_search, [f, start, stop]),
    ]

    executor = ThreadPoolExecutor(max_workers=len(tasks))
    futures = [executor.submit(task, *args) for (task, args) in tasks]
    done, _ = wait(futures, return_when=FIRST_COMPLETED)
    executor.shutdown(wait=False, cancel_futures=True)
    return done.pop().result()


if __name__ == "__main__":

    import random
    import time

    target = 995

    def f(x):
        time.sleep(0.01)
        if x <= target:
            return random.randint(1, 1000)
        return 0

    # Comment the following line to see
    # how much slower the concurrent version is
    print(linear_binary_search(f))

    stop = first_zero(f)
    print(linear_search(f, stop, 0, -1))
N3buchadnezzar
  • 471
  • 6
  • 11
  • Does this answer your question? [Python: multiprocessing - terminate other processes after one process finished](https://stackoverflow.com/questions/71192894/python-multiprocessing-terminate-other-processes-after-one-process-finished) – BeRT2me May 16 '22 at 00:39

0 Answers0