Repository: cupy/cupy

Issue:
Unable to create RandomState with MT19937
Hello,

I work with two versions of scripts that do some math operations. I have a CPU version that works with numpy and a GPU one that works with cupy. I wanted to validate that the code will return the same results when it has the same config. In my code I sometimes need to use some random distributions, therefore ideally I want to set up numpy and cupy in the same way so far as RandomState goes. This is where I encountered a problem - it seems I'm unable to set it up in the same way (same RandomState setup). I wanted to use the MT19937 random state for this comparison. However, on cupy I'm getting the following error when creating the random state :
```
cp.random.RandomState(method=cp.cuda.curand.CURAND_RNG_PSEUDO_MT19937)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/uname/anaconda3/envs/sai/lib/python3.7/site-packages/cupy/random/generator.py", line 56, in __init__
    self.seed(seed)
  File "/home/uname/anaconda3/envs/sai/lib/python3.7/site-packages/cupy/random/generator.py", line 697, in seed
    curand.setGeneratorOffset(self._generator, 0)
  File "cupy/cuda/curand.pyx", line 123, in cupy.cuda.curand.setGeneratorOffset
  File "cupy/cuda/curand.pyx", line 125, in cupy.cuda.curand.setGeneratorOffset
  File "cupy/cuda/curand.pyx", line 86, in cupy.cuda.curand.check_status
cupy.cuda.curand.CURANDError: CURAND_STATUS_TYPE_ERROR
```

My setup is the following (output from `python -c 'import cupy; cupy.show_config()'`):
```
CuPy Version          : 7.3.0  
CUDA Root             : /usr/local/cuda
CUDA Build Version    : 10020
CUDA Driver Version   : 10020
CUDA Runtime Version  : 10020
cuBLAS Version        : 10202
cuFFT Version         : 10102
cuRAND Version        : 10102
cuSOLVER Version      : (10, 3, 0)
cuSPARSE Version      : 10301
NVRTC Version         : (10, 2)
cuDNN Build Version   : 7605
cuDNN Version         : 7605
NCCL Build Version    : 2506
NCCL Runtime Version  : 2506
```
I'm using an Nvidia GTX 980 Ti GPU.

PS: Also I should point out that you should probably update your documentation, since the actual RandomState method enumeration: https://github.com/cupy/cupy/blob/v7.3.0/cupy/cuda/curand.pxd
does not match the method enumeration mentioned in the docs: https://docs-cupy.chainer.org/en/stable/reference/generated/cupy.random.RandomState.html#cupy.random.RandomState


Discussion:
Thank you for the bug report. I was able to reproduce the bug.
The problem seems to be that during the setting of the seed, offset is always set. However from the documentation, CURAND_RNG_PSEUDO_MTGP32 and CURAND_RNG_PSEUDO_MT19937 dont support setting of the [offset](https://docs.nvidia.com/cuda/curand/host-api-overview.html#offset).

As for the second problem mentioned, I think you are reffereing to quasi-random generators which are not yet a part of Numpy's API, and hence are not supported by CuPy. The enum has the values for completeness. 

Can I work on this ?

Resolving patch:
diff --git a/cupy/random/_generator.py b/cupy/random/_generator.py
--- a/cupy/random/_generator.py
+++ b/cupy/random/_generator.py
@@ -55,6 +55,7 @@ class RandomState(object):
 
     def __init__(self, seed=None, method=curand.CURAND_RNG_PSEUDO_DEFAULT):
         self._generator = curand.createGenerator(method)
+        self.method = method
         self.seed(seed)
 
     def __del__(self, is_shutting_down=util.is_shutting_down):
@@ -739,7 +740,9 @@ def seed(self, seed=None):
                     numpy.asarray(seed).astype(numpy.uint64, casting='safe'))
 
         curand.setPseudoRandomGeneratorSeed(self._generator, seed)
-        curand.setGeneratorOffset(self._generator, 0)
+        if (self.method not in (curand.CURAND_RNG_PSEUDO_MT19937,
+                                curand.CURAND_RNG_PSEUDO_MTGP32)):
+            curand.setGeneratorOffset(self._generator, 0)
 
         self._rk_seed = seed
 


Test patch:
diff --git a/tests/cupy_tests/random_tests/test_generator.py b/tests/cupy_tests/random_tests/test_generator.py
--- a/tests/cupy_tests/random_tests/test_generator.py
+++ b/tests/cupy_tests/random_tests/test_generator.py
@@ -221,6 +221,20 @@ def test_seed_invalid_type_float(self, dtype):
     def test_array_seed(self):
         self.check_seed(numpy.random.randint(0, 2**31, size=40))
 
+    def test_methods(self):
+        methods = [
+            cuda.curand.CURAND_RNG_PSEUDO_DEFAULT,
+            cuda.curand.CURAND_RNG_PSEUDO_MRG32K3A,
+            cupy.cuda.curand.CURAND_RNG_PSEUDO_MT19937,
+            cupy.cuda.curand.CURAND_RNG_PSEUDO_PHILOX4_32_10,
+            cupy.cuda.curand.CURAND_RNG_PSEUDO_MTGP32,
+            cupy.cuda.curand.CURAND_RNG_PSEUDO_XORWOW
+        ]
+
+        for method in methods:
+            rs = cupy.random.RandomState(method=method)
+            rs.normal()
+
 
 @testing.parameterize(
     {'a': 1.0, 'b': 3.0},