c++ - 使用 OpenMP 获得完整、未损坏的输出需要什么?
问题描述
我有一些在 c++11 标准下编译的代码。我有多个线程写入 cout。我注意到在写很多行时,会有一些行丢失的情况(比如 2000000 行中有 1 行)。我很惊讶地看到这一点,因为我的字符串(outStr
下面)是每个线程的本地字符串,并且我在写入 stdout 时有一个关键部分。当我刷新流时,我注意到问题消失了。
#pragma omp critical(cout)
{
cout << outStr;
cout.flush();
}
这是预期的行为吗?真正欺骗我的是,当我写的行数相对较少(<100000)时,我总是会看到输出的预期行数。
总的来说,我对关键部分并不满意,因为我在分析中注意到它引起了很多争论。我愿意接受任何改进我的 I/O 的建议。
*编辑我的印象是,在 c++11 下,只要我同步我的输出(即当我使用关键部分时没有交错或丢失输出),我的输出就不会损坏,但丢失的行似乎表明如果不刷新输出,这不是保证。
解决方案
这里的大部分问题源于刷新流非常慢的事实。因此,当一个线程进入临界区时,它们会在其中停留相当长的一段时间。当他们完成时,可能还有其他几个线程在等待,所以它成为一个严重的瓶颈。
防止该问题的最明显方法可能是让流本身由一个线程拥有,并拥有一个线程安全队列,其中包含需要写入流的事物。如果您可以累积数据“块”以将流转换为字符串(或其他一些预先确定的数据结构),那么这甚至是微不足道的。
我要郑重说明,虽然您最终可能想要使用无锁队列,但基于锁定的相当简单、老式的队列几乎肯定会比您现在正在做的事情提供巨大的改进——将字符串插入队列比刷新流要快得多(在纳秒到可能几微秒的范围内,其中刷新通常在毫秒级)。
推荐阅读
- python - Round 函数会根据类型返回不同的值
- asp.net - Windows 身份验证适用于 IIS,但不适用于 Kestrel / Microsoft.AspNetCore.Authentication.Negotiate(不在 Chrome 中,有时在 Edge 中,总是在 IE 中)?
- c# - C# SQL SERVER - 无法将 nvarchar 转换为文本?
- arrays - 如何在视图中居中排列节点?
- javascript - 如何在给定相对文件路径(Angular)的情况下下载文件?
- macos - 在 macOS 中将自签名证书添加为受信任无法正常工作
- php - 使用 EasyDeploy 部署时未找到 APP_SERVER env var
- sql - 在 hive 中选择 minValue 及其行
- node.js - Express.js/Typescript:错误 TS2339:“响应”类型上不存在属性“发送”
- java - 将ojdbc添加到maven项目