涉及大量磁盘 I/O 的大批量处理的并行方法

Posted

技术标签:

【中文标题】涉及大量磁盘 I/O 的大批量处理的并行方法【英文标题】:Parallel approach for large batch processing involving a lot of disk I/O 【发布时间】:2019-04-12 03:24:27 【问题描述】:

我有一个任务需要执行以下操作

for fi in files, do in parallel:
  for job in jobs, do serially:
    read fi into memory from disk
    do job(fi), save output to disk

(任务的特殊性使得并行化内部循环变得不切实际。)

有数千个 files 和大约 400 个 jobs。现在files 是一堆.csv,我将输出保存到其他地方的一堆csv。输入 csv 大约 30MB,输出大约 10MB

我真正想要的是一个数据库,但我所知道的数据库无法处理并行 I/O。所以我只是从一堆csv中读取并保存。我知道操作系统也不能进行并行 I/O,但它比我知道的数据库更好地处理并行请求。

那么,有什么更好的方法来做到这一点?我在 AWS 上,现在一切都在 EBS 卷中。将所有输入推送到 S3 存储桶、根据需要下载它们并上传输出(每个文件大小为几 MB),我是否期望获得更好的性能?

或者是否有某种并行 I/O 数据库架构存在于云端某个地方,我可以了解然后租用?

感谢您就如何解决此问题提出建议。

【问题讨论】:

每个文件csv大概有多大? @displayName 输入的 CSV 文件大约为 30MB。输出的大约是 10MB。问题已编辑 job(fi) 的计算密集度如何? @displayName 相当大。我需要确保我的实例每个工作人员有大约 6 GB 的 RAM。 多久会重复一次?您是在寻找短期解决方案还是长期流程? 【参考方案1】:

我认为你做的 I/O 比你需要的多。你有:

for fi in files, do in parallel:
  for job in jobs, do serially:
    read fi into memory from disk
    do job(fi), save output to disk

假设您有能力创建内存流,您可以这样做:

for fi in files, do in parallel:
  read fi into memory and create memory stream ms
  for job in jobs, do serially:
    do job(ms), save output to disk

当然,这假设您正在制作从磁盘读取的文件的副本,而不是就地修改它。

这应该会大大提高您的速度。与其读取数千个文件 400 次,不如读取每个文件一次。

【讨论】:

【参考方案2】:

30MB 对于现代系统来说不算什么。所以我猜你的瓶颈是工作,而不是 IO。您需要确认猜测,但看起来改进 IO 是浪费时间。

您可以尝试减少文件大小和计算复杂性的方法是简单地使用自定义二进制格式。文件的大小会更小,读取它们会花费更少的时间,因为我们不需要将字符串转换为数字,反之亦然。

只是一个想法......

【讨论】:

虽然这可能是真的,但拥有一个数据库肯定会很方便。 @generic_user 然后使用它!无论 SQL/noSQL 数据库将处理 30MB。不要浪费时间寻找并行 IO,因为如果有的话,差异可以忽略不计......【参考方案3】:

您的job 是计算密集型的。因此,如果您已经实现了 100% 的 CPU 使用率,我怀疑通过并行读取是否会有所改进。

可以做两件事来改进您当前的解决方案:

    如果您还没有这样做,请使用 SSD 将 I/O 时间降至最低; 划分您的任务,以便您可以使用多台机器。如果您已达到 100% 的 CPU 使用率并希望做得更快,那么您显然需要更多的内核来运行您的任务。

【讨论】:

以上是关于涉及大量磁盘 I/O 的大批量处理的并行方法的主要内容,如果未能解决你的问题,请参考以下文章

I/O多路复用之epoll

如何加速Oracle大批量数据处理?

批量处理大量数据集Laravel

Python调用MYSQL,将文件名和路径批量入库用法小结

使用pssh进行并行批量操作

MySQL批量更新大量的数据方法分享