适用于CUDA GPU的Numba 随机数生成
适用于CUDA GPU的Numba 随机数生成
随机数生成
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 (like cuRAND) uses the Box-Muller transform <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步的倍数。
参数: |
|
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步的倍数。
参数: |
|
numba.cuda.random.xoroshiro128p_uniform_float32
返回范围为[0.0,1.0)的float32并前进states[index]。
参数: |
|
返回类型: |
float32 |
numba.cuda.random.xoroshiro128p_uniform_float64
返回范围为[0.0,1.0)的float64并前进states[index]。
参数: |
|
返回类型: |
float64 |
numba.cuda.random.xoroshiro128p_normal_float32
返回正态分布的float32并前进states[index]。
使用Box-Muller变换从平均值= 0和sigma = 1的高斯中得出返回值。这使RNG序列前进了两个步骤。
参数: |
|
返回类型: |
float32 |
numba.cuda.random.xoroshiro128p_normal_float64
返回正态分布的float32并前进states[index]。
使用Box-Muller变换从平均值= 0和sigma = 1的高斯中得出返回值。这使RNG序列前进了两个步骤。
参数: |
|
返回类型: |
float64 |
例
这是使用随机数生成器的示例程序:
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())
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)