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]










share|improve this question


























    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]










    share|improve this question
























      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]










      share|improve this question













      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 10 at 18:36









      Michal Charemza

      19.7k972105




      19.7k972105
























          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





          share|improve this answer




























            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





            share|improve this answer





















              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














               

              draft saved


              draft discarded


















              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

























              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





              share|improve this answer

























                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





                share|improve this answer























                  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





                  share|improve this answer












                  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






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 10 at 18:57









                  roeen30

                  27919




                  27919
























                      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





                      share|improve this answer

























                        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





                        share|improve this answer























                          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





                          share|improve this answer












                          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






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 10 at 18:36









                          Michal Charemza

                          19.7k972105




                          19.7k972105






























                               

                              draft saved


                              draft discarded



















































                               


                              draft saved


                              draft discarded














                              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





















































                              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







                              Popular posts from this blog

                              Xamarin.iOS Cant Deploy on Iphone

                              Glorious Revolution

                              Dulmage-Mendelsohn matrix decomposition in Python