Concurrent tasks deterministically generating pseudo random numbers
up vote
1
down vote
favorite
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]
python python-3.x testing random python-asyncio
add a comment |
up vote
1
down vote
favorite
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]
python python-3.x testing random python-asyncio
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
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]
python python-3.x testing random python-asyncio
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]
python python-3.x testing random python-asyncio
python python-3.x testing random python-asyncio
asked Nov 10 at 18:36
Michal Charemza
19.7k972105
19.7k972105
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
2
down vote
accepted
From the random
module docs:
The functions supplied by this module are actually bound methods of a hidden instance of the random.Random class. You can instantiate your own instances of Random to get generators that don’t share state.
async def random_bytes():
generator = random.Random()
generator.seed(1234)
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
results.append(generator.getrandbits(8))
return results
add a comment |
up vote
1
down vote
You can use random.getstate
and random.setstate
, ensuring that between setting the state, generating the random number(s), and getting the state, you don't yield to another task.
async def random_bytes():
random.seed(a=1234)
state = random.getstate()
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
random.setstate(state)
results.append(random.getrandbits(8))
state = random.getstate()
return results
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
From the random
module docs:
The functions supplied by this module are actually bound methods of a hidden instance of the random.Random class. You can instantiate your own instances of Random to get generators that don’t share state.
async def random_bytes():
generator = random.Random()
generator.seed(1234)
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
results.append(generator.getrandbits(8))
return results
add a comment |
up vote
2
down vote
accepted
From the random
module docs:
The functions supplied by this module are actually bound methods of a hidden instance of the random.Random class. You can instantiate your own instances of Random to get generators that don’t share state.
async def random_bytes():
generator = random.Random()
generator.seed(1234)
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
results.append(generator.getrandbits(8))
return results
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
From the random
module docs:
The functions supplied by this module are actually bound methods of a hidden instance of the random.Random class. You can instantiate your own instances of Random to get generators that don’t share state.
async def random_bytes():
generator = random.Random()
generator.seed(1234)
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
results.append(generator.getrandbits(8))
return results
From the random
module docs:
The functions supplied by this module are actually bound methods of a hidden instance of the random.Random class. You can instantiate your own instances of Random to get generators that don’t share state.
async def random_bytes():
generator = random.Random()
generator.seed(1234)
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
results.append(generator.getrandbits(8))
return results
answered Nov 10 at 18:57
roeen30
27919
27919
add a comment |
add a comment |
up vote
1
down vote
You can use random.getstate
and random.setstate
, ensuring that between setting the state, generating the random number(s), and getting the state, you don't yield to another task.
async def random_bytes():
random.seed(a=1234)
state = random.getstate()
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
random.setstate(state)
results.append(random.getrandbits(8))
state = random.getstate()
return results
add a comment |
up vote
1
down vote
You can use random.getstate
and random.setstate
, ensuring that between setting the state, generating the random number(s), and getting the state, you don't yield to another task.
async def random_bytes():
random.seed(a=1234)
state = random.getstate()
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
random.setstate(state)
results.append(random.getrandbits(8))
state = random.getstate()
return results
add a comment |
up vote
1
down vote
up vote
1
down vote
You can use random.getstate
and random.setstate
, ensuring that between setting the state, generating the random number(s), and getting the state, you don't yield to another task.
async def random_bytes():
random.seed(a=1234)
state = random.getstate()
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
random.setstate(state)
results.append(random.getrandbits(8))
state = random.getstate()
return results
You can use random.getstate
and random.setstate
, ensuring that between setting the state, generating the random number(s), and getting the state, you don't yield to another task.
async def random_bytes():
random.seed(a=1234)
state = random.getstate()
results =
for _ in range(0, 128):
await asyncio.sleep(int(os.urandom(1)[0])/4096)
random.setstate(state)
results.append(random.getrandbits(8))
state = random.getstate()
return results
answered Nov 10 at 18:36
Michal Charemza
19.7k972105
19.7k972105
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242191%2fconcurrent-tasks-deterministically-generating-pseudo-random-numbers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown