代码之家  ›  专栏  ›  技术社区  ›  Megadardery

如何测试两种算法并确定哪种算法更快?

  •  1
  • Megadardery  · 技术社区  · 7 年前

    每当我处理一个特定的问题时,我可能会遇到不同的解决方案。我不知道如何在这两个选项中选择更好的。第一个想法是计算两个解决方案的复杂性,但有时它们可能具有相同的复杂性,或者它们可能不同,但输入的范围很小,常数因子很重要。

    第二个想法是对这两种解决方案进行基准测试。然而,我不知道如何使用c++对它们计时。我发现了这个问题: How to Calculate Execution Time of a Code Snippet in C++ ,但我不知道如何正确处理编译器优化或处理器不一致。

    简而言之:上述问题中提供的代码是否足以用于日常测试?在运行测试之前,是否应该在编译器中启用一些选项?(我使用的是Visual C++)我应该做多少测试,以及两个基准测试之间的时间差有多重要?

    下面是我要测试的代码示例。以下哪一个更快?我自己怎么计算呢?

    unsigned long long fiborecursion(int rank){
        if (rank == 0) return 1;
        else if (rank < 0) return 0;
        return fiborecursion(rank-1) + fiborecursion(rank-2);
    }
    
    double sq5 = sqrt(5);
    unsigned long long fiboconstant(int rank){
        return pow((1 + sq5) / 2, rank + 1) / sq5 + 0.5;
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   user9478968 user9478968    7 年前

    使用来自的时钟 this answer

    #include <iostream>
    #include <chrono>
    
    class Timer
    {
    public:
        Timer() : beg_(clock_::now()) {}
        void reset() { beg_ = clock_::now(); }
        double elapsed() const { 
            return std::chrono::duration_cast<second_>
                (clock_::now() - beg_).count(); }
    
    private:
        typedef std::chrono::high_resolution_clock clock_;
        typedef std::chrono::duration<double, std::ratio<1> > second_;
        std::chrono::time_point<clock_> beg_;
    };
    

    您可以编写一个程序来计时这两个函数。

    int main() {
        const int N = 10000;
        Timer tmr;
    
        tmr.reset();
        for (int i = 0; i < N; i++) {
            auto value = fiborecursion(i%50);
        }
        double time1 = tmr.elapsed();
    
        tmr.reset();
        for (int i = 0; i < N; i++) {
            auto value = fiboconstant(i%50);
        }
        double time2 = tmr.elapsed();
    
        std::cout << "Recursion"
                << "\n\tTotal: " << time1
                << "\n\tAvg: " << time1 / N
                << "\n"
                << "\nConstant"
                << "\n\tTotal: " << time2
                << "\n\tAvg: " << time2 / N
                << "\n";
    }
    

    我会尝试在没有编译器优化的情况下编译( -O0 )和max编译器优化( -O3 )看看有什么不同。在最大优化时,编译器可能会完全消除循环。