继previous question relating to heap usage restrictions之后,我正在寻找一个好的标准C ++类,以一种既节省内存又提高速度的方式处理大数据数据。我一直在使用单个malloc / HealAlloc分配数组,但是在使用各种调用的多个trys之后,继续犯下堆碎片。因此,除了移植到64位之外,我得出的结论是使用一种机制,允许我拥有一个跨越多个较小内存片段的大型数组。我不希望每个元素都有一个alloc,因为它的内存效率很低,所以计划是编写一个覆盖[]运算符的类,并根据索引选择一个合适的元素。是否已经有一个体面的班级来做这件事,或者我最好自己动手?
根据我的理解,以及一些googling,理论上32位Windows进程最多可以解决2GB的问题。现在假设我安装了2GB,各种其他进程和服务大约400MB,你认为我的程序可以合理地期望从堆中获得多少可用内存?
我目前正在使用各种风格的Visual C ++。
编辑根据Poita的帖子,我在VS2008上使用以下测试尝试了 std :: deque ;
#include <deque>
using namespace std;
struct V
{
double data[11];
};
struct T
{
long data[8];
};
void dequeTest()
{
deque<V> VQ;
deque<T> TQ;
V defV;
T defT;
VQ.resize(4000000,defV);
TQ.resize(8000000,defT);
}
以上数据的总内存为608MB,我是使用直接malloc还是HeapAlloc,并采用&lt; 1秒。 deque resizes最初占用了950MB,然后慢慢开始退回。 15分钟后,dequeTest()完成了,只使用了6MB的内存显示进程,这可能与运行时间有关。我也尝试使用各种推送选项填充双端队列,但性能非常糟糕,我不得不提前爆发。我可能提供一个比defualt更好的分配器来获得更好的响应,但从表面来看,deque并不是这项工作的类。请注意,这也可能与deque的MS VS2008实现有关,因为在这个类中似乎有很多与性能有关的非常依赖于实现。
我估计是时候写我自己的大数组了。
第二次编辑:使用以下内容立即分配较小的金额产生1.875GB;
#define TenMB 1024*1024*10
void SmallerAllocs()
{
size_t Total = 0;
LPVOID p[200];
for (int i = 0; i < 200; i++)
{
p[i] = malloc(TenMB);
if (p[i])
Total += TenMB; else
break;
}
CString Msg;
Msg.Format("Allocated %0.3lfGB",Total/(1024.0*1024.0*1024.0));
AfxMessageBox(Msg,MB_OK);
}
最终编辑我已经决定接受Poita的帖子和其后的各种评论,不是因为我将直接使用deque类,而是更多的数组作为一副卡片概念随后的评论。这应该是直接用O(1)随机元素访问实现的,基于每个块的固定数量的元素,这是我需要的。感谢大家的反馈!
答案 0 :(得分:11)
您是否尝试使用std::deque
?与使用一个巨大堆分配的std::vector
不同,deque
通常以小块分配,但仍然通过operator[]
提供分摊的常量时间索引。
答案 1 :(得分:5)
这个数组究竟有多稀疏?如果其中有大量空(未使用)空间,您可能需要采取另一种方法。 answer to this question建议使用stl地图。
如果它不稀疏(如评论中所述),您在Windows上运行时可能会考虑的一件事是使用memory-mapped file。虽然您的操作系统可能是32位,但您的文件系统不是。这当然意味着将会进行交换,这可能比你真正把整个事情放在RAM中要慢得多。
另外,你真的应该考虑将系统的RAM敲到最大值(我认为32位Windows上的3GB),看看是否能为你修复它。这应该只花费你大约100美元,并且你在工时上花费的时间远远超过工时而只是担心这个。
答案 2 :(得分:3)
从您的程序的角度来看,无论系统中发生了什么,您在启动时总是有2GB可用。我不相信Windows提供了一种方法来检测是否有内存被分页到磁盘。就数据结构而言,听起来你正在描述类似于STL中如何实现双端队列的东西。
答案 3 :(得分:1)
std :: deque正是你所描述的,但通常是以OS页面大小的粒度(即它分配的块通常是4 kB)。
如果您对deque的默认性能不满意,您可能可以编写一个可以抓取更大块的自定义分配器 - 也就是说,一次获得1 MB或更多。
正如其他人所说,您的进程的虚拟地址空间完全独立于所有其他进程,因此无论系统中发生了什么,您都可以处理2GB。操作系统将根据需要将您的内存页面交换到磁盘或从磁盘交换,以适应已安装内存量和所有争用它的进程的约束。这将发生在4 kB页面大小,与您的块大小无关。