用C ++读取大型CSV文件(~4GB)

时间:2017-08-24 15:25:43

标签: c++ file csv parsing large-files

我想阅读并将大型CSV文件存储到地图中。我开始只是阅读文件,看看处理需要多长时间。这是我的循环:

while(!gFile.eof()){
   gFile >> data;
}

我需要大约35分钟来处理包含3500万行和六列的csv文件。有什么方法可以加快速度吗?对SO来说很新,所以如果没有正确询问就道歉。

2 个答案:

答案 0 :(得分:4)

<强>背景
文件是流设备或概念。读取文件的最有效用途是保持数据流(流动)。对于每笔交易都有一笔开销。数据传输越大,开销就越小。因此,目标是保持数据流动。

内存比文件访问更快
搜索内存比搜索文件快许多倍。所以,搜索一个单词&#34;或分隔符将比逐字符读取文件更快以找到分隔符。

方法1:逐行
使用std::getline要比使用operator>>快得多。虽然输入代码可能会读取一个数据块;您只执行一个事务来读取记录而不是每列一个事务。请记住,保持数据流动并为列搜索内存的速度更快。

方法2:阻止阅读
本着保持流流动的精神,将一块内存读入缓冲区(大缓冲区)。处理缓冲区中的数据。这比逐行读取更有效,因为您可以使用一个事务读取多行数据,从而减少事务的开销。

有一点需要注意,您可能有一个记录交叉缓冲区边界,因此您需要提出一个算法来处理它。执行惩罚很小,每个事务只发生一次(考虑这部分事务的开销)。

方法3:多线程
本着保持数据流的精神,您可以创建多个线程。一个线程负责或将数据读入缓冲区,而另一个线程处理来自缓冲区的数据。这种技术可以更好地保持数据流动。

方法4:双缓冲&amp;多线程
这采用上面的方法3并添加多个缓冲区。读取线程可以填满一个缓冲区,然后开始填充第二个缓冲区。在处理数据之前,数据处理线程将一直等到第一个缓冲区被填满。该技术用于更好地将读取数据的速度与处理数据的速度相匹配。

方法5:内存映射文件
使用内存映射文件,操作系统会根据需要处理文件读取到内存。您需要编写的代码较少,但是您无法控制何时将文件读入内存。这仍然比逐场阅读更快。

答案 1 :(得分:1)

让我们从瓶颈开始。

  1. 从磁盘读取
  2. 解码数据
  3. 存储在地图
  4. 内存速度
  5. 内存量
  6. 从磁盘读取

    • 如果你阅读速度不够快,可以阅读 磁盘上的带宽可以更快。忽略所有其他步骤,只读。
    • 首先在缓冲区添加缓冲区
    • 设置阅读提示
    • 使用mmap
    • 4GB是一个微不足道的大小,如果你还没有32 GB升级
    • 购买M.2磁盘太慢了。
    • 仍然要慢,然后更奇特,更改磁盘驱动程序,转储操作系统。镜像磁盘,只有$£€是限制。

    解码数据

    • 如果您的数据在长度相同的行中,那么所有解码都可以并行完成,仅受内存带宽的限制。
    • 如果线路长度只是稍微警惕,则可以并行完成线路的查找结束,然后进行并行解码。
    • 如果行的顺序对于最终地图无关紧要,只需将文件拆分到#hardwarethreads部分中,然后让每个部分处理它们的部分直到下一个部分中的第一个换行符。
    • 内存带宽最有可能在CPU无论如何接近耗尽之前到达。

    存储在地图中

    • 希望您事先考虑过这张地图,因为没有任何标准地图是线程安全的。
    • 如果您不关心订单,可以使用std :: array,并且可以以全内存带宽运行。
    • 假设您想使用std :: unordered_map,每次写入后都需要更新大小的问题,所以有效地限制为1个线程写入它。
    • 您可以一次使用1个线程进行更新,而另一个预先计算记录的哈希值。
    • 有一个线程写入的问题是,几乎每次写入都会导致高速缓存未命中,严重限制了速度。
    • 所以,如果这还不够快,请滚动自己的hash_map,不要每次写入都必须更新大小。
    • 为了确保线程安全,您还需要保护写入,让一个互斥锁使您比单个写入器慢或慢。
    • 你可以试着让它锁定并等待免费......如果你不是专家,你会得到严重的头痛。
    • 如果您为哈希选择了一个存储桶设计,那么您可以将X倍数写入编写器线程互斥锁,使用哈希值来选择互斥锁。额外的互斥体增加了两个线程不会发生碰撞的可能性。

    记忆速度

    • 每条线路将通过内存总线传输至少4次,一次从磁盘传输到RAM(如果驱动程序不好则至少再传输一次),一次数据解码时,一次当地图读取时请求,以及地图写入时的另外一个。
    • 如果驱动程序写入缓存,那么良好的设置可以节省一次内存访问,因此解码不会导致LLC错过。

    内存量

    • 你应该有足够的内存来保存整个文件,数据结构和一些中间数据。
    • 检查RAM是否比编程时间便宜。