数据结构存储大量数据?

Ash*_*iya 12 c++ memory dynamic-memory-allocation data-structures

在我的应用程序中,我必须从一组图像(MRC图像)加载volumedata并将像素数据保存在内存中.(图像是灰度级的,因此每像素一个字节).

我的开发环境是QT框架,MinGW for Windows和GCC for Linux.

目前,我使用一个简单的数据结构来存储volumedata:

unsigned char *volumeData;
Run Code Online (Sandbox Code Playgroud)

并按如下方式进行大量分配.

volumeData=new unsigned char[imageXsize * imageYsize * numofImages];
Run Code Online (Sandbox Code Playgroud)

以下是访问给定平面中图像数据的重要方法,例如

unsigned char* getXYPlaneSlice(int z_value);
unsigned char* getYZPlaneSlice(int x_value);
unsigned char* getZXPlaneSlice(int y_value);
Run Code Online (Sandbox Code Playgroud)

使用我简单的数据结构,很容易实现上述方法.

但是我们可能需要在未来采用体积大小为2000x2000x1000(~3.7Gb).而目前的数据结构将无法处理这些庞大的数据.

  1. 如何避免碎片?现在,即使使用1000x1000x200数据,应用程序也会崩溃,从而导致bad_alloc.什么是更改数据结构的最佳方法?我应该使用链接列表,每个块大小为100mb.

  2. 此外,用户应该能够在体积数据上执行一些图像处理过滤器,并且还应该能够重置为原始像素值.这意味着,我应该保留两份卷数据.与目前的实施类似.

    unsigned char*volumeDataOriginal;

    unsigned char*volumeDataCurrent;

因此,对于2000x2000x1000数据范围,它将使用大约8Gb(每个音量4Gb).但在Win32中,地址空间为4GB.如何解决这个问题?我应该使用64位应用程序?

编辑:这是我的应用程序的快照 在此输入图像描述

基本上,我加载了体积数据(来自MRC格式的图像集),并将它们显示在不同的平面查看器中(XY,YX,YZ.Image显示XY平面查看器).我需要保持在上面3种数据访问方法,用于显示特定平面中的图像.使用滑块栏用户可以更改要在所选平面中显示的图像)

提前致谢.

jim*_*myb 14

我想你应该看看hdf5.这是一种二进制格式,用于存储从望远镜,物理实验和基因测序机器等收集的大量数据.使用这样的东西的好处很多,但有三个直接的想法:(1)测试,(2)支持hyperslab选择,(3)你免费获得压缩.

有C/C++,java,python,matlab库可用.


Ton*_*roy 5

64位可能是处理此问题的最简单方法...当您使用它们时,让操作系统出现故障.否则,如果不通过数据了解您的访问模式,就很难成功.如果你经常扫描图像以找到相同像素坐标处的值,那么谈论说要指向按需保存和重新加载的图像是毫无意义的.

对于撤消数据,您可以按照建议保留完整备份副本,或者您可以尝试进行撤消操作,以查看所做的更改并负责查找有效的实施.例如,如果您只是翻转位,那么这是非破坏性的,您只需要一个仿函数来进行相同的位翻转操作来撤消更改.如果将所有像素设置为相同的色调是常见操作(例如填充,清除),那么您可以使用布尔值和单个像素对该图像状态进行编码,并使用完整缓冲区进行撤消.


Nav*_*een 5

您可以使用内存映射文件来管理内存有限的大型数据集。但是,如果您的文件大小为 4GB,则建议使用 64 位。boost 项目有一个很好的多平台内存映射库,其性能非常接近您正在寻找的东西。

http://en.wikipedia.org/wiki/Memory-mapped_file http://www.boost.org/doc/libs/1_44_0/libs/iostreams/doc/classes/mapped_file.html 帮助您入门。下面是一些示例代码——

#include <boost/iostreams/device/mapped_file.hpp>
boost::iostreams::mapped_file_source input_source;
input_source.open(std::string(argv[1]));
const char *data = input_source.data();
long size = input_source.size();
input_source.close();
Run Code Online (Sandbox Code Playgroud)

谢谢,内森


Bid*_*ids 5

解决问题的最简单方法是使用64位地址空间 - 现代Mac支持开箱即用,在Windows和Linux上,您需要安装64位版本的操作系统.我相信Qt可以很好地用于构建64位应用程序.32位系统将无法支持您所讨论的大小的单一分配 - 即使具有4 GB可用地址空间的Mac也无法进行单个3.7 GB的分配,因为不会是一个可用的那个大小的连续空间.

对于撤消,我会考虑使用内存映射文件和copy-on-write来复制块:

http://en.wikipedia.org/wiki/Copy-on-write

这意味着您实际上不必复制所有原始数据,系统将在写入页面时复制页面.如果您的图像比实际内存大得多并且您没有更改图像的每个部分,这将极大地提高性能.看起来像具有"私有"访问权限的boost :: map_file可能对此有所帮助.

如果你真的,真的需要支持32位系统,你唯一的选择是以某种方式打破那些大块,通常是平面或子卷.在应用3D滤镜等时,两者都很难用,所以如果可以,我真的会避免这种情况.

如果你进入子卷路由,一个技巧是将所有子卷保存在内存映射文件中,并仅在需要时将它们映射到地址空间.当从地址空间取消映射时,它们应该保留在统一缓冲区高速缓存中直到被清除,这实际上意味着您可以使用比地址空间更多的RAM(特别是在Windows上,默认情况下32位应用程序仅获得2 GB的地址空间) .

最后,在32位Windows上,您还可以查看boot.ini中的/ 3GB开关.这允许您为应用程序分配3 GB的地址空间,而不是正常的2 GB.从你描述的问题我不认为这会给你足够的地址空间,但它可能会帮助你一些较小的卷.请注意,/ 3GB开关可能会导致某些驱动程序出现问题,因为它会减少内核可用的地址空间量.