3.7。随机数生成

原文: http://numba.pydata.org/numba-doc/latest/cuda/random.html

Numba 提供可在 GPU 上执行的随机数生成算法。然而,由于 NVIDIA 如何实施 cuRAND 的技术问题,Numba 的 GPU 随机数发生器并非基于 cuRAND。相反,Numba 的 GPU RNG 是 xoroshiro128 +算法的实现。 xoroshiro128 +算法的周期为2**128 - 1,短于 cuRAND 默认使用的 XORWOW 算法的周期,但 xoroshiro128 +仍然通过随机数生成器质量的 BigCrush 测试。

在 GPU 上使用任何 RNG 时,务必确保每个线程都有自己的 RNG 状态,并且已经初始化它们以生成非重叠序列。 numba.cuda.random 模块提供了执行此操作的主机功能,以及用于获取均匀或正态分布的随机数的 CUDA 设备功能。

注意

Numba(如 cuRAND)使用 <cite>Box-Muller 变换&lt; https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform></cite> 从均匀发生器生成正态分布的随机数。但是,Box-Muller 会生成一对随机数,而当前的实现仅返回其中一个。结果,生成正态分布值是均匀分布值的一半。

  1. numba.cuda.random.create_xoroshiro128p_states(n, seed, subsequence_start=0, stream=0)

返回为 n 个随机数生成器初始化的新设备数组。

这初始化了 RNG 状态,使得阵列中的每个状态对应于主序列中彼此分开 2 64 步的子序列。因此,只要没有 CUDA 线程请求超过 2 64 个随机数,该函数产生的所有 RNG 状态都保证是独立的。

subsequence_start 参数可用于使第一 RNG 状态前进 2 ** 64 步的倍数。

| 参数: |

  • nint) - 产生
  • 种子的 RNG 状态数 uint64 ) - 发生器列表的起始种子
  • subsequence_startuint64 ) -
  • CUDA 流 ) - 在

上运行初始化内核的流 | | —- | —- |

  1. numba.cuda.random.init_xoroshiro128p_states(states, seed, subsequence_start=0, stream=0)

在 GPU 上为并行生成器初始化 RNG 状态。

这初始化了 RNG 状态,使得阵列中的每个状态对应于主序列中彼此分开 2 64 步的子序列。因此,只要没有 CUDA 线程请求超过 2 64 个随机数,该函数产生的所有 RNG 状态都保证是独立的。

subsequence_start 参数可用于使第一 RNG 状态前进 2 ** 64 步的倍数。

| 参数: |

  • 状态1D DeviceNDArray dtype = xoroshiro128p_dtype ) - RNG 状态数组
  • 种子uint64 ) - 发生器列表的起始种子

    | | —- | —- |

  1. numba.cuda.random.xoroshiro128p_uniform_float32

返回范围[0.0,1.0)中的 float32 并前进states[index]

| 参数: |

  • 状态1D 阵列 dtype = xoroshiro128p_dtype ) - RNG 状态数组
  • 指数int64 ) - 更新状态的偏移

    | | —- | —- | | 返回类型: | FLOAT32 | | —- | —- |

  1. numba.cuda.random.xoroshiro128p_uniform_float64

返回范围[0.0,1.0)中的 float64 并前进states[index]

| 参数: |

  • 状态1D 阵列 dtype = xoroshiro128p_dtype ) - RNG 状态数组
  • 指数int64 ) - 更新状态的偏移

    | | —- | —- | | 返回类型: | float64 | | —- | —- |

  1. numba.cuda.random.xoroshiro128p_normal_float32

返回正态分布的 float32 并前进states[index]

使用 Box-Muller 变换从高斯均值= 0 和 sigma = 1 绘制返回值。这使 RNG 序列前进两步。

| 参数: |

  • 状态1D 阵列 dtype = xoroshiro128p_dtype ) - RNG 状态数组
  • 指数int64 ) - 更新状态的偏移

    | | —- | —- | | 返回类型: | FLOAT32 | | —- | —- |

  1. numba.cuda.random.xoroshiro128p_normal_float64

返回正态分布的 float32 并前进states[index]

使用 Box-Muller 变换从高斯均值= 0 和 sigma = 1 绘制返回值。这使 RNG 序列前进两步。

| 参数: |

  • 状态1D 阵列 dtype = xoroshiro128p_dtype ) - RNG 状态数组
  • 指数int64 ) - 更新状态的偏移

    | | —- | —- | | 返回类型: | float64 | | —- | —- |

3.7.1。示例

这是一个使用随机数生成器的示例程序:

  1. from __future__ import print_function, absolute_import
  2. from numba import cuda
  3. from numba.cuda.random import create_xoroshiro128p_states, xoroshiro128p_uniform_float32
  4. import numpy as np
  5. @cuda.jit
  6. def compute_pi(rng_states, iterations, out):
  7. """Find the maximum value in values and store in result[0]"""
  8. thread_id = cuda.grid(1)
  9. # Compute pi by drawing random (x, y) points and finding what
  10. # fraction lie inside a unit circle
  11. inside = 0
  12. for i in range(iterations):
  13. x = xoroshiro128p_uniform_float32(rng_states, thread_id)
  14. y = xoroshiro128p_uniform_float32(rng_states, thread_id)
  15. if x**2 + y**2 <= 1.0:
  16. inside += 1
  17. out[thread_id] = 4.0 * inside / iterations
  18. threads_per_block = 64
  19. blocks = 24
  20. rng_states = create_xoroshiro128p_states(threads_per_block * blocks, seed=1)
  21. out = np.zeros(threads_per_block * blocks, dtype=np.float32)
  22. compute_pi[blocks, threads_per_block](rng_states, 10000, out)
  23. print('pi:', out.mean())