我正在研究一个多线程程序,其中所有线程共享一些向量(只读)。每个线程的目标是遍历整个向量。尽管如此,所有线程都必须以不同的方式访问此向量。
由于向量是const并且在所有线程之间共享,我不能使用random_shuffle并且只是迭代它。目前我的解决方案是构建 一个crossref向量,它将包含共享向量的索引然后 洗牌这个载体,即
genre.name
尽管如此,这样做会揭示一些问题(1)它不是很有效,因为每个线程在访问共享向量之前都需要访问它的crossref向量,(2)由于所需的内存量,我有一些性能问题:共享向量非常大,我有很多线程和处理器。
有没有人有一些改进的想法,可以避免额外的内存?
答案 0 :(得分:14)
您可以使用primitive root modulo n的代数概念。 基本上
如果n是正整数,则1和n - 1之间的整数是 coprime to n形成一组模数为n的原始类。这个小组 当且仅当n等于2,4,p ^ k或2p ^ k时才是循环的,其中p ^ k是 一个奇素数的幂
维基百科显示如何使用7
作为生成器生成3
以下的数字。
从这个陈述中你可以得到一个算法。
n
m
n
F(0)
和2
m
F(i+1) = (F(i) * F(0)) mod m
计算下一个索引。如果该索引在[0, n]
范围内,请访问该元素。如果没有走向下一个指数。m - 1
次迭代后停止(或者当你获得1时,它是相同的。)因为m
是素数,所以2和m-1之间的每个数字都是m
的互质数,因此是序列{1 ... m}
的生成符。我们保证在前m - 1
步骤中不会重复任何号码,并且会显示所有m - 1
个号码。
复杂性:
O(thread count)
O(m)
时间,每个帖子的空格O(1)
。你不需要存储F(i)。您只需知道第一个值和最后一个值。这与增量相同的属性答案 1 :(得分:6)
如果我理解你想要以增量方式生成随机排列,即你想要调用 n 次函数 f 这样它就可以生成从1到 n 的所有置换数,因此该函数具有恒定的内存。
如果你想在排列中获得均匀分布,我怀疑它是否存在,但你可能对这组排列的一个子集感到满意。
如果是这种情况,您可以通过使用 n 取一个 p 数字来生成排列,并计算[1]中的每个 i ,n]:i.p (mod n)
。
例如,如果你有n = 5和p = 7,那么7%5 = 2,14%5 = 4,21%5 = 1,28%5 = 3,35%5 = 0。你可以结合几个这样的功能来获得满足你的东西......
答案 2 :(得分:2)
如果内存是您最大的问题,那么您必须将CPU周期换成内存空间。
E.g。 c ++&#39; s std::vector<bool>
(http://en.cppreference.com/w/cpp/container/vector_bool)是一个位数组,因此具有很高的内存效率。
每个帖子都可以拥有自己的vector<bool>
,表明它是否访问了特定索引。然后,您必须使用CPU周期来随机选择尚未访问的索引,并在所有bool
为true
时终止。
答案 3 :(得分:2)
似乎this家伙以非常好的方式解决了你的问题。
这就是他在帖子第一行所说的内容:在这篇文章中,我将展示一种方法来制作一个迭代器,它将以随机顺序访问列表中的项目,只访问每个项目一次,告诉你何时访问了所有项目并完成了。它不会存储混洗列表,也不必跟踪已经访问过的项目。
他利用可变位长度块密码算法的强大功能来生成数组中的每个索引。
答案 4 :(得分:1)
这不是一个完整的答案,但它应该引导我们找到正确的解决方案。
你写过一些我们可以作为假设的东西:
(1)由于每个线程都需要访问它,因此效率不高 访问共享之前的crossref向量,
这不可能是真的。我们谈论的是一次间接查询。除非你的参考数据真的是一个整数的向量,否则这将代表你执行时间的无限小部分。如果您的参考数据是一个int的向量,那么只需制作它的N个副本并随机播放它们......
(2)由于内存量的原因,我有一些性能问题 需要:共享向量非常大,我有很多线程 和处理器。
有多大?你测量过了吗?向量中有多少个离散对象?每个人有多大?
多少个帖子?
多少个处理器?
你有多少记忆?
您是否分析过代码?您是否确定性能瓶颈在哪里?您是否考虑过更优雅的算法?