【问题标题】:C++ While loop, usleep()/sleep() how not to use 90% of CPU? (Ubuntu 12.04)C++ While循环,usleep()/sleep()怎么不占用90%的CPU? (Ubuntu 12.04)
【发布时间】:2014-04-11 23:15:48
【问题描述】:

假设我有 C++ 代码,例如

#include "myheaderfiles.h"
//..some stuff
//...some more stuff
int main()
{
   double milliseconds;
   int seconds;
   int minutes;
   int timelimit=2;
   ...
   ...
   //...code here that increments 
   //.....milliseconds,seconds, and minutes

   while(minutes <=timelimit)
   {
      //...do stuff
      if(milliseconds>500)
      {
         //...do stuff 
         //...every half second
      } //end if
   } //end while
}//end main

该程序将运行良好并执行它应该执行的操作,但它会占用我 90% 以上的 cpu。

有人建议我在我的 while 循环中每 100 毫秒左右使用一次 usleep(),因为无论如何我真的只关心每 500 毫秒做一次事情。这样,它会在不需要时占用 CPU。

所以我像这样将它添加到我的 while 循环中

   while(minutes <=timelimit)
   {
      //...do stuff
      if(milliseconds>500)
      {
         //...do stuff 
         //...every half second
      } //end if
      usleep(100000);
   } //end while

它编译得很好,但是当我运行它时,程序会在睡眠时挂起并且永远不会返回。我在某处读到,在调用 usleep 之前,需要刷新所有缓冲区,所以我刷新了所有文件流和 couts 等。仍然没有运气。

我已经搜索了 2 天的解决方案。我也使用过 sleep() ,但没有运气。

我找到了一些替代方案,但它们看起来很复杂,并且会在我的程序中添加很多我并不完全理解的代码,这会使它复杂化并使其变得混乱,而且它可能无法正常工作。

我之前从未真正在 while() 循环中考虑过太多,因为我编写的大多数程序都是针对微控制器或 FPGA 的,占用处理器是没有问题的。

如果有人可以提供帮助.... 任何资源、链接、书籍?谢谢。

【问题讨论】:

  • 请告诉我您没有使用 CPU 时钟来测量时间...
  • 你能展示你完整的 while() 循环吗?这可能有很多原因,这被称为忙循环问题。 usleep() 不会导致任何挂起。您的代码中还有其他问题。
  • 我想知道——该程序有什么可做的,还是只是在某处闲逛?如果有事要做,更快地完成它不应该受到伤害(在 *nix 或 Windows 上,尽管可以调低 prio)。如果您正在投票,也许有一个事件驱动的解决方案?
  • 如果你想要的话,为什么不注册让定时器唤醒并每隔半秒给你打电话呢?这似乎不是开始的正确解决方案。你确定它在睡觉时挂着吗?也许你没有正确增加“毫秒”。
  • 你有没有在你的程序中使用信号?

标签: c++ while-loop cpu usleep


【解决方案1】:

您的方法有些出自错误的目的。一个程序应该消耗 90-100% 的 CPU,只要它有一些有用的事情要做(否则它应该阻塞,消耗零 CPU)。
中间休眠会无故延长执行时间,并且消耗更多的能量,而不是尽可能快地完成工作(以 100% 的 CPU)然后完全阻塞直到有更多的工作可用或直到一些其他重要的事情(例如一半一秒钟过去了,如果这对你很重要)发生了。

考虑到这一点,您的程序的结构在概念上类似于:

while(blocking_call() != exit_condition)
{
    while(have_work)
        do_work();
}

另外,在执行期间不要休眠,而是使用计时器(例如setitimer)定期执行某些操作。这不仅效率更高,而且更加精确和可靠。

具体实现的方式取决于您希望软件的可移植性。在 Ubuntu/Linux 下,您可以使用诸如 epoll_waiteventfd 之类的 API,而不是为计时器编写信号处理程序。

【讨论】:

    【解决方案2】:

    此代码按预期工作(虽然在 OSX 上运行)。

      #include <unistd.h>
      #include <iostream> 
    
      int main() {
        std::cout << "hello" << std::endl;
    
        int i = 0;
        while(i < 10) {
          ++i;
          usleep(100000);
          std::cout << "i = " << i << std::endl;                                                                                                                                        
        }
        std::cout << "bye" << std::endl;
        return 0;
      }
    

    【讨论】:

      【解决方案3】:

      存在逻辑问题,或者您正在制作多个计数器?既然您说您已经完成了微控制器,我假设您在调用系统计时器时尝试使用时钟周期作为计数方法?另外,我想问的是,如果你被推荐使用 usleep(x),你为什么要使用 double 来表示毫秒? usleep(1) 是 1 微秒 == 1000 毫秒。 sleep(x) 是每 x 秒的计数器,因此系统会将其当前任务暂停 x 秒。

      #include <iostream>
      #include <unistd.h>
      
      using namespace std;
      
      #define MILLISECOND 1000
      #define SECOND 1000*MILLISECOND
      
      int main(int argc, char *argv[]){
          int time = 20;
          int sec_counter = 0;
          do{     
              cout<<sec_counter<<" second"<<endl;
              usleep(SECOND);
              sec_counter++;
          } while(sec_counter<time+1);
          return 0;
      }
      

      如果您想使用 500 毫秒,请将 usleep(SECOND) 替换为 usleep(500*MILLISECOND)。 我建议您使用调试器并单步执行您的代码以查看发生了什么。

      【讨论】:

      • 只是想指出 1 微秒不等于 1000 毫秒,反之亦然。您可能需要修改答案的最后一部分。
      猜你喜欢
      • 2010-09-06
      • 2012-11-20
      • 1970-01-01
      • 2010-10-09
      • 2012-01-31
      • 1970-01-01
      • 2020-03-17
      • 1970-01-01
      • 2016-01-21
      相关资源
      最近更新 更多