gpt4 book ai didi

c++ - 如何在 C++ 中快速解析空格分隔的 float ?

转载 作者:IT老高 更新时间:2023-10-28 12:35:25 25 4
gpt4 key购买 nike

我有一个包含数百万行的文件,每行有 3 个 float ,以空格分隔。读取文件需要很多时间,所以我尝试使用内存映射文件读取它们,结果发现问题不在于 IO 的速度,而在于解析的速度。

我目前的解析是获取流(称为文件)并执行以下操作

float x,y,z;
file >> x >> y >> z;

Stack Overflow 中有人推荐使用 Boost.Spirit,但我找不到任何简单的教程来解释如何使用它。

我正在尝试找到一种简单有效的方法来解析如下所示的行:

"134.32 3545.87 3425"

我将非常感谢一些帮助。我想用strtok来拆分它,但是我不知道如何将字符串转换为 float ,我不太确定这是最好的方法。

我不介意解决方案是否是 Boost。我不介意它是否不是有史以来最有效的解决方案,但我确信它可以将速度提高一倍。

提前致谢。

最佳答案

UPDATE

Since Spirit X3 is available for testing, I've updated the benchmarks. Meanwhile I've used Nonius to get statistically sound benchmarks.

All charts below are available interactive online

Benchmark CMake project + testdata used is on github: https://github.com/sehe/bench_float_parsing

enter image description here

总结:

Spirit 解析器是最快的。如果可以使用 C++14,可以考虑实验版 Spirit X3:

enter image description here

以上是使用内存映射文件的措施。使用 IOstreams 会更慢,

enter image description here

但不如使用 C/POSIX FILE* 函数调用的 scanf 慢:

enter image description here


以下是旧答案的部分内容


I implemented the Spirit version, and ran a benchmark comparing to the other suggested answers.

Here's my results, all tests run on the same body of input (515Mb of input.txt). See below for exact specs.


(wall clock time in seconds, average of 2+ runs)

To my own surprise, Boost Spirit turns out to be fastest, and most elegant:

  • handles/reports errors
  • supports +/-Inf and NaN and variable whitespace
  • no problems at all detecting the end of input (as opposed to the other mmap answer)
  • looks nice:

    bool ok = phrase_parse(f,l,               // source iterators
    (double_ > double_ > double_) % eol, // grammar
    blank, // skipper
    data); // output attribute

Note that boost::spirit::istreambuf_iterator was unspeakably much slower (15s+). I hope this helps!

Benchmark details

All parsing done into vector of struct float3 { float x,y,z; }.

Generate input file using

od -f -A none --width=12 /dev/urandom | head -n 11000000

This results in a 515Mb file containing data like

     -2627.0056   -1.967235e-12  -2.2784738e+33
-1.0664798e-27 -4.6421956e-23 -6.917859e+20
-1.1080849e+36 2.8909405e-33 1.7888695e-12
-7.1663235e+33 -1.0840628e+36 1.5343362e-12
-3.1773715e-17 -6.3655537e-22 -8.797282e+31
9.781095e+19 1.7378472e-37 63825084
-1.2139188e+09 -5.2464635e-05 -2.1235992e-38
3.0109424e+08 5.3939846e+30 -6.6146894e-20

Compile the program using:

g++ -std=c++0x -g -O3 -isystem -march=native test.cpp -o test -lboost_filesystem -lboost_iostreams

Measure wall clock time using

time ./test < input.txt 

环境:

  • Linux 桌面 4.2.0-42-generic#49-Ubuntu SMP x86_64
  • Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
  • 32GiB 内存

完整代码

旧基准的完整代码位于 edit history of this post ,最新版本是on github

关于c++ - 如何在 C++ 中快速解析空格分隔的 float ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17465061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com