0

我正在使用 C 语言开发一个具有非常严格要求的Wa-tor模拟器,我对如何在具有相同参数的调用之间正确获得可​​重现的行为有点困惑。

Wa-tor 基本上是一个 2D 细胞阵列,只能包含水,一条鱼或一条鲨鱼。

我所拥有的是(我将尝试仅列出对理解问题感兴趣的内容):

  • 一个配置文件,用户可以在其中指定一个整数种子,以及其他选项
  • 一个主进程,它解析配置文件并产生(fork+execve)用户请求的尽可能多的工作子进程。此外,它将收集所有工作人员的状态,将其显示为一个大网格。Worker 通过 UNIX 套接字文件与 master 通信。
  • 许多多线程(pthreads)工作进程。

工作人员连接到主套接字并接收模拟参数,包括用户指定的种子(此时种子在向其添加工作人员 ID 的工作人员之间进行区分。工作人员 ID 是主设备可重复分配给工作人员的渐进式数字,并且是包含在 execve 的命令行中,因此 worker 可以在连接到 master 的套接字时进行识别,并且每次都被分配到相同的网格部分)。

Worker 随机初始化其 subgrid 并将其发送给 master,然后从相邻的 worker 接收/发送边界值。

Worker 的状态从现在开始以离散的步骤演变,称为 chronon。在每个步骤中,worker 为其子网格中的每个生物计算一个随机动作,然后与相邻的 worker 和 master 交换更新。

一个线程监听信号,而另一个例程处理“模拟”部分。这个模拟例程 - 在每一步结束时 - 产生 4 个其他线程以向相邻线程发送更新,4 个用于接收更新,1 个用于向主线程发送状态。在开始另一个步骤之前,此线程将在此后加入。

我目前正在做的处理随机数的生成是拥有一个全局“unsigned int SEED”,它在工作进程开始时(在产生任何线程之前)从主服务器接收到的值提供,并使用“extern”关键字包含在我需要的每个文件中。所以我在调用“rand_r(&SEED)”时使用它的地址。

第一个问题是调用 rand_r 后 SEED 的值没有更新,因为我可以观察到运行单线程应用程序。我忘记了什么?

然后我问一个全局变量是否是获得可重现序列的正确方法,承认 rand_r 可以由不同的线程调用,并且由于工作人员之间的通信不遵循严格的顺序,动作序列可能会发生变化, - 如果不是这样,从一个整数值作为种子开始?要求是,从相同的确切参数和种子开始,两次执行一步一步地产生相同的结果(就像任何受人尊敬的模拟器一样,我猜 :)

Ps 我正在考虑切换到 drand48_r() 但汤是一样的,我猜。

问候博士

4

1 回答 1

3

By having a single global var SEED , the behavior of rand_r is not thread safe - it would be thread safe if there were a seed var per thread. I would suggest to generate a distinct seed per thread with rand_r from your initial SEED at init time. Then each thread runs independently with its own same random sequence.

于 2013-08-28T22:15:40.133 回答