使用Boost的file_mapping和mapped_region最大限度地减少内存使用量?

时间:2013-02-15 21:19:08

标签: c++ memory-management boost file-io

对于这个问题,我将一个大的三维体积从文件加载到程序中,但通常只需要一次查看三个平面(x,y,z)。我目前正在使用Boost :: Interprocess :: File_Mapping来创建文件的映射(32 GB)并将其加载到我的具有24 GB RAM的系统上。当前方法对文件使用单个Boost :: Interprocess :: Mapped_Region。内存使用率迅速接近99%。

我是内存映射文件i / o世界的新手,想知道如何最好地对文件进行分段以减少内存使用量。创建尺寸减小的区域(例如每个Z平面)会改善结果吗?我想尽可能少地使用内存而不会产生不良影响。

我是否以正确的方式进行此操作,还是有更直接的方法来执行此操作?

1 个答案:

答案 0 :(得分:1)

在Windows上,它通常可以正常工作。我创建了一个测试应用程序(抱歉,我讨厌提升,因为我认为它的质量是适合的,我的样本使用ATL,但基础Windows API是相同的):

HRESULT TestMain( LPCTSTR strFileName )
{
    CAtlFile file;
    HRESULT hr = file.Create( strFileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING );
    if( FAILED( hr ) )
        return hr;
    CAtlFileMapping<BYTE> mapping;
    hr = mapping.MapFile( file );
    if( FAILED( hr ) )
        return hr;
    size_t sz = mapping.GetMappingSize();
    BYTE res = 0;
    for( size_t i = 0; i < sz; i++ )
        res ^= mapping[ i ];

    printf( "Read the complete file, %Iu bytes, the XOR is %.2X\n", sz, int( res ) );
    return S_OK;
}

当我被要求在我的机器上读取带有8GB RAM的12GB文件时,我看到了你所描述的效果(我的进程的资源监视器内存数据:提交25 MB,私有20 MB,工作集和可共享6.5 GB,这是我的免费RAM量)。然而,互联网上的多个来源说这些数字没有任何意义,也不影响性能,因为一旦任何进程请求更多内存,就会丢弃未使用的物理页面,而且这个过程非常便宜(当然,除非您正在写入你的内存映射文件)。

或者,如果您对此行为感到非常不满意,可以通过调用VirtualUnlock自行释放未使用的部分,如下所述:https://stackoverflow.com/a/1882478/126995

或者,您只能映射所需文件的部分。

但您可以做的最好的事情 - 优化数据布局。如果您的数据文件中的体素保持为double voxels[x][y][z],请将其存储为struct { double voxels[8][8][8] } blocks[x/8][y/8][z/8]。这样,块大小恰好是4kb,这是一个页面大小,如果你只需要访问例如在XZ平面上,您将按照数量级保存很多的I / O带宽。只是不要搞乱错位,即如果你的数据前有一个标题,请确保标题的大小是4kb * n,其中n是整数。

相关问题