低内存内存管理:查找和跟踪随机函数返回值的重复项
Memory management with low memory: finding and tracking duplicates of random function return values
假设我有一个函数,它接受 32 位整数输入,并返回随机的 32 位整数输出。
现在,我想看看这个函数将在从 0 到 2^32-1 的所有可能的输入值上返回多少个重复值。如果我有超过 4GB 的免费内存,我可以让这变得容易,但我的内存不超过 1g。
我尝试使用 4gig 文件在磁盘上映射计算值,其中一个字节表示它获得了多少重复项,但我注意到以我的 HDD 速度,近似的完成时间将是未来 25 天!(我不得不使用SSD,因为害怕损坏我的硬盘...
所以,现在下一步是在 RAM 中计算这一切,根本不使用磁盘,但是在思考如何优雅地解决这个问题时,我跑了起来。我能想到的唯一方法是循环 (2^32)*(2^32) 乘以函数,但这显然比我的 HDD 方法还要慢。
我现在需要的是一些讨厌的想法来加快速度!
编辑:该函数并不是真正的随机函数,而是类似于随机函数,但事实是您不需要了解该函数的任何信息,这不是这里的问题。我想用我的肉眼看到所有的重复项,而不仅仅是一些数学猜测可能有多少。我为什么要这样做?出于好奇:)
要检查 2^32 个可能的重复项,您只需要 4 千兆位,即 512MB,因为每个值只需要一个位。第一次点击零位将其设置为 1,每次点击 1 位时,您就知道您有一个副本,可以将其打印出来或对它做任何您想做的事情。
也就是说,您可以执行以下操作:
int value = nextValue(...);
static int bits[] = new int[ 0x08000000 ]();
unsigned int idx = value >> 5, bit = 1 << ( value & 31 );
if( bits[ idx ] & bit )
// duplicate
else
bits[ idx ] |= bit;
回应您的意见
是的,如果重复项不是太多,也没有太多不同的重复项,则将重复项放入地图中是个好主意。这里最坏的情况是 2^31 个条目,如果每 2 个值恰好出现两次。如果映射变得太大而无法立即保存在内存中,您可以对其进行分区,即只允许特定范围内的值,即整个数字空间的四分之一。如果重复项分布相当均匀,这将使地图的大小仅为整个地图的 1/4。当然,您需要每个季度运行该程序 4 次才能找到所有重复项。
要查找第一个重复项,您可以分两次运行它:在第一遍中,您使用位图查找重复项并将它们放入图中。在第二遍中,如果映射中已经有一个条目并且该值尚不存在,则跳过位图并将值添加到映射中。
不,没有充分的理由在无符号的 int 数组上使用 int。 您也可以使用无符号的 int,这实际上在这里更合适。
一个不可问的问题:为什么?. 你想实现什么目标?
这是某种蒙特卡洛实验吗?
如果没有,只需查找您的(P)RNG的实现算法,它将准确地告诉您值的分布
。看看Boost.Random,寻找比你所能想象的更多的选择,它会有例如 uniform_int<>
和变量生成器,可以限制输出范围,同时仍对输出域中的值分布有明确定义的保证
- 从python中调用C++函数并获取返回值
- 为什么模板类中的对象不能返回值
- 返回值优化:显式移动还是隐式
- lock_guard是否保护返回值
- 调用CreateProcess()并获取字符串的返回值
- 如何使 windows 命令提示符在C++可执行文件上显示返回值?
- 编译器警告:执行到达值返回函数的末尾而不返回值
- 查找 GCD:并非所有控制路径都返回值
- 将内存分配返回值强制转换为 TYPE 数组
- Clang++ 6.0 内存清理器未报告返回值指示条件分支的函数中的未初始化局部变量
- 获取“将返回值分配给新变量”的警告和输出是内存地址
- 为循环中多次调用的函数返回值预分配内存的正确方法是什么
- 内存分配,用于在C 11中循环中函数的返回值:如何优化
- 如果我的C++“新”内存分配失败,如何找出返回值
- 是指向在向函数返回值/参数和类请求传输数据期间复制的内存的指针
- 释放返回值/指向CvMat的指针的内存
- 大返回值(如字符串)的内存释放如何在C++中发生
- 动态多态内存容器-返回值不正确
- 参数返回值的 V8 内存管理
- 低内存内存管理:查找和跟踪随机函数返回值的重复项