繁体   English   中英

好的C ++数组类,用于以快速且内存高效的方式处理大型数据数组?

[英]Good C++ array class for dealing with large arrays of data in a fast and memory efficient way?

前面有关堆使用限制的问题之后 ,我正在寻找一个好的标准C ++类,以一种既能节省内存又能提高速度的方式处理大型数据。 我一直在使用单个malloc / HealAlloc分配数组,但是在使用各种调用多次尝试之后,请避免犯下堆碎片的问题。 因此,除了移植到64位之外,我得出的结论是要使用一种机制,使我能够拥有一个跨多个较小的内存片段的大型阵列。 我不希望为每个元素分配内存,因为这会导致内存效率低下,因此计划是编写一个重写[]运算符的类,然后根据索引选择一个合适的元素。 是否已经有一个不错的班级来做到这一点,还是我最好自己动手做?

根据我的理解和一些谷歌搜索 ,从理论上讲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,则需要不到1秒的时间。 双端队列调整大小最初占用了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)随机元素访问来实现,这正是我所需要的。 感谢大家的反馈!

您是否尝试过使用std::deque 与使用一个巨大堆分配的std::vector不同, deque通常以小块分配,但仍通过operator[]提供摊销的固定时间索引。

这个数组到底有多稀疏? 如果其中有大量的空(未使用)空间,则可能要采取另一种方法。 这个问题答案建议一个stl映射。

如果它不是稀疏的(如注释中所述),则由于您正在Windows上运行,因此您可能要考虑的一件事是使用内存映射文件 尽管您的操作系统可能是32位的,但您的文件系统却不是。 当然,这的确意味着会进行交换,这比将真正的坏东西真正放入RAM的速度要慢得多。

另外,您确实应该考虑将系统的RAM调到最大(我相信32位Windows上为3GB),看看是否可以为您解决问题。 那只花了您大约100美元,而您花费的时间比在工时上花费的更多,只是担心这一点。

从程序的角度来看,无论系统中发生了什么事情,启动时始终有2GB可用空间。 我认为Windows无法提供一种方法来检测是否有内存被调出到磁盘上。 就数据结构而言,听起来好像您正在描述类似于在STL中实现双端队列的方式。

std :: deque确实可以满足您的描述,但通常以OS页面大小的粒度(即,它分配的块通常为4 kB)为准。

如果您对deque的默认性能不满意,则可以编写一个捕获更大块的自定义分配器-即一次获取1 MB或更多。

正如其他人所说,您的进程的虚拟地址空间完全独立于所有其他进程,因此无论系统中发生了什么,您都可以寻址2GB。 操作系统将根据需要与磁盘交换内存页,以适应已安装内存量和所有争用该内存的进程的限制。 这将在4 kB页面大小时发生,与您的块大小无关。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM