2012-03-22 53 views
0

我有一个GUI应用程序,它与点云数据以及它后面的四叉树数据结构一起处理数据。由于我正在使用的点格式最近发生了变化,我不得不修改我的点类来保存新的属性,这会导致Point对象显着增大,并且实际上会降低我的四叉树的性能。显示和处理数据时不需要这些属性中的一部分,但仍需要将其保存在输出中。这大约是我的观点类是如何看的那一刻:将未使用的类数据成员存储在磁盘上

class Point { 
public: 
    /* ... */ 
private: 
    /* Used data members */ 
    double x; 
    double y; 
    double z; 
    double time; 
    int attr1; 
    int attr2; 

    /* Unused data members */ 
    int atr3; 
    double atr4; 
    float atr5; 
    float atr6; 
    float atr7; 
} 

当数据从点存储在一个点*数组,然后通过四叉树处理的文件加载。同样,当它们被保存时,一系列点将从四叉树传递并保存到文件中。请注意,我在我的四叉树中使用的Point对象与存储在文件中的Point对象不同,但我使用的库提供读者和写者对象,我使用它创建点。这里有一个例子:

int PointLoader::load(int n, Point* points) { 

    Point temp; 
    int pointCounter = 0; 

    /* reader object is provided by the library and declared elsewhere */   
    while (pointCounter < n && reader->read_point()) { 
     temp = Point(reader->get_x(), reader->get_y(), reader->get_z(), /* ... */) 

     points[pointCounter] = temp; 
     ++pointCounter;   
    } 
    return pointCounter; 
} 

现在,我的想法是,以减少Point类的大小和使用的属性存储在硬盘上称为PointData另一个类(或结构)。这是必要的,因为数据通常不适合内存,并且存在一个缓存系统,它将再次受益于较小的点对象。因此,给出的例子会是这个样子:

int PointLoader::load(int n, Point* points) { 

    Point temp; 
    PointData tempData; 
    int pointCounter = 0;  

    while (pointCounter < n && reader->read_point()) { 
     temp = Point(reader->get_x(), reader->get_y(), reader->get_z(), /* ... */) 
     pointData = (reader->get_attr3(), reader->get_attr4(), /* ... */) 

     temp.dataHandle = /* some kind of handle to the data object */ 
     points[pointCounter] = temp; 

     /* Save pointData to file to retrieve when saving points */ 

     ++pointCounter;   
    } 
    return pointCounter; 
} 

后来,当我救我的修改点我会简单地用dataHandle(文件偏移在内存中的索引映射的阵列?)来检索每个pointData指向并将其写回文件。

这听起来像个好主意吗?什么是最明智的做法呢?

回答

1

我建议你使用映射文件来存储附加数据。如果存在内存压力,这将自动将它们刷新到磁盘并从RAM中移除,但是如果有足够的内存,它们大部分时间都会驻留在RAM中。

在您的Point类中,将偏移量存储在文件中比将直接指针存储到映射的内存区域更好,因为如果必须重新映射文​​件才能使其增大,偏移量仍然是正确的(必须增大文件你自己使用例如lseek(),因为你只能映射文件的大小)。

这种机制编码起来非常方便,但您必须有足够的地址空间来映射整个文件 - 在64位应用程序中没有问题,但如果您是32位并且需要多于一个的问题文件中有几百MB的数据。您当然可以映射和取消映射多个文件,但它需要更多的编码工作并且性能较差(对映射和取消映射文件有一定的成本)。

+0

谢谢。要考虑的一件事是,我可以使用int来存储映射的数组索引,但可能必须使用无符号long long(64位)来存储偏移量,这又会负面影响Point对象的大小。我正在寻找可能的最有效的解决方案。 – jaho 2012-03-22 14:41:37

+0

@Marian如果对象的大小是固定的,将数组索引存储到映射区域并使用int而不是基于字节的索引(这将需要很长的时间)没有问题。这是指针算术的美妙之处。 – 2012-03-22 16:22:59

+0

好的,很酷。我应该使用mmap还是有更多的C++方法来创建内存映射文件? – jaho 2012-03-22 16:59:22