首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Linux与Windows上读取大文件(mmap vs CreateFileMapping/MapViewOfFile)

在Linux与Windows上读取大文件(mmap vs CreateFileMapping/MapViewOfFile)
EN

Stack Overflow用户
提问于 2021-06-13 14:22:43
回答 1查看 62关注 0票数 0

我必须从一个大文件(超过7 7GB)逐行读取一些数据,它包含一个顶点坐标列表和面到顶点的连通性信息,以形成网格。我还在学习如何在Linux上使用openmmap,在Windows上使用CreateFileACreateFileMappingMapViewOfFile。Linux和Windows版本都是64位编译的。

当我在Linux (使用docker)和g++-10 test.cpp -O3 -std=c++17的时候,我得到了大约6秒。当我在Windows (我实际的PC)上使用(版本19.29.30037 x64) cl test.cpp /EHsc /O3 /std:c++17时,我得到了13s,而使用clang++-11 (来自Visual Studio Build Tools)时,我得到了11s。

除了生成表示内存阵列的const char*和表示内存大小的uint64_t大小之外,两个系统(相同的PC,但其中一个使用docker)使用完全相同的代码。

这是我切换平台的方式:

代码语言:javascript
复制
// includes for using a specific platform API
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// using windows handle void*
#define handle_type HANDLE
#else
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
// using file descriptors
#define handle_type int
#endif

具体地说,获取char-s数组中的内存的代码是:

代码语言:javascript
复制
using uint_t = std::size_t;

// open the file -----------------------------------------------------------------------------
handle_type open(const std::string& filename) {
#ifdef _WIN32
  // see windows file mapping api for parameter explanation
  return ::CreateFileA(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // private access
#else
  return ::open(filename.c_str(), O_RDONLY);
#endif
}


// get the memory size to later have a bound for reading -------------------------------------
uint_t memory_size(handle_type fid) {
#ifdef _WIN32
  LARGE_INTEGER size{};
  if (!::GetFileSizeEx(fid, &size)) {
    std::cerr << "file not found\n";
    return size.QuadPart;
  }
  return size.QuadPart;
#else
  struct stat sb;
  // get the file stats and check if not zero size
  if (fstat(fid, &sb)) {
    std::cerr << "file not found\n";
    return decltype(sb.st_size){};
  }
  return sb.st_size;
#endif
}

// get the actual char array to access memory ------------------------------------------------
const char* memory_map(handle_type fid, uint_t memory_size) {
#ifdef _WIN32
  HANDLE mapper = ::CreateFileMapping(fid, NULL, PAGE_READONLY, 0, 0, NULL);
  return reinterpret_cast<const char*>(::MapViewOfFile(mapper, FILE_MAP_READ, 0, 0, memory_size));
#else
  return reinterpret_cast<const char*>(::mmap(NULL, memory_size, PROT_READ, MAP_PRIVATE, fid, 0));
#endif
}

我对这种解析完全陌生,我想知道我在Windows API中选择参数(模仿mmap的行为)是否做错了什么,或者时间上的差异是编译器/系统的问题并必须接受它?

实际打开、获取内存大小和内存映射的时间在Linux和Windows上都可以忽略不计,其余代码是相同的,因为它只使用const char*size_t信息进行操作。

感谢您抽出时间来阅读。任何提示都非常感谢,如果有任何不清楚的地方,我们深表歉意。

EN

回答 1

Stack Overflow用户

发布于 2021-06-13 19:30:36

也许你应该看看https://github.com/alitrack/mman-win32,它是一个用于Windows的mmap实现。这样你就不需要为Windows编写不同的代码了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67955471

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档