【问题标题】:Fastest way to read a vector<double> from file从文件中读取 vector<double> 的最快方法
【发布时间】:2019-01-17 15:17:20
【问题描述】:

我有 3 个向量,每个向量正好有 256^3 ~ 1600 万个元素,我想将它们存储在一个文件中并尽可能快地读取。我只关心读取性能,内存中数据的表示可以是任意的。

我已经研究了一些序列化技术以及使用 ofstream 向文件写入/读取纯数字,但是我想知道是否有更直接和更快的方法。

(我对 c++ 及其概念很陌生)

【问题讨论】:

  • 你关心与其他操作系统或机器的兼容性吗?如果没有,您可以将向量内容的二进制表示直接转储到二进制文件中。
  • 取决于文件系统,如果你是多进程...
  • 我需要使用windows创建文件并仍然使用android加载它
  • 这些向量代表什么?
  • @MichaelVeksler 我怀疑所有这些都可以保证具有相同的双重格式:developer.android.com/ndk/guides/abis

标签: c++


【解决方案1】:

假设 windows 和 android 这两个系统都是 little endian,这在 ARM 和 x86/x64 CPU 中很常见,您可以执行以下操作。

首先:确定具有特定大小的类型,因此可以选择 double、64 位、float 和 32 位、uint64/32/16 或 int64/32/16。不要使用 intlong 之类的东西来确定您的数据类型。

第二种:使用以下方法写入二进制数据:

std::vector<uint64_t> myVec;
std::ofstream f("outputFile.bin", std::ios::binary);
f.write(reinterpret_cast<char*>(myVec.data()), myVec.size()*sizeof(uint64_t));
f.close();

在此,您将获取原始数据并将其二进制格式写入文件。

现在在其他机器上,确保您使用的数据类型具有相同的数据类型大小和相同的字节序。如果两者相同,您可以这样做:

std::vector<uint64_t> myVec(sizeOfTheData);
std::ifstream f("outputFile.bin", std::ios::binary);
f.read(reinterpret_cast<char*>(&myVec.front()), myVec.size()*sizeof(uint64_t));
f.close();

请注意,在读取数据之前,您必须知道数据的大小。

注意:这个代码是我的头。我还没有测试过,但它应该可以工作。

现在如果目标系统没有相同的字节序,你必须批量读取数据,翻转字节序,然后将它放入你的向量中。如何翻转字节序已被广泛讨论here

为了确定您的系统的字节顺序,已讨论过here

性能损失与这些系统的不同程度成正比。如果它们都是相同的字节顺序并且您选择相同的数据类型和大小,那么您很好并且您具有最佳性能。否则,您将受到一些惩罚,具体取决于您必须进行多少次转换。这是您能获得的最快速度。

来自 cmets 的注意事项:如果您要传输双精度或浮点数,请确保两个系统都使用 IEEE 754 标准。使用这些是很常见的,远远超过字节序,但只是为了确定。

现在,如果这些解决方案不适合您,那么您必须使用适当的序列化库来为您标准化格式。有一些库可以做到这一点,例如protobuf

【讨论】:

  • 绝对不是 OP 想要的。 Android 不保证这一点。
  • @Jeffrey 不保证具体是什么?
  • 字节顺序和数据类型大小。另外,你可以 static_cast double* 到 char* 吗?我的编译器给了我“不允许从 'double *' 到 'char *' 的 static_cast”
  • @Jeffrey Endianness 可以翻转,可以在编译时检测到。如果static_cast 不起作用,请使用reinterpret_cast
  • 对于浮点但很重要:两者都需要使用 IEEE 754 来表示 - 但这与 LE 一样常见...
猜你喜欢
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-26
  • 1970-01-01
相关资源
最近更新 更多