Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用ifstream在两个线程中处理相同的文件_C++_Multithreading_Io_Fstream_Ifstream - Fatal编程技术网

C++ 使用ifstream在两个线程中处理相同的文件

C++ 使用ifstream在两个线程中处理相同的文件,c++,multithreading,io,fstream,ifstream,C++,Multithreading,Io,Fstream,Ifstream,我的应用程序中有一个包含大量信息的输入文件。按顺序读取,并且一次只读取一个文件偏移量,对于我的应用程序的使用是不够的。理想情况下,我希望有两个线程,它们从同一文件的两个唯一文件偏移量中读取独立且不同的ifstreams。我不能只启动一个ifstream,然后使用它的复制构造函数复制它(因为它是不可复制的)那么,我该如何处理呢? 我马上想到两种方法 为第二个线程构造一个新的ifstream,在同一个文件中打开它 跨两个线程共享打开的ifstream的单个实例(例如使用boost::shared_p

我的应用程序中有一个包含大量信息的输入文件。按顺序读取,并且一次只读取一个文件偏移量,对于我的应用程序的使用是不够的。理想情况下,我希望有两个线程,它们从同一文件的两个唯一文件偏移量中读取独立且不同的
ifstream
s。我不能只启动一个
ifstream
,然后使用它的复制构造函数复制它(因为它是不可复制的)那么,我该如何处理呢?

我马上想到两种方法

  • 为第二个线程构造一个新的
    ifstream
    ,在同一个文件中打开它
  • 跨两个线程共享打开的
    ifstream
    的单个实例(例如使用
    boost::shared_ptr
    )。当线程获得时间片时,查找当前线程当前感兴趣的适当文件偏移量
  • 这两种方法是首选方法之一吗?

    还有第三个(或第四个)选项我还没有想到吗?

    显然,我最终会受到硬盘驱动器来回旋转的限制,但我感兴趣的是利用(如果可能的话)在两个文件偏移量上同时进行一些操作系统级的磁盘缓存


    谢谢。

    在两者之间,我更喜欢第二种。同一个文件有两个开口可能会导致文件之间的视图不一致,具体取决于底层操作系统

    对于第三个选项,将引用或原始指针传递到另一个线程。只要语义是一个线程“拥有”istream,原始指针或引用就可以了


    最后请注意,在绝大多数硬件上,加载大型文件时,磁盘是瓶颈,而不是CPU。使用两个线程会使情况变得更糟,因为您正在将顺序文件访问转变为随机访问。典型的硬盘可以按顺序执行100MB/s的访问,但随机访问速度最高可达3Mb/s或4Mb/s。

    两个
    std::ifstream
    实例可能是最佳选择。现代HDD针对大量I/O请求进行了优化,因此同时读取两个
    std::ifstream
    实例应该会提供相当好的性能

    如果您只有一个
    std::ifstream
    ,您将不得不担心对它的同步访问,而且它可能会破坏操作系统的自动顺序访问预读缓存,从而导致性能下降。

    其他选项:

    • 内存映射文件,创建任意多个内存istream对象。(
      istrstream
      对此很好,
      istringstream
      则不然)

      • 我的投票将是一个读卡器,它将数据交给多个工作线程


        如果您的文件位于单个磁盘上,那么多个读卡器将降低您的读取性能。是的,您的内核可能具有一些出色的缓存或排队功能,但它将花费更多的时间来查找而不是读取数据。

        这实际上取决于您的系统。现代制度通常是 向前地在文件中查找可能会抑制这种情况,因此应该 肯定要避免

        可能值得在您的系统上尝试预读的工作方式: 打开文件,然后按顺序读取前半部分,然后查看如何读取 这需要很长时间。然后打开它,找中间,读第二个 半连续的。(在我过去见过的一些系统上,一个简单的 seek在任何时候都将关闭预读。)最后,打开它,然后 每读一次记录;这将使用相同的方法模拟两个线程 文件描述符。(对于所有这些试验,使用固定长度记录,以及 以二进制模式打开。同时采取任何必要步骤确保 文件中的任何数据在 在Unix下启动测试,复制10或20 GB的文件 对于这一点,使用
        /dev/null
        通常就足够了

        这会给你一些想法,但确实是最好的 解决方案是测试真实案例。如果共享一个 单个
        ifstream
        (因此是单个文件描述符),并且持续 追求,赢得,但你永远不知道

        我还推荐系统特定的解决方案,如
        mmap
        ,但如果您 有那么多数据,你很有可能无法绘制它 不管怎样,都可以一次完成。(您仍然可以使用
        mmap
        ,映射它的各个部分。) 有时,但它会变得复杂得多。)

        最后,是否有可能将数据分割成 较小的文件?这可能是最快的解决方案。(理想情况下, 这将在生成数据或将数据导入到
        系统。)

        注意他用“<代码> STD::IFSturis/Cuff>”来读取文件。在这种情况下,他不必担心不一致的视图。@科丽:在这种特殊情况下,这是正确的。我在更一般地思考。编译器是否需要支持某个C++标准来使用这个?@ JT:内存映射没有被标准覆盖。您必须对我们进行监视。在POSIX上,它将是
        mmap
        ,在Windows上,它将是
        CreateFileMapping
        +
        MapViewOfFile
        内存映射不是标准的一部分。不过,Boost Interprocess支持跨平台内存映射。我想?@awoodland:是的。在C++0x中,它也被弃用。Since deprecated意味着“需要出现在任何一致的实现中”,我们可以这样做;-)另一种方法是重写代码,直接在映射数组上操作,而不是通过流,但是使用
        istrstream
        (必须是只读的)是非常无害的。只有在原始访问是随机的情况下,这才是正确的。如果最初的访问是顺序的,那么由两个线程引起的随机访问将使情况变得更糟。他明确表示,按顺序阅读是不够的。