samedi 10 novembre 2018

Concurrent tasks deterministically generating pseudo random numbers

I have a coroutine that returns a list of pseudo-random bytes

import asyncio
import random
import os

async def random_bytes():
    random.seed(a=1234)
    results = []
    for _ in range(0, 128):
        await asyncio.sleep(int(os.urandom(1)[0])/4096)
        results.append(random.getrandbits(8))
    return results

loop = asyncio.get_event_loop()
task_1 = loop.create_task(random_bytes())
print(loop.run_until_complete(task_1))

As expected, this list is always the same on every run, even though the time interval between each generation is different [based on some external entropy from os.urandom], the pseudo-random number generator is seeded with the same value.

Now, if I run two of these concurrently, creating two lists...

loop = asyncio.get_event_loop()
task_1 = loop.create_task(random_bytes())
task_2 = loop.create_task(random_bytes())
print(loop.run_until_complete(asyncio.gather(task_1, task_2)))

...the lists are always different: the tasks basically interfere with each other, and are no longer deterministic.

How can I have two concurrent tasks of pseudo-random numbers generated, where each list of pseudo-random numbers is just as deterministic as though no other task were running?

[My use case: testing concurrent behaviour, using large amounts of pseudo-random numbers, generated at non-deterministic intervals, but would like the pseudo-random numbers themselves to be the same for each run of the test for each task]

Aucun commentaire:

Enregistrer un commentaire