C++ 以固定速率重放存储的数据

C++ 以固定速率重放存储的数据,c++,multithreading,performance,io,locking,C++,Multithreading,Performance,Io,Locking,我正在处理一个问题,我想以指定的速率重放存储在文件中的数据 例如:25000条记录/秒 该文件为ascii格式。目前,我读取了文件的每一行,并将正则表达式应用于 提取数据。2-4行组成一个记录。我对这个操作进行了计时,它需要接近 15微秒用于生成每条记录 发布每条记录所需的时间为6微秒 如果我按顺序执行读写操作,那么我将以21微秒的时间来发布每条记录。所以实际上,这意味着我的上限是每秒47K条记录 如果我决定多线程读写,那么我将能够每9微秒发送一个数据包(忽略锁定惩罚,因为读写器共享相同的Q),

我正在处理一个问题,我想以指定的速率重放存储在文件中的数据

例如:25000条记录/秒

该文件为ascii格式。目前,我读取了文件的每一行,并将正则表达式应用于 提取数据。2-4行组成一个记录。我对这个操作进行了计时,它需要接近 15微秒用于生成每条记录

发布每条记录所需的时间为6微秒

如果我按顺序执行读写操作,那么我将以21微秒的时间来发布每条记录。所以实际上,这意味着我的上限是每秒47K条记录

如果我决定多线程读写,那么我将能够每9微秒发送一个数据包(忽略锁定惩罚,因为读写器共享相同的Q),这将提供每秒110K个时钟的吞吐量

我以前的设计正确吗

当单个生产者和消费者共享一个队列时,哪种队列和锁定结构的惩罚最小

如果我想超越这个范围,最好的方法是什么


我的应用程序使用C++

如果读取/准备一条记录需要15秒,那么您的最大吞吐量大约为1秒/15uSec=67k/秒。您可以忽略6uSec部分,因为读取文件的单线程无法生成更多的记录。(尝试一下,将程序更改为只读/处理并放弃输出)不确定您是如何获得9uS的

要使此速度超过67k/秒

A) 估计每秒可从要格式化的磁盘读取的最大记录数。虽然这在很大程度上取决于硬件,但对于普通笔记本电脑来说,20Mb/秒的数字是典型的。这个数字会给你目标的上限,当你接近目标时,你可以放松尝试

B) 创建一个线程只是为了读取文件并引起IO延迟。这个线程应该写入大的预分配缓冲区,比如说每个4Mb。请参阅以了解管理这些问题的方法。您希望每个缓冲区保存1000条记录(猜测,但不只是8条记录!)伪代码:

   while not EOF
     Allocate big buffer
     While not EOF and not buffer full
          Read file using fgets() or whatever
          Apply only very small preprocessing, ideally none
          Save into buffer
     Release buffer for other threads
C) 创建另一个线程(如果记录的顺序不重要,则创建几个线程)以在环形缓冲区已满时处理它,这是您的正则表达式步骤。该线程依次写入另一组输出环形缓冲区(提示,在内存中保持环形缓冲区控制结构的分离)

D) 创建最终线程以使用数据。不清楚此输出是否正在写入磁盘或网络,因此这可能会影响磁盘读取线程

    Wait/get input buffer from processed records pool
    Output records to wherever
    Return buffer to processed records pool
注释。 预先分配所有缓冲区并将它们传递回它们的来源。例如,在文件读取线程和处理线程之间可能有4个缓冲区,当所有4个缓冲区都被注入时,文件读取器会等待一个缓冲区空闲,而不仅仅是分配新的缓冲区。 如果可以避免的话,尽量不要使用memset()缓冲区,这样会浪费内存带宽。 你不需要很多缓冲区,6?每环缓冲器

系统将自动调整到最慢的线程(),因此,如果读取和准备数据的速度比输出数据的速度快,则所有缓冲区都将填满,除输出外,所有内容都将暂停

由于线程正在为每个同步点传递合理数量的数据,因此这方面的开销不会太大


上面的设计是我的一些代码如何尽可能快地读取CSV文件,基本上都是以输入IO带宽作为限制因素。

如果读取/准备一条记录需要15秒,那么您的最大吞吐量大约为1秒/15uSec=67k/秒。您可以忽略6uSec部分,因为读取文件的单线程无法生成更多的记录。(尝试一下,将程序更改为只读/处理并放弃输出)不确定您是如何获得9uS的

要使此速度超过67k/秒

A) 估计每秒可从要格式化的磁盘读取的最大记录数。虽然这在很大程度上取决于硬件,但对于普通笔记本电脑来说,20Mb/秒的数字是典型的。这个数字会给你目标的上限,当你接近目标时,你可以放松尝试

B) 创建一个线程只是为了读取文件并引起IO延迟。这个线程应该写入大的预分配缓冲区,比如说每个4Mb。请参阅以了解管理这些问题的方法。您希望每个缓冲区保存1000条记录(猜测,但不只是8条记录!)伪代码:

   while not EOF
     Allocate big buffer
     While not EOF and not buffer full
          Read file using fgets() or whatever
          Apply only very small preprocessing, ideally none
          Save into buffer
     Release buffer for other threads
C) 创建另一个线程(如果记录的顺序不重要,则创建几个线程)以在环形缓冲区已满时处理它,这是您的正则表达式步骤。该线程依次写入另一组输出环形缓冲区(提示,在内存中保持环形缓冲区控制结构的分离)

D) 创建最终线程以使用数据。不清楚此输出是否正在写入磁盘或网络,因此这可能会影响磁盘读取线程

    Wait/get input buffer from processed records pool
    Output records to wherever
    Return buffer to processed records pool
注释。 预先分配所有缓冲区并将它们传递回它们的来源。例如,在文件读取线程和处理线程之间可能有4个缓冲区,当所有4个缓冲区都被注入时,文件读取器会等待一个缓冲区空闲,而不仅仅是分配新的缓冲区。 如果可以避免的话,尽量不要使用memset()缓冲区,这样会浪费内存带宽。 你不需要很多缓冲区,6?每环缓冲器

系统将自动调整到最慢的线程(),因此,如果读取和准备数据的速度比输出数据的速度快,则所有缓冲区都将填满,除输出外,所有内容都将暂停

由于线程正在为每个同步点传递合理数量的数据,因此这方面的开销不会太大


上面的设计是我的一些代码如何尽可能快地读取CSV文件,基本上都是以输入IO带宽作为限制因素。

太棒了!这太棒了。你的代码是开源的吗?如果是的话,你能给我指一下吗?关于B)和C)的问题,你是说我们读取一个4mb的数据块并将其存储在预分配的缓冲区中,然后读取缓冲区将数据转换为记录,然后另一个线程实际发送记录?你有吗