使用ifstream在两个线程中处理同一个文件
Process same file in two threads using ifstream
我的应用程序中有一个输入文件,其中包含大量信息。按顺序读取,一次只读取一个文件偏移量,对于我的应用程序来说是不够的。理想情况下,我希望有两个线程,它们具有从同一文件的两个唯一文件偏移量读取的独立且不同的ifstream
。我不能只启动一个ifstream
,然后使用它的复制构造函数来复制它(因为它是不可复制的)那么,我该如何处理呢
我立刻想到两种方法,
- 为第二个线程构造一个新的
ifstream
,在同一个文件上打开它 - 在两个线程之间共享打开的
ifstream
的单个实例(例如使用boost::shared_ptr<>
)。当线程获得时间片时,查找当前线程当前感兴趣的适当文件偏移量
是否首选这两种方法之一
还有第三个(或第四个)选项我还没有想到吗
很明显,我最终受到了硬盘必须来回旋转的限制,但我感兴趣的是(如果可能的话)在两个文件偏移量上同时进行一些操作系统级别的磁盘缓存。
谢谢。
两个std::ifstream
实例可能是这里的最佳选择。现代HDD针对大量I/O请求进行了优化,因此同时从两个std::ifstream
实例中读取应该会提供相当好的性能。
如果您有一个std::ifstream
,您将不得不担心同步对它的访问,此外,它可能会破坏操作系统的自动顺序访问预读缓存,从而导致较差的性能。
在两者之间,我更喜欢第二种。根据底层操作系统的不同,打开两个相同文件可能会导致文件之间的视图不一致。
对于第三个选项,将引用或原始指针传递到另一个线程中。只要语义是一个线程"拥有"istream,原始指针或引用就可以了。
最后要注意的是,在绝大多数硬件上,当加载大文件时,磁盘是瓶颈,而不是CPU。使用两个线程会使变得更糟,因为您正在将顺序文件访问转换为随机访问。典型的硬盘可以按顺序执行100MB/s,但最高可达3或4 MB/s的随机访问。
其他选项:
- 内存映射文件,创建任意数量的内存istream对象。(
istrstream
对此有好处,istringstream
则不然)
这实际上取决于您的系统。一个现代系统通常会读向前地在文件中查找可能会抑制这种情况,因此应该一定要避免。
预读在您的系统中的工作方式可能值得一试:打开文件,然后按顺序读取它的前半部分,看看如何这需要很长时间。然后打开它,找中间,读第二个半顺序。(在我过去见过的一些系统上seek在任何时候都将关闭预读。)最后,打开它,然后每隔一条记录读取一次;这将模拟使用相同的两个线程文件描述符。(对于所有这些测试,使用固定长度的记录,以及以二进制模式打开。同时采取一切必要措施确保文件中的任何数据在开始测试—在Unix下,复制10或20 GB的文件到CCD_ 11通常就足够了。
这会给你一些想法,但可以肯定的是,最好的解决方案是测试真实的案例。如果分享单个ifstream
(因此是单个文件描述符),并且寻求,赢得,但你永远不会知道。
我也推荐像mmap
这样的系统特定解决方案,但如果您有那么多数据,你很有可能无法绘制地图总之,一气呵成。(您仍然可以使用mmap
,映射它的部分一次,但它变得复杂得多。)
最后,是否有可能将已经切割成的数据更小的文件?这可能是最快的解决方案。(理想地,这将在生成数据或将数据导入系统。)
我的投票将是一个读卡器,它将数据交给多个工作线程。
如果你的文件在一个磁盘上,那么多个读卡器会影响你的读取性能。是的,您的内核可能有一些出色的缓存或排队功能,但它将花费更多的时间来寻找而不是读取数据。
- 将更高的优先级设置为 boost::asio 线程处理进程
- C++ 使用 2 个容器进行线程处理
- 当线程处理不同的类时,应该在哪里声明条件变量、互斥对象
- 多线程处理中的静态成员变量
- Opencv cpp 使用多线程处理同一视频的不同部分
- 对象析构函数在多线程处理时不断被调用,但该对象并未超出范围
- 使用 wxWidgets 进行多线程处理时出现奇怪的行为
- 使用共享变量进行线程处理
- 通过多线程处理确定每个字符在文件中出现的次数
- 使用多线程处理的异步请求
- 多线程处理,同时保持部分序列
- 如何在类中进行 c++ 多线程处理(将线程引用保留为成员 var)
- 用管道在C++中创建调度队列/线程处理程序:FIFO溢出
- 用多个线程处理SIGTERM的正确方法
- 使用C++的递归线程处理会使资源暂时不可用
- SDL 带变量的多线程处理 -- 无法按预期工作
- 使用多线程处理对象数组 - 无效使用 void 表达式错误
- 如何使用"priority"进行多线程处理?
- 使用简单的过程进行慢速多线程处理
- C++11 使用共享对象的多线程处理