```
123)
random.seed(= random.random()
r1 123)
random.seed(= random.random()
r2 == r2 r1
```

`True`

Python

Author

Imad Dabbura

Published

April 24, 2023

Pseudorandom number generator is a proxy for truly random number generator. It is not truly random because the numbers generated are determined by an initial value called `seed`

. Therefore, the numbers generated are deterministic if we know the `seed`

. The randomness comes from the value of the seed. In other words, if we set the seed to a fixed number such as `seed = 123`

, then we can guarantee to generate the exact same sequence any time we set the seed to `123`

. For example:

There is no raltionship between the pseudorandom numbers generated, as the plot below shows:

Also, the pseudorandom numbers generated follow standard uniform distribution.

Simple implementation to set the `random_state`

using the seed as well as generating random numbers that follow the standard uniform distribution:

```
rnd_state = None # starting value
def seed(a):
"Set the random state"
global rnd_state
a, x = divmod(a, 30268)
a, y = divmod(a, 30306)
a, z = divmod(a, 30322)
rnd_state = int(x) + 1, int(y) + 1, int(z) + 1
def rand():
global rnd_state
x, y, z = rnd_state
x = (171 * x) % 30269
y = (172 * y) % 30307
z = (170 * z) % 30323
rnd_state = x, y, z
return (x / 30269 + y / 30307 + z / 30323) % 1.0
```

Both `torch`

and `numpy`

fail at creating different random numbers in both the parent and the child processes because both processes have the same random_state, which is used to generate the random number.. But `Python`

works fine because it takes care of changing the random_state in the child process(es) as the code segments below illustrates:

```
if os.fork():
print(f"In parent: {torch.rand(1)}")
else:
print(f"In child: {torch.rand(1)}")
os._exit(os.EX_OK)
```

```
In parent: tensor([0.3910])
In child: tensor([0.3910])
```

```
if os.fork():
print(f"In parent: {np.random.randn(1)}")
else:
print(f"In child: {np.random.randn(1)}")
os._exit(os.EX_OK)
```

```
In parent: [-0.51009584]
In child: [-0.51009584]
```

```
if os.fork():
print(f"In parent: {random.random()}")
else:
print(f"In child: {random.random()}")
os._exit(os.EX_OK)
```

```
In parent: 0.6560074137612377
In child: 0.3243934113820527
```

As a result, we need to be careful when using multiprocessing/threading with pytorch and numpy that requires generating different random numbers in different threads/processes.