在 parfor-循环中重复随机数
本示例演示了如何通过为每次迭代分配特定的子流,来控制 parfor 循环中的随机数生成。
如控制工作单元上的随机数流中所述,集群中执行同一项作业的每个工作单元都有一个独立的随机数生成器流。默认情况下,工作池中的每个工作单元以及 parfor-loop 中的每次迭代都拥有一组唯一且独立的随机数。parfor 循环的后续运行会生成不同的数字。
在 parfor 循环中,您无法控制迭代执行的顺序,也无法控制哪个工作单元运行哪些迭代。因此,即使您重置随机数生成器,parfor 循环也可以按照不同的序列生成相同的值。
要在 parfor 循环中确保每次运行时都能生成同一组随机数,必须通过为每次迭代分配特定的子流来控制随机数的生成。
使用支持子流的生成器,创建您要使用的流。将流创建为 parallel.pool.Constant 可允许所有工作单元访问该流。有关支持子流的生成器的列表,请参阅 选择随机数生成器。
sc = parallel.pool.Constant(RandStream("Threefry"))sc =
Constant with properties:
Value: [1x1 RandStream]
在 parfor-loop 循环内部,您可以根据循环索引设置子流索引。这确保了每次迭代都会使用一组独特且可重现的随机数,无论由哪个工作单元执行该迭代,也无论迭代的执行顺序如何。
有两种方法可以在工作单元上使用该流来生成随机数。
您可以将修改后的流作为第一个参量传递给 rand、randn、randi 和 randperm 等函数。此方法可确保每次函数调用都使用正确的子流。
r1 = zeros(1,10); parfor idx = 1:10 % Extract the stream from the Constant stream = sc.Value; stream.Substream = idx; r1(idx) = rand(stream,1); end disp(r1)
0.3640 0.8645 0.0440 0.7564 0.5323 0.8075 0.2145 0.9128 0.4057 0.0581
您还可以将工作单元上的全局随机数流设置为修改后的流。这种方法使得此后所有随机数生成调用都能自动使用已分配的流。
r2 = zeros(1,10); parfor idx = 1:10 % Extract the stream from the Constant stream = sc.Value; stream.Substream = idx; % Save previous global stream oldGlobalStream = RandStream.setGlobalStream(stream); r2(idx) = rand(1); % Restore the previous global stream RandStream.setGlobalStream(oldGlobalStream); end disp(r2)
0.3640 0.8645 0.0440 0.7564 0.5323 0.8075 0.2145 0.9128 0.4057 0.0581
验证每个选项在每次迭代中生成的随机数是否相同。
isequal(r1,r2)
ans = logical
1