如何在32位系统上读取4GB文件

bio*_*oky 3 c++ boost 32-bit data-processing large-files

在我的情况下,我有不同的文件让我们假设我有4GB文件的数据.我想逐行读取该文件并处理每一行.我的一个限制是软件必须在32位MS Windows上运行,或者在64位上运行少量RAM(最小4GB).您还可以假设这些行的处理不是瓶颈.

在当前的解决方案中,我读取该文件ifstream并复制到某个字符串.这是片段的样子.

std::ifstream file(filename_xml.c_str());
uintmax_t m_numLines = 0;
std::string str;
while (std::getline(file, str))
{
    m_numLines++;
}
Run Code Online (Sandbox Code Playgroud)

好的,这是有效的,但在这里慢慢地是我的3.6 GB数据的时间:

real    1m4.155s
user    0m0.000s
sys     0m0.030s
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种比这更快的方法,例如我发现如何快速解析C++中空格分隔的浮点数?我喜欢用boost :: mapped_file提出解决方案,但我遇到了另一个问题,如果我的文件是大的,在我的情况下文件1GB大到足以放弃整个过程.我不得不关心内存中的当前数据,可能使用该工具的人的RAM安装量不超过4 GB.

所以我发现了来自boost的mapped_file但是在我的情况下如何使用它?是否可以部分读取该文件并接收这些行?

也许你有另一个更好的解决方案.我必须处理每一行.

谢谢,
巴特

seh*_*ehe 6

很高兴看到你找到我的基准如何快速解析C++中空格分隔的浮点数?

看来你真的在寻找最快的计算线数(或任何线性单程分析),我已经完成了类似的分析和基准

有趣的是,您会发现性能最高的代码根本不需要依赖内存映射.

static uintmax_t wc(char const *fname)
{
    static const auto BUFFER_SIZE = 16*1024;
    int fd = open(fname, O_RDONLY);
    if(fd == -1)
        handle_error("open");

    /* Advise the kernel of our access pattern.  */
    posix_fadvise(fd, 0, 0, 1);  // FDADVICE_SEQUENTIAL

    char buf[BUFFER_SIZE + 1];
    uintmax_t lines = 0;

    while(size_t bytes_read = read(fd, buf, BUFFER_SIZE))
    {
        if(bytes_read == (size_t)-1)
            handle_error("read failed");
        if (!bytes_read)
            break;

        for(char *p = buf; (p = (char*) memchr(p, '\n', (buf + bytes_read) - p)); ++p)
            ++lines;
    }

    return lines;
}
Run Code Online (Sandbox Code Playgroud)


Mat*_*son 4

在内存较小的 64 位系统的情况下,应该可以将大文件加载到其中 - 这完全取决于地址空间 - 尽管在这种情况下它可能比“最快”选项慢,但这实际上取决于其他什么内存中以及有多少内存可用于将文件映射到其中。在 32 位系统中,它不起作用,因为指向文件映射的指针最多不会超过约 3.5GB - 通常最大约为 2GB - 再次取决于可用的内存地址将文件映射到的操作系统。

然而,内存映射文件的好处非常小——大部分时间都花在实际读取数据上。使用内存映射的节省是因为数据加载到 RAM 后无需复制数据。(当使用其他文件读取机制时,读取函数会将数据复制到提供的缓冲区中,其中内存映射文件会将其直接填充到正确的位置)。