【问题标题】:How to time a methods execution using chrono in C++?如何在 C++ 中使用 chrono 计时方法执行?
【发布时间】:2020-03-06 22:04:43
【问题描述】:

所以这是我第一次尝试进行性能测量,并在我的课程作业中尝试之前使用了一些在线资源来测试我的代码的较小版本。不幸的是,我无法让它打印完成该功能所花费的时间,而且我不确定我是否做得对。

#include <string>
#include <iostream>
#include <unordered_map>
#include <chrono>

using namespace std;

class Timer {
public:
   Timer() {
       startTimept = std::chrono::high_resolution_clock::now();
   }

   ~Timer() {
       Timer Stop();
   }

   void Stop() {
       auto endTimept = std::chrono::high_resolution_clock::now();

       auto start = std::chrono::time_point_cast<std::chrono::microseconds>(startTimept).time_since_epoch().count();
       auto end = std::chrono::time_point_cast<std::chrono::microseconds>(endTimept).time_since_epoch().count();

       auto duration = end - start;
       double ms = duration * 0.001;

       std::cout << duration << "us (" << ms << "ms)";

   }
private:
   std::chrono::time_point<std::chrono::high_resolution_clock> startTimept;
};

int main()
{
   std::unordered_map<std::string, std::string>::iterator found, start, nFound;

//ADDS PAIRS OF SENTENCE INTO A MAP
   std::unordered_map<std::string, std::string> sortMap =
   { { "these", "pairs" }, { "the", "correct" }, { "pairs", "makes" }, { "correct", "sentence" }, { "makes", "the" } };
   std::unordered_map<std::string, std::string> swapMap =
   { { "pairs","these" }, {"correct", "the"}, { "makes", "pairs" }, {"sentence", "correct" }, {"the",  "makes"} };

//CREATES CONTAINER TO STORE COMPLETE SENTENCE
   std::list<std::string> resultSeq;

   start = sortMap.begin();

//ADD STARTING WORDS INTO THE LIST
   resultSeq.push_back(start->first);
   resultSeq.push_back(start->second);

//TEMP POINTER TO SOUGHT WORD
   found = sortMap.find(start->second);

//THIS IS THE FUNCTION I AM TRYING TO TEST
   {
       Timer timer();
       for (auto it = sortMap.begin(); it != sortMap.end(); ++it) {
           if (it == found) {
               resultSeq.push_back(it->second);
               found = sortMap.find(it->second);
               it = sortMap.begin();
           }
       }
   }

   for (std::list<std::string>::iterator hard = resultSeq.begin(); hard != resultSeq.end(); ++hard)
   {
       std::cout << (*hard) << std::endl;
   }

   __debugbreak;
}

如果有人能发现我做错了什么或提供任何链接来帮助进行性能测量,那将非常有帮助!

【问题讨论】:

  • 小测验:startTimept 究竟是如何被初始化的?在要测量的性能实际执行之前,哪一行代码将其值设置为当前时间?
  • 所以据我了解,它在 Timer 类的私有部分初始化,但我认为 start 将值设置为当前时间,但现在我正在查看它,我有一个感觉它可能根本没有设置
  • 你看警告了吗?看起来很重要。顺便说一句,这个问题实际上与性能测试无关,代码与此相关,但这不是问题所涉及的方面。
  • 哦,我明白了,这是一个最令人头疼的解析问题。有趣的是,wikipedia page 上的示例还使用了一个名为 Timer 的类。
  • 你应该感到困惑。令人烦恼是有原因的。您遇到的问题是 Timer timer() 看起来与函数声明完全一样,因此编译器不会创建名为 timer 的变量,而是声明一个从未使用过的名为 timer 的函数,因此错误不会被稍后编译。通常,您稍后会在代码中使用timer 作为变量,然后会收到一条编译器错误消息,上面写着“Timer 不是变量,伙计。”

标签: c++ methods execution chrono


【解决方案1】:

您应该使用std::steady_clock 来测量时差。 std::system_clock 可以是任何东西,不需要是单调的。 std::high_resolution_clock 也是如此。

high_resolution_clock 的实施不一致 不同的标准库实现,和它的使用应该是 避免。它通常只是 std::chrono::steady_clock 或的别名 std::chrono::system_clock,但它是哪一个取决于库 或配置。当是system_clock时,不是单调的 (例如,时间可以倒退)。例如,对于 gcc 的 libstdc++ 它 是 system_clock,对于 MSVC 是 stable_clock,对于 clang 的 libc++ 这取决于配置。

此外,为了封装时间测量,您可以利用 C++ 的 RAII 机制:

#include <chrono>
#include <type_traits>
#include <iostream>

template <typename Resolution = std::chrono::duration<double,std::micro>>
class Stopwatch {
  typedef std::chrono::steady_clock Clock;
  private:
    std::chrono::time_point<Clock> last;
  public:
    void reset() noexcept {
      last = Clock::now();
    }   
    Stopwatch() noexcept {
      reset();
    }   
    auto operator()() const noexcept {// returns time in Resolution
      return Resolution(Clock::now() - last).count();
    }
    ~Stopwatch() {
      // bad encapulation, you should reconsider this design!
      // e.g. take a std::function as argument to the constructor and call it here
      std::cout << (*this)() << "\n";
    }
};

int main() {
  { // the block I want to measure
    Stopwatch sw;
    (void)(1+2+3); // some costly operation
  } // end of measured block
}

【讨论】:

    【解决方案2】:

    如果只是为了快速调试,我个人的方法是使用std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(std::chrono::system_clock::now().time_since_epoch()).count();。由于它很罗嗦,我建议为它制作一个包装函数。无论如何,这只是返回自 1970 年以来以毫秒为单位的时间(不确定)。然后,您只需在函数之前粘贴一个,在函数之后粘贴一个,cout 差异,您就有了函数执行所需的毫秒数。

    【讨论】:

      猜你喜欢
      • 2018-11-03
      • 2020-04-02
      • 2010-09-15
      • 2018-06-23
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多