我可以报告 openmp 任务的进度吗?

2023-12-27

想象一个经典的 OMP 任务:

  • 对 [0.0, 1.0) 范围内的双精度型大向量求和

Live On Coliru http://coliru.stacked-crooked.com/a/6167c106392d7020

using namespace std;

int main() {
    vector<double> v;

    // generate some data
    generate_n(back_inserter(v), 1ul << 18, 
       bind(uniform_real_distribution<double>(0,1.0), default_random_engine { random_device {}() }));

    long double sum = 0;

    {
#pragma omp parallel for reduction(+:sum)
        for(size_t i = 0; i < v.size(); i++)
        {
            sum += v[i];
        }
    }
    std::cout << "Done: sum = " << sum << "\n";
}

我无法想出如何报告进度。毕竟,OMP 正在为我处理团队线程之间的所有协调,而我没有全局状态。

我可能会使用常规的std::thread并从那里观察一些共享变量,但是没有更“omp-ish”的方法来实现这一点吗?


在没有本机原子支持(甚至有它们)的处理器上使用#pragma omp atomic正如这里的其他答案所暗示的那样,可能会减慢您的程序速度。

进度指示器的想法是给用户一个idea某事何时完成。如果您的目标是加/减总运行时间的一小部分,用户就不会太烦恼。也就是说,用户希望事情尽快完成,但代价是更准确地知道事情何时完成。

因此,我通常仅跟踪单个线程的进度并使用它来估计总进度。这对于每个线程具有相似工作负载的情况来说是很好的。既然你正在使用#pragma omp parallel for,您可能正在处理一系列没有相互依赖性的类似元素,因此我的假设可能对您的用例有效。

我已经将这个逻辑包装在一个类中ProgressBar,我通常将其及其辅助类包含在头文件中Timer。该类使用 ANSI 控制信号来保持外观美观。

输出如下所示:

[======                                            ] (12% - 22.0s - 4 threads)

通过声明以下内容,编译器也可以轻松消除进度条的所有开销-DNOPROGRESS编译标志。

代码和示例用法如下:

#include <iostream>
#include <chrono>
#include <thread>
#include <iomanip>
#include <stdexcept>

#ifdef _OPENMP
  ///Multi-threading - yay!
  #include <omp.h>
#else
  ///Macros used to disguise the fact that we do not have multithreading enabled.
  #define omp_get_thread_num()  0
  #define omp_get_num_threads() 1
#endif


///@brief Used to time how intervals in code.
///
///Such as how long it takes a given function to run, or how long I/O has taken.
class Timer{
 private:
  typedef std::chrono::high_resolution_clock clock;
  typedef std::chrono::duration<double, std::ratio<1> > second;

  std::chrono::time_point<clock> start_time; ///< Last time the timer was started
  double accumulated_time;                   ///< Accumulated running time since creation
  bool running;                              ///< True when the timer is running

 public:
  Timer(){
    accumulated_time = 0;
    running          = false;
  }

  ///Start the timer. Throws an exception if timer was already running.
  void start(){
    if(running)
      throw std::runtime_error("Timer was already started!");
    running=true;
    start_time = clock::now();
  }

  ///Stop the timer. Throws an exception if timer was already stopped.
  ///Calling this adds to the timer's accumulated time.
  ///@return The accumulated time in seconds.
  double stop(){
    if(!running)
      throw std::runtime_error("Timer was already stopped!");

    accumulated_time += lap();
    running           = false;

    return accumulated_time;
  }

  ///Returns the timer's accumulated time. Throws an exception if the timer is
  ///running.
  double accumulated(){
    if(running)
      throw std::runtime_error("Timer is still running!");
    return accumulated_time;
  }

  ///Returns the time between when the timer was started and the current
  ///moment. Throws an exception if the timer is not running.
  double lap(){
    if(!running)
      throw std::runtime_error("Timer was not started!");
    return std::chrono::duration_cast<second> (clock::now() - start_time).count();
  }

  ///Stops the timer and resets its accumulated time. No exceptions are thrown
  ///ever.
  void reset(){
    accumulated_time = 0;
    running          = false;
  }
};


///@brief Manages a console-based progress bar to keep the user entertained.
///
///Defining the global `NOPROGRESS` will
///disable all progress operations, potentially speeding up a program. The look
///of the progress bar is shown in ProgressBar.hpp.
class ProgressBar{
 private:
  uint32_t total_work;    ///< Total work to be accomplished
  uint32_t next_update;   ///< Next point to update the visible progress bar
  uint32_t call_diff;     ///< Interval between updates in work units
  uint32_t work_done;
  uint16_t old_percent;   ///< Old percentage value (aka: should we update the progress bar) TODO: Maybe that we do not need this
  Timer    timer;         ///< Used for generating ETA

  ///Clear current line on console so a new progress bar can be written
  void clearConsoleLine() const {
    std::cerr<<"\r\033[2K"<<std::flush;
  }

 public:
  ///@brief Start/reset the progress bar.
  ///@param total_work  The amount of work to be completed, usually specified in cells.
  void start(uint32_t total_work){
    timer = Timer();
    timer.start();
    this->total_work = total_work;
    next_update      = 0;
    call_diff        = total_work/200;
    old_percent      = 0;
    work_done        = 0;
    clearConsoleLine();
  }

  ///@brief Update the visible progress bar, but only if enough work has been done.
  ///
  ///Define the global `NOPROGRESS` flag to prevent this from having an
  ///effect. Doing so may speed up the program's execution.
  void update(uint32_t work_done0){
    //Provide simple way of optimizing out progress updates
    #ifdef NOPROGRESS
      return;
    #endif

    //Quick return if this isn't the main thread
    if(omp_get_thread_num()!=0)
      return;

    //Update the amount of work done
    work_done = work_done0;

    //Quick return if insufficient progress has occurred
    if(work_done<next_update)
      return;

    //Update the next time at which we'll do the expensive update stuff
    next_update += call_diff;

    //Use a uint16_t because using a uint8_t will cause the result to print as a
    //character instead of a number
    uint16_t percent = (uint8_t)(work_done*omp_get_num_threads()*100/total_work);

    //Handle overflows
    if(percent>100)
      percent=100;

    //In the case that there has been no update (which should never be the case,
    //actually), skip the expensive screen print
    if(percent==old_percent)
      return;

    //Update old_percent accordingly
    old_percent=percent;

    //Print an update string which looks like this:
    //  [================================================  ] (96% - 1.0s - 4 threads)
    std::cerr<<"\r\033[2K["
             <<std::string(percent/2, '=')<<std::string(50-percent/2, ' ')
             <<"] ("
             <<percent<<"% - "
             <<std::fixed<<std::setprecision(1)<<timer.lap()/percent*(100-percent)
             <<"s - "
             <<omp_get_num_threads()<< " threads)"<<std::flush;
  }

  ///Increment by one the work done and update the progress bar
  ProgressBar& operator++(){
    //Quick return if this isn't the main thread
    if(omp_get_thread_num()!=0)
      return *this;

    work_done++;
    update(work_done);
    return *this;
  }

  ///Stop the progress bar. Throws an exception if it wasn't started.
  ///@return The number of seconds the progress bar was running.
  double stop(){
    clearConsoleLine();

    timer.stop();
    return timer.accumulated();
  }

  ///@return Return the time the progress bar ran for.
  double time_it_took(){
    return timer.accumulated();
  }

  uint32_t cellsProcessed() const {
    return work_done;
  }
};

int main(){
  ProgressBar pg;
  pg.start(100);
  //You should use 'default(none)' by default: be specific about what you're
  //sharing
  #pragma omp parallel for default(none) schedule(static) shared(pg)
  for(int i=0;i<100;i++){
    pg.update(i);
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我可以报告 openmp 任务的进度吗? 的相关文章

  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • C++ 是否可以在 MacOS 上与 OpenMP 和 boost 兼容?

    我现在已经尝试了很多事情并得出了一些结论 也许 我监督了一些事情 但似乎我无法完成我想要的事情 问题是 是否有可能使用 OpenMP 和 boost 在 MacOS High Sierra 上编译 C 一些发现 如果我错了请纠正我 Open
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 查看 NuGet 包依赖关系层次结构

    有没有一种方法 文本或图形 来查看 NuGet 包之间的依赖关系层次结构 如果您使用的是新的 csproj 您可以在此处获取所有依赖项 在项目构建后 项目目录 obj project assets json
  • C# 数据表更新多行

    我如何使用数据表进行多次更新 我找到了这个更新 1 行 http support microsoft com kb 307587 my code public void ExportCSV string SQLSyntax string L
  • File.AppendText 尝试写入错误的位置

    我有一个 C 控制台应用程序 它作为 Windows 任务计划程序中的计划任务运行 此控制台应用程序写入日志文件 该日志文件在调试模式下运行时会创建并写入应用程序文件夹本身内的文件 但是 当它在任务计划程序中运行时 它会抛出一个错误 指出访
  • 在Linux中,找不到框架“.NETFramework,Version=v4.5”的参考程序集

    我已经设置了 Visual studio 来在我的 Ubuntu 机器上编译 C 代码 我将工作区 我的代码加载到 VS 我可以看到以下错误 The reference assemblies for framework NETFramewo
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • 使 Guid 属性成为线程安全的

    我的一个类有一个 Guid 类型的属性 该属性可以由多个线程同时读写 我的印象是对 Guid 的读取和写入不是原子的 因此我应该锁定它们 我选择这样做 public Guid TestKey get lock testKeyLock ret
  • 可访问性不一致:参数类型的可访问性低于方法

    我试图在两个表单之间传递一个对象 基本上是对当前登录用户的引用 目前 我在登录表单中有一些类似的内容 private ACTInterface oActInterface public void button1 Click object s
  • GCC 的“-Wl,option”和“-Xlinker option”语法之间有区别吗?

    我一直在查看一些配置文件 并且看到它们都被使用 尽管在不同的体系结构上 如果您在 Linux 机器上使用 GCC 将选项传递给链接器的两种语法之间有区别吗 据我所知 阅读 GCC 手册时 他们的解释几乎相同 From man gcc Xli
  • 中断连接套接字

    我有一个 GUI 其中包含要连接的服务器列表 如果用户单击服务器 则会连接到该服务器 如果用户单击第二个服务器 它将断开第一个服务器的连接并连接到第二个服务器 每个新连接都在一个新线程中运行 以便程序可以执行其他任务 但是 如果用户在第一个
  • 是否可以在不连接数据库的情况下检索 MetadataWorkspace?

    我正在编写一个需要遍历实体框架的测试库MetadataWorkspace对于给定的DbContext类型 但是 由于这是一个测试库 我宁愿不连接到数据库 它引入了测试环境中可能无法使用的依赖项 当我尝试获取参考时MetadataWorksp
  • 不区分大小写的字符串比较 C++ [重复]

    这个问题在这里已经有答案了 我知道有一些方法可以进行忽略大小写的比较 其中涉及遍历字符串或一个good one https stackoverflow com questions 11635 case insensitive string

随机推荐

  • 将列表转换为字符串?

    我想知道是否有办法将我的列表转换为字符串 示例 有没有办法转换MyList a b c d e to MyString abcde 原因 我试图用这 5 个字母组成单词 bag bad cab bed 我尝试创建一个标签来显示MyList
  • 如何暂停后续任务直到第一次完成然后与等待的任务共享其响应?

    我有一个actor它以第一个请求暂停后续请求直到完成的方式限制请求 然后与它们共享其响应 这样它们就不必发出相同的请求 这就是我想做的 let cache Cache let operation OperationStatus func e
  • 映射的网络驱动器未显示在“我的电脑”中

    我正在尝试使用 PowerShell 5 0 创建外部网络驱动器 我需要这些驱动器才能显示在 我的电脑 中 为此 我使用以下命令 New PSDrive Name X PSProvider FileSystem Root 192 168 0
  • int* p 和 int *p 声明之间的区别[重复]

    这个问题在这里已经有答案了 和有什么区别int p and an int p宣言 有没有不同 这是一个问题notation not 语义 第二个是较少误导 因为 int a b 明确宣布int and an int 然而 int a b 看
  • 需要适当的 MySQL 查询

    很抱歉在这里问这个问题 但我对 JOIN 的理解相当不稳定 几个小时的混乱并没有让我有任何结果 这是我已经设置的以及我需要的 我有三张表 每一张用于用户 位置和签到 每次用户前往某个位置时 他们都可以在那里签到 签到表示例如下 checki
  • 如何在 Chrome headless 中评估脚本?

    节点有 e and p分别用于评估和评估并打印的标志 我知道有一个 replChrome headless 的标志 但我想知道是否有一种方法可以评估并打印表达式 例如 chrome headless eval and print navig
  • 为什么 java.util.Collection 上有一个方法 iterator()

    当接口 java util Collection 已经扩展了定义了此方法的 java util Iterable 时 为什么还要在接口 java util Collection 上定义该方法 iterator 呢 我正在考虑某种向后兼容性或
  • 从Datamapper开始,关联问题

    我刚刚深入研究 Datamapper 和 Sinatra 并有一个关于关联的问题 以下是我拥有的一些型号 这就是我想要实现的 我在锻炼项目和锻炼方面遇到问题 锻炼将单独管理 但锻炼项目有与每一行关联的单个锻炼 锻炼 只是类型的列表 锻炼 跑
  • 带有重新分析点的FolderBrowserDialog SelectedPath

    当我选择的文件夹位于远程服务器上并且是符号链接 或任何类型的重新分析点 时 我遇到了 FolderBrowserDialog 的 SelectedPath 属性问题 如果我选择普通文件夹 则会返回完整路径 例如 SERVER folder
  • MySQL 数据 - 实现分页的最佳方式?

    我的 iPhone 应用程序连接到我的 PHP Web 服务以从 MySQL 数据库检索数据 一个请求最多可返回 500 个结果 实现分页并一次检索 20 个项目的最佳方法是什么 假设我从数据库收到前 20 个条目 现在如何请求接下来的 2
  • java.lang.String的哈希码真的被缓存了吗?

    String s1 String1 System out println s1 hashCode return an integer i1 Field field String class getDeclaredField value fi
  • 在 Python 中对集合进行排序与​​对列表进行排序在时间上存在巨大差异

    我想知道我是否应该将数据结构作为集合或列表 大多数情况下我会进行集合运算 但最终我需要对其进行排序 我想知道是否应该先将集合设为列表 然后使用sorted list my set 或者立即对集合进行排序sorted my set 可以说 我
  • SPARQL DESCRIBE 查询

    看来我不理解 SPARQL DESCRIBE 查询 我需要检索与条件匹配的资源的完整图表 在我尝试过的一个 SPARQL 端点上 挪威 R data N http data bibsys no data query authority ht
  • 如何更改 Android 上切换按钮的背景颜色

    我尝试使用 XML 文件将切换按钮的背景颜色更改为白色 但切换按钮完全损坏 看起来所有的按钮都被白色覆盖了 当我将切换按钮的颜色更改为白色时 切换按钮上没有打开或关闭的指示 是否有另一种方法可以更改背景而不会损坏切换按钮的指示
  • 使用 React Router 6 导航时恢复滚动位置

    如何设置 React Router 6 以在导航和刷新浏览器窗口时恢复滚动位置 React Router 5 有一个关于滚动恢复的页面 https v5 reactrouter com web guides scroll restorati
  • 如何混淆(保护)JavaScript? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想制作一个非开源的 JavaScript 应用程序 因此我想了解如何混淆我的 JS 代码 这可能吗 混淆 尝试YUI压缩器 http
  • 交错2个不等长度的列表[重复]

    这个问题在这里已经有答案了 我希望能够交错两个长度可能不相等的列表 我所拥有的是 def interleave xs ys a xs b ys c a b c 2 a c 1 2 b return c 这对于长度等于或只是 1 的列表非常有
  • C# 3.5 参数的可选值和默认值

    我正在使用 C net 3 5 构建应用程序 我一直在 net 4 0 中使用可选参数属性 没有出现任何问题 我确实注意到 在 3 5 中 可以选择 解决方法 将以下属性添加到您的方法中 如下所示 public static void Me
  • 您可以在一个项目中混合使用 .net 语言吗?

    您可以在一个项目中混合使用 net 语言吗 所以预编译后 我想调用其他源文件的类和方法 对于网络和应用程序 我对 F 和 C 特别感兴趣 您可以在单个程序集中混合语言 and MSBuild http msdn microsoft com
  • 我可以报告 openmp 任务的进度吗?

    想象一个经典的 OMP 任务 对 0 0 1 0 范围内的双精度型大向量求和 Live On Coliru http coliru stacked crooked com a 6167c106392d7020 using namespace