Hi all,
I would like to write an object that generates a deterministic output given a seed. Without the given seed, I’d like it to return the seed that would generate the same output. Furthermore, it should be aware of any manual seed set before its creation. I think I’m close, but I’m not quite there yet. Context: reproducibility of random transforms in TorchIO 1.
I’ve read the docs on reproducibility 3, torch.Generator 3, fork_rng 2, etc., but I might have missed something.
This is some code I’m playing with, called script.py:
import sys
import torch

if len(sys.argv) > 1:
    seed = int(sys.argv[1])
    torch.manual_seed(seed)
    print('Initial seed:', seed)
else:
    print('No initial seed')

def random_stuff(seed=None):
    with torch.random.fork_rng():
        if seed is None:
            seed = torch.seed()
        else:
            torch.manual_seed(seed & (2**63 - 1))
        number = int(1000 * torch.rand(1).item())
    return number, seed

print('random_stuff(seed=None):', random_stuff(seed=None))
nice_number, nice_seed = random_stuff(seed=None)
print('random_stuff(seed=None) to reproduce:', nice_number, nice_seed)
print('random_stuff(seed=42):', random_stuff(seed=42))
print('random_stuff(seed=42):', random_stuff(seed=42))
print('1000 * int(torch.rand(1).item()):', int(1000 * torch.rand(1).item()))
print('Reproduced result:', random_stuff(seed=nice_seed)[0])
print('1000 * int(torch.rand(1).item()):', int(1000 * torch.rand(1).item()))
print()

I call this command:
$ for i in {,,99,99}; do python script.py $i; done      

And get this output, that I have commented:
No initial seed
random_stuff(seed=None): (233, 1238635228448488131)
random_stuff(seed=None) to reproduce: 270 16876508215961374208
random_stuff(seed=42): (882, 42)
random_stuff(seed=42): (882, 42)
1000 * int(torch.rand(1).item()): 154
Reproduced result: 270
1000 * int(torch.rand(1).item()): 771

No initial seed
random_stuff(seed=None): (873, 6207067658288732991)
random_stuff(seed=None) to reproduce: 83 9352679628244516342
random_stuff(seed=42): (882, 42)
random_stuff(seed=42): (882, 42)
1000 * int(torch.rand(1).item()): 591
Reproduced result: 83
1000 * int(torch.rand(1).item()): 20

Initial seed: 99
random_stuff(seed=None): (442, 4463515504174338291)
random_stuff(seed=None) to reproduce: 919 5178903995377210757
random_stuff(seed=42): (882, 42)
random_stuff(seed=42): (882, 42)
1000 * int(torch.rand(1).item()): 103
Reproduced result: 919
1000 * int(torch.rand(1).item()): 970

Initial seed: 99
random_stuff(seed=None): (95, 3538104565691272705)
random_stuff(seed=None) to reproduce: 24 12991252712705207801
random_stuff(seed=42): (882, 42)
random_stuff(seed=42): (882, 42)
1000 * int(torch.rand(1).item()): 103
Reproduced result: 24
1000 * int(torch.rand(1).item()): 970

I would like the first two (and second to last) lines of the 4th block to be the same as the ones in the 3rd block.
Do you know which direction I should follow here? I feel like I should somehow get the “current seed” instead of calling torch.seed(). I’ve tried different things involving e.g. torch.default_generator, with no luck.