我有一个多线程C ++ 11程序,其中每个线程产生大量需要写入磁盘的数据。所有数据都需要写入一个文件。目前,我使用一个互斥锁来保护从多个线程访问文件。我的朋友建议我可以为每个线程使用一个文件,然后在最后将文件合并到一个文件中,使用cat
从C ++代码完成system()
命令。
我在想如果cat
命令将从磁盘读回所有数据,然后再将其写入磁盘,但这次只能写入一个文件,它不会更好。我用谷歌搜索但找不到cat
命令实现细节。我可以知道它是如何工作的,是否会加速整个过程?
修改 事件的年表并不重要,并且对文件的内容没有排序约束。这两种方法都可以实现我想要的效果。
答案 0 :(得分:7)
您没有指定是否对文件内容有一些排序或结构限制。通常是这种情况,所以我会这样对待它,但希望我的解决方案应该以任何一种方式工作。
经典的程序化方法
这个想法是将写入磁盘的工作卸载到专用的IO线程,并有一个多生产者/一个消费者队列来排队所有的写命令。每个工作线程只是将其输出格式化为字符串并将其推回队列。 IO线程将来自队列的批量消息弹出到缓冲区中,并发出写命令。
或者,您可以在消息中添加一个字段,以指示哪个worker发出了write命令,并在需要时将IO线程推送到不同的文件。
为了获得更好的性能,如果您的主机操作系统支持它们,那么查看IO系统原语(读/写)的异步版本也很有意思。然后,IO线程将能够监视多个并发IO,并在终止后立即向操作系统提供新的。
正如评论中所建议的那样,您必须监控IO线程是否存在拥塞情况,并相应地调整工作人员数量。基于“自然”反馈的机制是简单地使队列受限制,并且工作人员将等待锁定,直到空间释放为止。这使您可以在过程生命周期中的任何时刻控制生成的数据量,这是内存受限场景中的一个重要点。
您的cat
问题
至于cat
,this command line tool只是读取写入其输入通道的任何内容(通常为stdin
),并将其复制到其输出(stdout
)。这很简单,你可以清楚地看到与上面提到的解决方案的相似性。不同之处在于cat
不理解文件内部结构(如果有的话),它只处理字节流,这意味着如果多个进程同时写入cat
输入而没有同步,结果输出可能会完全混淆。另一个问题是IO基元的atomicity(或缺少)。
注意:在某些系统上,有一个简洁的小功能,称为fork,它允许您在单个文件中复用多个“独立”数据流。如果您碰巧在支持该功能的平台上工作,您可以将所有数据流捆绑在一个文件中,但可以单独访问。