大きなファイル (7 GB 以上) から 1 行ずつデータを読み取る必要があります。このファイルには、メッシュを形成するための頂点座標と面から頂点への接続情報のリストが含まれています。open
また、mmap
Linux では をCreateFileA
、 Windows ではを使用する方法も学んCreateFileMapping
でMapViewOfFile
います。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
では 13 秒、clang++-11
(Visual Studio Build Tools から) では 11 秒になります。
const char*
両方のシステム (同じ PC ですが、一方は Docker を使用しています)は、メモリ配列を表す とメモリuint64_t
サイズを表すサイズを生成することを除いて、まったく同じコードを使用します。
これは私がプラットフォームを切り替える方法です:
// 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 の配列でメモリを取得するためのコードは次のとおりです。
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 の動作を模倣するため)、それとも時間の違いがコンパイラ/システムの問題であり、受け入れ?
const char*
開いてメモリ サイズを取得し、メモリ マップを取得するための実際の時間は、LinuxとWindows の両方で無視できますsize_t
。
お読みいただきありがとうございます。何かヒントがあれば大歓迎です。不明な点があれば申し訳ありません。