【问题标题】:Best seed for parallel process并行过程的最佳种子
【发布时间】:2025-12-12 16:35:01
【问题描述】:

我需要在不同的机器上并行运行 MonteCarlo 模拟。代码是用 c++ 编写的,但程序是使用 python 脚本设置和启动的,该脚本设置了很多东西,尤其是随机种子。函数 setseed 是一个 4 字节的无符号整数

使用简单的

import time
setseed(int(time.time()))

不是很好,因为我将作业提交到集群上的队列,它们保持等待几分钟然后它们开始,但是开始时间是不可预测的,可能是两个作业同时开始(秒) ,所以我切换到:

setseet(int(time.time()*100))

但我不开心。什么是最好的解决方案?也许我可以结合以下信息:时间、机器 ID、进程 ID。或者最好的解决方案是从 /dev/random (linux 机器)读取?

如何从 /dev/random 读取 4 个字节?

f = open("/dev/random","rb")
f.read(4)

给我一​​个字符串,我要一个整数!

【问题讨论】:

  • 你还没有真正说出什么是“最好的”。我认为您正在尝试确保每个实例使用不同的种子。但是,它们是否应该在一次运行中的不同作业之间是唯一的,或者您是否需要一些接近(或保证是)全局唯一性(所有运行和所有作业)的东西。其次,您是否需要能够使用相同的种子重复运行(有时有助于间歇性调试)。并且可能还有其他并发症。
  • 我想要每个实例的随机种子,所以如果种子是从 0 到 2^(8*4)-1,那么每个实例的种子很可能是不同的。我不强迫种子不同,即使它们不同可能会更好。我认为这不是一个很大的问题。我不需要用同一个种子重复运行。
  • 嗯,这很简单,您已经有了很好的答案。干杯。

标签: python random parallel-processing seed montecarlo


【解决方案1】:

阅读/dev/random 是个好主意。只需将 4 字节字符串转换为 Integer:

f = open("/dev/random","rb")
rnd_str = f.read(4)

使用结构:

import struct
rand_int = struct.unpack('I', rnd_string)[0]

更新需要大写的 I。

或乘加:

rand_int = 0
for c in rnd_str:
    rand_int <<= 8
    rand_int += ord(c)

【讨论】:

  • 请注意,如果您走这条路,请记住保存您的种子,以确保您以后可以重现准确的结果。
  • 我把种子保存在输出文件的名字里
  • 谢谢,但将 'i' 更改为 'I' 并将 rnd_string 更改为 rnd_str
  • 最后我将 'i' 更改为 'I' 因为我得到: TypeError: void TRandom3::SetSeed(UInt_t seed = 0) => could not convert argument 1 (can't convertnegative value to无符号长)
【解决方案2】:

您可以简单地将四个字节复制到一个整数中,这应该是您最不担心的。

但并行伪随机数生成是一个相当复杂的话题,而且通常做得不好。通常您在一台机器上生成种子并将它们分发给其他机器。

看看SPRNG,它可以解决您的问题。

【讨论】:

    【解决方案3】:

    如果这是 Linux 或类似的操作系统,您需要/dev/urandom——它总是会立即生成数据。

    /dev/random 可能会停止等待系统收集随机性。它确实会产生加密级别的随机数,但这对您的问题来说太过分了。

    【讨论】:

    • 我知道,但我更喜欢随机。我只需要4字节的随机数,不会太多
    【解决方案4】:

    您可以使用随机数作为种子,其优点是与操作系统无关(无需 /dev/random),无需从字符串转换为整数:

    为什么不简单地使用

    random.randrange(-2**31, 2**31)
    

    作为每个进程的种子?稍微不同的开始时间会产生截然不同的种子,这样......

    如果您大致知道每个进程将使用多少个随机数,您也可以使用random.jumpahead 方法(random.WichmannHill.jumpahead 的文档很有用)。

    【讨论】:

      最近更新 更多