[Python] Parallel Random Number Generation in GIL-Free Python

Discussão em 'Python' iniciado por Stack, Abril 7, 2025.

  1. Stack

    Stack Membro Participativo

    I am doing a reinforcement learning simulation in Python that involves running many episodes and updating the weights of the agent per episode. To speed up the process, I wish to run parallel simulations using random numbers and update the weights in parallel.

    The problem is, I noticed that even when using the experimental GIL-free Python 3.13t, the main bottleneck is in the random number generation. Basically, when I use N threads to run N simulations, it takes N times longer as if the random number generation were not parallelized.

    Here is a simple program to illustrate this:

    import threading
    import time
    import random

    def generate_randoms(n):
    """Generate n random floats between 0 and 1"""
    rng = random.Random()
    for i in range(n):
    rng.random()

    def run_tasks_in_parallel(num_tasks, numbers):
    threads = []
    for i in range(num_tasks):
    t = threading.Thread(target=generate_randoms, args=(numbers,))
    threads.append(t)
    t.start()

    for t in threads:
    t.join()

    if __name__ == "__main__":
    num_tasks = 2
    numbers = [1000000] * 2

    start_time = time.time()
    run_tasks_in_parallel(num_tasks, numbers)
    end_time = time.time()

    print(f"Time taken: {end_time - start_time} seconds")


    The program takes 2 times as long with num_tasks=2 than with num_takes=1. Using numpy.random.default_rng takes even longer. I thought it was a problem of shared random state, so I instantiated an rng for each thread as above, but the problem persisted. I have ruled out Python issues since removing the random number generation above allows for parallelism (n threads do not take n times as long without random number generation).

    Is there a way to parallelize random number generation in GIL-free Python? Why doesn't random number generation (both CPython and Numpy) scale with threads?

    I do not need the threads to share random state (I even prefer them not to), nor do I need thread-safe random number generation. I just need parallel random numbers to speed up my training.

    Continue reading...

Compartilhe esta Página