Repository: openai/gym

Issue:
[Bug Report] Action space seeding hangs due to memory constraints
**Describe the bug**
When seeding Dict action spaces, gym hangs.

**Code example**
```
from gym.spaces import Dict, Discrete, MultiDiscrete

space = Dict(a=Discrete(4), b=MultiDiscrete([6, 6, 6, 6, 6, 6]))

space.seed(1626)
```

**System Info**
Describe the characteristic of your environment:
 * Gym=0.21 (pip)
 * Windows 10 Enterprise H202
 * Python 3.9

**Additional context**
![image](https://user-images.githubusercontent.com/5785856/182115904-d6ef4fc5-709d-4c78-969a-f781cf505b60.png)

### Checklist

- [x] I have checked that there is no similar [issue](https://github.com/openai/gym/issues) in the repo (**required**)



Discussion:
The same memory issues can occur on mac, so this is not just a windows issues. 

As `np_random.choice()` will generate in memory `np.arange(2147483647)` this could be a speed issue as well.
In addition, in testing, as we use `np.iinfo(int).max` and the size of `int` can vary on different systems, @olipinski has `int32` and my mac has `int64`, any solution should use a standardised `np.intXX` value. 


Resolving patch:
diff --git a/gym/spaces/dict.py b/gym/spaces/dict.py
--- a/gym/spaces/dict.py
+++ b/gym/spaces/dict.py
@@ -101,8 +101,18 @@ def __init__(
         )  # None for shape and dtype, since it'll require special handling
 
     def seed(self, seed: Optional[Union[dict, int]] = None) -> list:
-        """Seed the PRNG of this space and all subspaces."""
+        """Seed the PRNG of this space and all subspaces.
+
+        Depending on the type of seed, the subspaces will be seeded differently
+        * None - All the subspaces will use a random initial seed
+        * Int - The integer is used to seed the `Dict` space that is used to generate seed values for each of the subspaces. Warning, this does not guarantee unique seeds for all of the subspaces.
+        * Dict - Using all the keys in the seed dictionary, the values are used to seed the subspaces. This allows the seeding of multiple composite subspaces (`Dict["space": Dict[...], ...]` with `{"space": {...}, ...}`).
+
+        Args:
+            seed: An optional list of ints or int to seed the (sub-)spaces.
+        """
         seeds = []
+
         if isinstance(seed, dict):
             for key, seed_key in zip(self.spaces, seed):
                 assert key == seed_key, print(
@@ -115,19 +125,9 @@ def seed(self, seed: Optional[Union[dict, int]] = None) -> list:
                 seeds += self.spaces[key].seed(seed[seed_key])
         elif isinstance(seed, int):
             seeds = super().seed(seed)
-            try:
-                subseeds = self.np_random.choice(
-                    np.iinfo(int).max,
-                    size=len(self.spaces),
-                    replace=False,  # unique subseed for each subspace
-                )
-            except ValueError:
-                subseeds = self.np_random.choice(
-                    np.iinfo(int).max,
-                    size=len(self.spaces),
-                    replace=True,  # we get more than INT_MAX subspaces
-                )
-
+            subseeds = self.np_random.integers(
+                np.iinfo(np.int32).max, size=len(self.spaces)
+            )
             for subspace, subseed in zip(self.spaces.values(), subseeds):
                 seeds.append(subspace.seed(int(subseed))[0])
         elif seed is None:
diff --git a/gym/spaces/tuple.py b/gym/spaces/tuple.py
--- a/gym/spaces/tuple.py
+++ b/gym/spaces/tuple.py
@@ -41,7 +41,16 @@ def __init__(
         super().__init__(None, None, seed)  # type: ignore
 
     def seed(self, seed: Optional[Union[int, List[int]]] = None) -> list:
-        """Seed the PRNG of this space and all subspaces."""
+        """Seed the PRNG of this space and all subspaces.
+
+        Depending on the type of seed, the subspaces will be seeded differently
+        * None - All the subspaces will use a random initial seed
+        * Int - The integer is used to seed the `Tuple` space that is used to generate seed values for each of the subspaces. Warning, this does not guarantee unique seeds for all of the subspaces.
+        * List - Values used to seed the subspaces. This allows the seeding of multiple composite subspaces (`List(42, 54, ...)`).
+
+        Args:
+            seed: An optional list of ints or int to seed the (sub-)spaces.
+        """
         seeds = []
 
         if isinstance(seed, list):
@@ -49,19 +58,9 @@ def seed(self, seed: Optional[Union[int, List[int]]] = None) -> list:
                 seeds += space.seed(seed[i])
         elif isinstance(seed, int):
             seeds = super().seed(seed)
-            try:
-                subseeds = self.np_random.choice(
-                    np.iinfo(int).max,
-                    size=len(self.spaces),
-                    replace=False,  # unique subseed for each subspace
-                )
-            except ValueError:
-                subseeds = self.np_random.choice(
-                    np.iinfo(int).max,
-                    size=len(self.spaces),
-                    replace=True,  # we get more than INT_MAX subspaces
-                )
-
+            subseeds = self.np_random.integers(
+                np.iinfo(np.int32).max, size=len(self.spaces)
+            )
             for subspace, subseed in zip(self.spaces, subseeds):
                 seeds.append(subspace.seed(int(subseed))[0])
         elif seed is None:


Test patch: