GPU 上的随机数流
默认情况下,随机数生成函数 rand
、randi
和 randn
在 GPU 上进行计算时使用与 CPU 上不同的生成器设置。您可以改变随机数生成器的行为,以在 GPU 和 CPU 上生成可重现的随机数序列。
下表总结了客户端和工作单元 MATLAB® 会话中 GPU 和 CPU 的默认设置:
生成器 | 种子 | 正态变换 | |
---|---|---|---|
客户端 CPU | 'Twister' 或 'mt19937ar' | 0 | 'Ziggurat' |
工作单元 CPU | 'Threefry' 或 'Threefry4x64_20' | 0 | 'Inversion' |
GPU(在客户端或工作单元上) | 'Threefry' 或 'Threefry4x64_20' | 0 | 'BoxMuller' |
大多数情况下,GPU 上的默认随机数生成器与客户端或工作单元 CPU 上的默认生成器不一样并不重要。但是,如果您需要在 GPU 和 CPU 上重现相同的结果,则可以相应地设置生成器。
客户端 CPU 和 GPU
在新的 MATLAB 会话中,MATLAB 在 CPU 和 GPU 上生成不同的随机数序列。
Rc = rand(1,4)
Rc = 0.8147 0.9058 0.1270 0.9134
Rg = rand(1,4,'gpuArray')
Rg = 0.3640 0.5421 0.6543 0.7436
如果您需要在 GPU 和 CPU 上生成相同的随机数序列,则可以设置生成器设置以匹配。
GPU 上有三种随机数生成器算法:'Threefry'
、'Philox'
和 'CombRecursive'
。所有这些都受 CPU 支持。下表列出了这些生成器的算法及其属性。
关键字 | 生成器 | 多流和子流支持 | 高精度近似周期 |
---|---|---|---|
"Threefry" 或 "Threefry4x64_20" | 执行 20 轮的 Threefry 4x64 生成器 | 是 | 2514(2256 个长度为 2258 的流) |
"Philox" 或 "Philox4x32_10" | 执行 10 轮的 Philox 4x32 生成器 | 是 | 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
设置控制。您可以使用 parallel.gpu.RandStream
在 GPU 上控制它。
在客户端 CPU 上,默认的 'NormalTransform'
设置为 'Ziggurat'
。在工作单元 CPU 上,默认设置为 'Inversion'
。
除非另有说明,GPU 代码对 'BoxMuller'
和 'Threefry'
生成器使用 'Philox'
变换,对 'Inversion'
生成器使用 'CombRecursive'
变换。
您可以在 CPU 和 GPU 上设置相同的生成器和变换以获得相同的 randn
序列。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