I interpret this as the optional generator can be a Union of a single torch._C.Generator, a list of torch._C.Generator, and NoneType. And the default value if None.
Thus, if we don’t want it to be None, wouldn’t we need to pass in a value?
So in the following line:
torch.manual_seed(1024)
pipe(prompt).images[0]
How come we don’t need to pass in the generator, for example, something like the following?
a_generator = torch.manual_seed(1024)
pipe(prompt, generator=<a union containing a_generator>).images[0]
So torch._C.Generator was the old name of torch. Generator per pytorch issue.
Could Python experts and StableDiffusion library experts enlighten me?
Calling torch.manual_seed(1024) sets the seed for all subsequent PyTorch random number generation operations that are to be executed, regardless of whether they belong to other modules, are part a third-party library, etc. For example, in the snippet below,
torch.manual_seed(1024)
a = random_func1()
b = random_func2()
Variables a and b will evaluate to the same values every time thanks to the first line, and it is not necessary to invoke torch.manual_seed inside random_func1 or random_func2.
Are there configurations some where that enable once execute “torch.manual_seed(1024)” sets the seed for all subsequent PyTorch random number generation operations?
I didn’t understand how and when the returned torch.Generator from this line torch.manual_seed(1024) got passed into the pipe object (through the call() method). If no generator is passed in for the optional generator parameter, then the default value is none according to the torch documentation. So that is why I was thinking may be there is some sort of configuration which automatically assigns the returned generator from the torch.manual_seed(1024) call to the optional parameter in the the call() method for the pipe object.
In the two line code above, a generator returned from the first line is passed in to the pipe() for the generator parameter (i.e. generator=generator).
How come when having this line:
torch.manual_seed(1024)
the generator from this line is automatically assigned to the generator parameter in pipe()?
I am thinking may be torch.manual_seed(1024) returns a global torch.Generator that sets a fixed seed for all torch random number generators, and that some where in the call() or in pipe, something like torch.rand(<some number>) that uses the seed generated by the torch.manual_seed() and that the generator parameter in the call() is not used, thus no need to pass in any generator value.
torch.manual_seed(1024) performs two actions: First, it sets the global PyTorch RNG seed to 1024, so all succeeding operations will be deterministic. Second, as you say, it returns a Generator object that can optionally be used as an argument in RNG methods to explicitly manage determinism. In other words, creating a generator using torch.Generator("cuda").manual_seed(1024) that is thereafter passed to pseudo-random PyTorch functions would yield identical results with simply calling torch.manual_seed(1024) at the beginning of the program and assigning None to the generator keyword argument in relevant functions, as demonstrated below.