【问题标题】:Create huge text file - multi-threading a good idea?创建巨大的文本文件——多线程是个好主意?
【发布时间】:2020-12-07 17:41:12
【问题描述】:

需要创建巨大的 (>10 Gb) 文本文件,其中每一行都是一个很长的数字,基本上是一个字符串,因为像 unsigned long long 这样的偶数类型是不够的。所以我将使用随机生成器,但首先创建多个线程可能是个好主意。据我所知,每个线程一次只写一行,这在 C++ 中被认为是线程安全的操作。 这是一个好主意还是我错过了什么,最好从一个线程逐行编写?

【问题讨论】:

  • 这里的瓶颈是IO操作而不是CPU操作,所以在这里添加线程是没有意义的。
  • 你在std::ofstream中使用<<操作符?
  • 随机数:不是线程安全的。流 IO:不是线程安全的。写入同一个文件是有争议的(相同的资源)并且会导致过度阻塞。您的 IO 设备有多快?在设备跟不上之前有多少线程写入设备?
  • 总之...没有。
  • 除非它的文档明确声明某些东西是线程安全的,否则它不会是线程状态的。 C++ 中几乎没有什么是线程安全的。大多数时候你不需要线程安全,那么为什么要为你可能不使用的东西付出代价呢?相反,使用thread support library 中的工具,几乎所有东西都相对容易包装或以其他方式保护。

标签: c++ multithreading file c++11


【解决方案1】:

此处的正确答案在很大程度上取决于您要写入文件的驱动器类型。

如果它是一个实际的硬盘驱动器,那么单个线程可能能够生成您的随机数以磁盘可以接受的最快速度将数据写入磁盘。在现代 CPU 上使用合理的代码,运行该代码的内核可能会花费比实际工作更多的空闲时间。

如果它是一个 SATA 硬盘 SSD,实际上同样的事情也是如此,但是(尤其是如果您使用的是较旧的 CPU)运行代码的核心可能会花费更少的空闲时间。单个线程可能仍然能够生成数据并将其写入驱动器,只要驱动器可以接受它。

然后我们会谈到 NVMe 和 Optane 驱动器之类的东西。老实说,在这里,您可能有很大的机会通过从多个线程写入来提高性能。但是(至少根据我的经验)要做到这一点,您只需要跳过使用 iostreams,而是直接与操作系统对话。在 Windows 下,这意味着使用 CreateFile 打开文件(在您这样做时指定 FILE_FLAG_OVERLAPPED)。 Windows 还内置了对I/O completion ports(实际上是一种线程池)的支持,以最大限度地减少开销并提高性能——但使用它有点不简单。

在 Linux 上,异步 I/O 有点让人头疼。有一个用于执行异步 I/O 的官方 AIO 接口,Linux 已经实现了很长时间,但它从来没有真正运行得很好。最近,一个名为io_uring 的东西被添加到了Linux 内核中。我没有经常使用它,但它看起来可能是一个更好的设计——但它不(据我所知)支持标准 AIO 接口,所以你几乎必须通过它自己的 @987654322 来使用@ 反而。而不是 Windows I/O 完成端口,这很好用,但使用它有点不重要。

【讨论】:

    【解决方案2】:

    如果线程之间没有显式同步,您需要确保您使用的库函数是线程安全的。例如, 中的 C++ 随机数生成器不是,因此最好每个线程有一个 RNG。此外,您需要查看瓶颈。将数字转换为文本是一个瓶颈,多线程可以帮助解决这个问题。输出是另一个,多线程不会。分析将有助于解决此问题。

    Ostream 不是线程安全的,因此您必须使用同步来保护每个线程的访问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-12
      • 2015-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-19
      相关资源
      最近更新 更多