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)使用 Box-Muller 变换< https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform>
从均匀发生器生成正态分布的随机数。但是,Box-Muller 会生成一对随机数,而当前的实现仅返回其中一个。结果,生成正态分布值是均匀分布值的一半。
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 步的倍数。
| 参数: |
- n ( int) - 产生
- 种子的 RNG 状态数 uint64 ) - 发生器列表的起始种子
- subsequence_start ( uint64 ) -
- 流( CUDA 流 ) - 在
上运行初始化内核的流 | | --- | --- |
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 ) - 发生器列表的起始种子
| | --- | --- |
numba.cuda.random.xoroshiro128p_uniform_float32
返回范围[0.0,1.0)中的 float32 并前进states[index]
。
| 参数: |
- 状态( 1D 阵列 _ , _dtype = xoroshiro128p_dtype ) - RNG 状态数组
- 指数( int64 ) - 更新状态的偏移
| | --- | --- | | 返回类型: | FLOAT32 | | --- | --- |
numba.cuda.random.xoroshiro128p_uniform_float64
返回范围[0.0,1.0)中的 float64 并前进states[index]
。
| 参数: |
- 状态( 1D 阵列 _ , _dtype = xoroshiro128p_dtype ) - RNG 状态数组
- 指数( int64 ) - 更新状态的偏移
| | --- | --- | | 返回类型: | float64 | | --- | --- |
numba.cuda.random.xoroshiro128p_normal_float32
返回正态分布的 float32 并前进states[index]
。
使用 Box-Muller 变换从高斯均值= 0 和 sigma = 1 绘制返回值。这使 RNG 序列前进两步。
| 参数: |
- 状态( 1D 阵列 _ , _dtype = xoroshiro128p_dtype ) - RNG 状态数组
- 指数( int64 ) - 更新状态的偏移
| | --- | --- | | 返回类型: | FLOAT32 | | --- | --- |
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。示例
这是一个使用随机数生成器的示例程序:
from __future__ import print_function, absolute_import
from numba import cuda
from numba.cuda.random import create_xoroshiro128p_states, xoroshiro128p_uniform_float32
import numpy as np
@cuda.jit
def compute_pi(rng_states, iterations, out):
"""Find the maximum value in values and store in result[0]"""
thread_id = cuda.grid(1)
# Compute pi by drawing random (x, y) points and finding what
# fraction lie inside a unit circle
inside = 0
for i in range(iterations):
x = xoroshiro128p_uniform_float32(rng_states, thread_id)
y = xoroshiro128p_uniform_float32(rng_states, thread_id)
if x**2 + y**2 <= 1.0:
inside += 1
out[thread_id] = 4.0 * inside / iterations
threads_per_block = 64
blocks = 24
rng_states = create_xoroshiro128p_states(threads_per_block * blocks, seed=1)
out = np.zeros(threads_per_block * blocks, dtype=np.float32)
compute_pi[blocks, threads_per_block](rng_states, 10000, out)
print('pi:', out.mean())