【问题标题】:C++ accurately do action in "every" 100 microsecond without pausingC++ 在“每” 100 微秒内准确地执行操作而不会暂停
【发布时间】:2016-11-09 15:17:13
【问题描述】:

我编写了一个程序,该程序需要在一个循环中定期循环 100 微秒。我发现 to 在固定的时间内定期循环。但是当循环时间设置得太小时,我发现了一个问题。

以下演示代码(不完整代码)是:

  1. 每 100 微秒增加一次 count
  2. 每 1 秒显示一次 count

预期的结果是每秒显示大约 10000 个。

结果显示每秒大约 4000

void f2(int input)
{
    auto start = std::chrono::system_clock::now();
    auto displayStart = std::chrono::system_clock::now();
    while(true){    //keep looping quickly
      auto now = std::chrono::system_clock::now();
      auto interval = std::chrono::duration_cast<std::chrono::microseconds>(now - start);
      if ( interval.count() > input){   //if 100 microsecond do
            count++;
            start = std::chrono::system_clock::now();
      }

      auto displayNow = std::chrono::system_clock::now();
      auto displayInterval = std::chrono::duration_cast<std::chrono::microseconds>(displayNow - displayStart);
      if ( displayInterval.count() > 1000000){  //if 1 second do
        std::cout<< "1 second count: "<<count<<std::endl;
        count=0;
        displayStart = std::chrono::system_clock::now();

      }

    }

}

在那之后我认为CPU调度可能是这个问题。我检查了程序在每个循环中都能正常工作。每次迭代大约需要 100 微秒,这是准确的。但是当程序/线程暂停并等待CPU重新调度时,可能会出现问题。

例如,让我们放大该值以获得更清晰的说明。线程暂停了 1 秒。通常它会增加 10000 次。但是现在,对于下一次迭代,它会检查 >100 微秒,因此 count++ 和计数器在经过 1 秒时被重置。对于这种情况,计数仅增加 1。

使用我修改的以下代码,我可以在一秒钟内完成 10000 个count++但问题是这10000个计数并不是在一秒钟内均匀分布的。因为这只是用于测试的演示程序。 我真正想要的动作是每 100 微秒准确地执行一次动作。但是由于线程暂停,我仍然没有找到解决这个问题的方法。

void f2(int input)
{
    auto start = std::chrono::system_clock::now();
    auto displayStart = std::chrono::system_clock::now();
    while(true){    //keep looping quickly
      auto now = std::chrono::system_clock::now();
      auto interval = std::chrono::duration_cast<std::chrono::microseconds>(now - start);
      if ( interval.count() > input){   //if 100 microsecond do
            for(int i=0;i<interval.count()/input;i++){    //modified part
                count++;
            }
            start = std::chrono::system_clock::now();

      }


      auto displayNow = std::chrono::system_clock::now();
      auto displayInterval = std::chrono::duration_cast<std::chrono::microseconds>(displayNow - displayStart);
      if ( displayInterval.count() > 1000000){  //if 1 second do
        std::cout<< "1 second count: "<<count<<std::endl;
        count=0;
        displayStart = std::chrono::system_clock::now();


      }


    }


}

有没有类似的方法: 例如。使过程不暂停。将其保存在 CPU 中(不太可能) 让演示程序中的计数动作每 100 微秒运行一次?

非常感谢

【问题讨论】:

  • 对于这种精度,您需要a real-time operating system。通用操作系统不会让您实现这一点 - 例如,您的程序可能随时被驱动程序中断。无论如何 - 你想解决什么样的问题,你觉得需要 10,000 FPS 的性能?
  • 感谢您的回答。我必须为程序使用 linux。我正在编写一个软件开关,计数器每 100 微秒需要 *0.08 次,以便为其他目的计算一些数据。 (计算每个端口的拥塞数据)
  • 恐怕您必须找到另一种方法来计算该数据。如果您解释您要解决的实际问题,而不是您尝试的解决方案(无论如何您都无法开始工作),您可能会得到一些帮助。另见:XY problem
  • @RaymondMa 您需要每 100 毫秒执行一次吗?如果是 200 毫秒,*.08 * .08 会不起作用吗?你能用时间戳记录所有活动并不断衰减它们吗?
  • @RaymondMa 您可能想查看实时 linux 选项。其中一些声称适合硬实时。

标签: c++ loops scheduling


【解决方案1】:

有 N 个桶,其中 N 足够大,调度延迟不会成为问题。

跟踪您的衰减代码上次运行的时间。

当一个新数据包“发出”时,根据您的衰减代码上次运行的时间将其放入存储桶中(如果小于 100 毫秒,存储桶 0,如果 200 毫秒,存储桶 1,等等)。

当您的衰减代码运行时,在正确衰减所有内容后计算当前值并更新时间戳。

请注意,争用(线程更新和线程衰减)仍然是一个问题。您可以通过计数器、原子标志和指针以及非性能敏感代码(例如衰减代码)中的繁忙循环的双重或三重缓冲来在一定程度上解决此问题。

或者,不记录计数,而是记录时间戳。消耗时间戳的缓冲区,在该点进行衰减。涉及缓冲区大小和多线程的类似问题仍然存在,采用类似的解决方案。

或者,在进行计数的代码中进行衰减数学运算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多