首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多线程黑客

多线程黑客
EN

Stack Overflow用户
提问于 2010-08-22 05:40:41
回答 3查看 288关注 0票数 0

我正在编写一个应该有点快的数值程序,而且也是多线程的。我有一个类表示一个数字,我想在其中使用一个随机数生成器。现在,我并不真的要求我的RNG是一个真正的RNG,我只需要它生成均匀分布在0到NMAX之间的整数。

所以我的班上有这样一个:

代码语言:javascript
复制
// use just an int here and forget about multithreading.
static uint32 rand = NMAX/4; 
// this will be called multithreadedly
static uint32 GetRand() { return rand = ( rand + 1 ) % NMAX; }

现在,在一个线程化的世界中,这对我的目的来说是完全没有问题的。

因为这是多线程的,所以我假设唯一可能发生的坏事情是偶尔(比如<1%的时间)更新会被删除。这意味着两个线程读取rand,在寄存器中更新它,返回更新后的值,然后用相同的值写两次。这完全没问题。

我的问题是比这更糟糕的事还会发生吗?我完全同意每个线程使用自己的rand变量,但这只是一个巨大的痛苦来实现。我绝对不能做的是让类的每个实例都使用自己的rand变量,因为这样会占用太多的内存。

更新:

那我为什么要这么做?完整的故事是一个浮点类,它使用1或2个字节。所以它必须是快速的,这似乎是最好的方法。事实上,我认为我会将它从( rand + 1 ) % NMAX更新到类似( rand + [some prime] ) % NMAX的东西,因为它似乎更好用。这是一个例子,在这种情况下,一个更健壮的解决方案需要更多的代码,使代码更少通用,更依赖,使代码变得不那么清晰和更容易中断,所有这些都是因为“应该使用适当的同步”。

最主要的是,我担心编译器可能会做一些奇怪的优化,这样对rand的更新不仅会被删除,而且会变成完全的垃圾。不过,现在我已经考虑过了,即使这样也可以(使用这个数字的方式),因为下一次使用GetRand将使它%NMAX,这个错误最多只会导致GetRand的一次使用超出[0,NMAX]的给定范围。谢谢你的回答。

EN

回答 3

Stack Overflow用户

发布于 2010-08-22 05:46:04

我完全同意每个线程使用自己的rand变量,但这只是一个巨大的痛苦来实现。

用这种方式做并不一定那么困难。一些编译器(例如GCC)支持http://en.wikipedia.org/wiki/Thread_local_storage#GCC,它允许每个线程都有自己的给定变量的副本。

话虽如此,用你目前的做法,我只能想到一个问题--除了你提到的那个问题。如果每个线程运行在不同的内核上,并且随机值存储在每个内核的非共享缓存中,那么更新可能无法在内核之间传播不确定的时间。您可以通过使用记忆屏障 (可以通过使用锁来创建)来避免这种情况,但是这可能不利于性能。

票数 1
EN

Stack Overflow用户

发布于 2010-08-22 06:37:28

为了便于讨论,我们假设以下实现:

  • 使用Mersenne (mt19937),它在每次呼叫中生成624个随机数。
  • 类的每个实例(仅在单个线程中使用)从批处理中读取一个数字,并增加全局索引计数器,以便下一个调用(来自任何实例)将获取批处理中的下一个数字。当全局索引到达数组结束时,将锁定RNG并生成新的624个随机数,然后重置全局索引。

我对改进的建议是,每个实例一次获取16个数字。不需要在实例中存储(复制)这16个数字:只需将全局索引增加16 (使其他实例不可用),以便实例可以逐一使用它们。

票数 1
EN

Stack Overflow用户

发布于 2010-08-22 07:35:36

  1. 您可以使用TLS,以便每个线程都有“自己的”变量。
代码语言:javascript
复制
__declspec(thread) static uint32 rand = NMAX/4; 
// this will be called multithreadedly
static uint32 GetRand() { return rand = ( rand + 1 ) % NMAX; }
  1. 在您的特殊情况下,很容易修复代码,使其线程安全。
代码语言:javascript
复制
static long rand = NMAX/4; 
// this will be called multithreadedly
static uint32 GetRand() { return InterlockedIncrement(&rand) % NMAX; }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3540331

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档