GPU 上的随机数流
默认情况下,随机数生成函数 rand、randi 和 randn 在 GPU 上进行计算时使用与 CPU 上不同的生成器设置。您可以改变随机数生成器的行为,以在 GPU 和 CPU 上生成可重现的随机数序列。
下表总结了客户端和工作单元 MATLAB® 会话中 GPU 和 CPU 的默认设置:
| 生成器 | 种子 | 正态变换 | |
|---|---|---|---|
| 客户端 CPU | 梅森扭转算法 | 0 | 金字塔 |
| 工作单元 CPU | 执行 20 轮的 Threefry 4x64 生成器 | 0 | 反转 |
| GPU(在客户端或工作单元上) | 执行 20 轮的 Threefry 4x64 生成器 | 0 | Box–Muller |
大多数情况下,GPU 上的默认随机数生成器与客户端或工作单元 CPU 上的默认生成器不一样并不重要。但是,如果您需要在 GPU 和 CPU 上重现相同的结果,则可以相应地设置生成器。
客户端 CPU 和 GPU
在新的 MATLAB 会话中,MATLAB 在 CPU 和 GPU 上生成不同的随机数序列。
Rc = rand(1,4)
Rc =
0.8147 0.9058 0.1270 0.9134Rg = rand(1,4,"gpuArray")
Rg =
0.3640 0.5421 0.6543 0.7436如果您需要在 GPU 和 CPU 上生成相同的随机数序列,则可以将生成器的设置调整为一致。
GPU 上有三种随机数生成器算法:"Threefry"、"Philox" 和 "CombRecursive"。这三项功能在 CPU 上也都得到了支持。下表列出了这些生成器的算法及其属性。
| 值 | 发电机名称 | 生成器关键字 | 多流和子流支持 | 高精度近似周期 |
|---|---|---|---|---|
"Threefry" | 执行 20 轮的 Threefry 4x64 生成器 | threefry4x64_20 | 是 | 2514(2256 个长度为 2258 的流) |
"Philox" | 执行 10 轮的 Philox 4x32 生成器 | philox4x32_10 | 是 | 2193(264 条长度为 2129 的流) |
"CombRecursive" | 组合多重递归生成器 | mrg32k3a | 是 | 2191(263 条长度为 2127 的流) |
您可以使用 rng 和 gpurng 分别在 CPU 和 GPU 上设置生成器算法和种子。有关 GPU 随机数生成器及其性能的更多信息,请参阅 在 GPU 上生成随机数。
sc = rng(1,"Threefry");
Rc = rand(1,4)Rc = 0.1404 0.8197 0.1073 0.4131
sg = gpurng(1,"Threefry"); Rg = rand(1,4,"gpuArray")
Rg =
0.1404 0.8197 0.1073 0.4131现在,rand 和 randi 函数在客户端 CPU 和 GPU 上生成的随机数序列相同。
您还可以使用 rng 和 gpurng 将生成器算法和种子分别重置为 CPU 和 GPU 上的默认值。
rsc = rng("default"); rsg = gpurng("default");
工作单元 CPU 和 GPU
如果有的话,并行工作单元 CPU 使用与客户端 GPU 和工作单元 GPU 相同的默认随机数生成器类型和种子。GPU 和 CPU 不共享同一个流。默认情况下,rand 和 randi 在 GPU 和工作单元 CPU 上生成相同的数字序列。
该设置与客户端 CPU 上的设置不同。有关详细信息,请参阅 控制工作单元上的随机数流
如果需要在每个工作单元身上生成不同的随机数,您可以更改生成器设置。在这个示例中,每个工作单元在其 GPU 和 CPU 上创建相同的序列,但是每个工作单元上生成的序列不同。
p = parpool(2); spmd rng(spmdIndex,"Threefry"); Rc = rand(1,4) gpurng(spmdIndex,"Threefry"); Rg = rand(1,4,"gpuArray") end delete(p)
正态分布的随机数
对于使用 randn 函数创建的正态分布随机数,MATLAB 在客户端 CPU、工作单元 CPU 和 GPU 上产生不同的结果。将均匀随机数转换为正态分布随机数的过程由 NormalTransform 参量控制。您可以在 GPU 上使用 parallel.gpu.RandStream 函数来控制这一点。
在客户端 CPU 上,NormalTransform 的默认值为 "Ziggurat"。在工作单元 CPU 上,默认值为 "Inversion"。
除非另有说明,GPU 代码对 "Threefry" 和 "Philox" 生成器使用 "BoxMuller" 变换,对 "CombRecursive" 生成器使用 "Inversion" 变换。
您可以在 CPU 和 GPU 上设置相同的生成器和变换,以获得相同的正态分布随机数序列。CPU 和 GPU 都支持的唯一变换是 "Inversion"。
sc = RandStream("Threefry",NormalTransform="Inversion",Seed=1); RandStream.setGlobalStream(sc) sg = parallel.gpu.RandStream("Threefry",NormalTransform="Inversion",Seed=1); parallel.gpu.RandStream.setGlobalStream(sg); Rc = randn(1,4)
Rc = -1.0783 0.9144 -1.2412 -0.2196
Rg = randn(1,4,"gpuArray")
Rg = -1.0783 0.9144 -1.2412 -0.2196
另请参阅
gpurng | parallel.gpu.RandStream | RandStream | rng | gpuArray