【问题标题】:Testing Function for speed performance in CPPCPP中速度性能的测试功能
【发布时间】:2015-06-25 12:46:43
【问题描述】:

我创建了一个简单的函数来将任何小写字母 az 转换为大写,这个问题可能不是问题,但每个测试都返回 0。如果我添加 system("pause") 我可以看到一个新值,指示长度暂停。

是否有更准确的方法来测试速度,或者这实际上是否正确?我想将它与其他函数进行比较,看看它是否比标准函数转换得更快。

char* ToUppercase(char* Input)
{
    int Len = Length(Input);
    for (int i = 0; i < Len; i++)
    {
        short keycode = static_cast<short>(Input[i]);
        if (keycode >= 97 && keycode <= 122)
            Input[i] -= 32;
    }
    return Input;
}

我用来测试的当前计时器是(由其他人创建的)

template<typename TimeT = std::chrono::milliseconds>
struct measure
{
    template<typename F, typename ...Args>
    static typename TimeT::rep execution(F func, Args&&... args)
    {
        auto start = std::chrono::system_clock::now();
        func(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast< TimeT>
            (std::chrono::system_clock::now() - start);
        return duration.count();
    }
};

打电话给我:

void Debug()
{
    char Buffer[10000] = "aaaa /..../ aaaa";
    MyStringControl::ToUppercase(Buffer);
}
int main()
{
    std::cout << measure<std::chrono::nanoseconds>::execution(Debug);
}

【问题讨论】:

  • 你看std::chrono::high_resolution_clock了吗?
  • 我有,但它仍然返回 0。我开始怀疑速度是否太快(四核 i7 cpu),所以我使用了这个:start high_res_clock for(int i = 0; i
  • 我下面的代码是否在您的系统上给出了 0?我也在使用快速核心 i7 (3.5 GHz) - 仍然不应该是 0。:) (我只是编辑了发布时间而不是调试,我的仍然非零。)
  • 我注意到评论“ 修复:时钟被重写以保持一致和精确。”这里:blogs.msdn.com/b/vcblog/archive/2014/06/03/…
  • 当它给你暂停的长度时,它是否以纳秒为单位给你?我还在想一辆越野车duration_cast

标签: c++ c++11 performance-testing


【解决方案1】:

你看过std::chrono::high_resolution_clock吗?

这是一个例子:

#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>

template<typename TimeT = std::chrono::milliseconds>
struct measure
{
    template<typename F, typename ...Args>
    static typename TimeT::rep execution(F func, Args&&... args)
    {
        auto start = std::chrono::high_resolution_clock::now();
        func(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast< TimeT>
                (std::chrono::high_resolution_clock::now() - start);
        return duration.count();
    }
};

int total = 0;

void test()
{
    int foo = 0;
    for (int i=0; i<1000; ++i) ++foo;
    total += foo;
}

int main ()
{
    using namespace std::chrono;

    for (int i = 0; i < 30; ++i)
    {
        total = 0;
        auto t = measure<std::chrono::nanoseconds>::execution(test);
        std::cout << "Calculated total = " << total << " in " << t << " ns." << std::endl;
    }    
    return 0;
}

这给出了:

Calculated total = 1000 in 64 ns.
Calculated total = 1000 in 21 ns.
Calculated total = 1000 in 22 ns.
Calculated total = 1000 in 21 ns.
Calculated total = 1000 in 14 ns.
Calculated total = 1000 in 15 ns.
Calculated total = 1000 in 13 ns.
Calculated total = 1000 in 14 ns.
Calculated total = 1000 in 13 ns.
Calculated total = 1000 in 14 ns.
Calculated total = 1000 in 13 ns.
Calculated total = 1000 in 21 ns.
Calculated total = 1000 in 14 ns.
Calculated total = 1000 in 15 ns.
Calculated total = 1000 in 14 ns.
Calculated total = 1000 in 15 ns.
Calculated total = 1000 in 22 ns.
Calculated total = 1000 in 21 ns.
Calculated total = 1000 in 20 ns.
Calculated total = 1000 in 14 ns.
Calculated total = 1000 in 14 ns.
Calculated total = 1000 in 14 ns.
Calculated total = 1000 in 20 ns.
Calculated total = 1000 in 20 ns.
Calculated total = 1000 in 21 ns.
Calculated total = 1000 in 20 ns.
Calculated total = 1000 in 15 ns.
Calculated total = 1000 in 15 ns.
Calculated total = 1000 in 15 ns.
Calculated total = 1000 in 14 ns.

【讨论】:

  • 这个写成的代码输出计算的总数 = 1000 in 0 ns。在每个循环调用上。我在发布模式下使用 vs2013 社区。​​span>
  • 看起来你的代码是正确的,而 VS 在某种程度上被破坏了。我目前没有 Windows 开发机器,所以无法测试。
  • 你能看到如果你删除duration_cast会发生什么吗?我看到有人提到这在 VS 中有错误,但我认为我看到的示例会导致编译问题。
【解决方案2】:

函数运行 1000000 次,结果除以 1000000。你可以使用高精度定时器,但由于硬件的古怪,它更容易出现不准确的情况。

编辑:

您希望对函数本身进行 1000,000 次调用,并且只对计时器进行一次调用:

    auto start = std::chrono::system_clock::now();
    for (size_t counter = 0; counter<1000000; ++counter)
         func(std::forward<Args>(args)...);
    auto duration = std::chrono::duration_cast< TimeT>
        (std::chrono::system_clock::now() - start)/1000000;
    return duration.count();

【讨论】:

  • 这样做会输出一个 500,000 次迭代的数字,我收到了 14 个 high_res
  • 我已将这个想法添加到答案中,因为您无法在 cmets 中进行任何格式化。
  • 同意这是一个好主意,如果您正在寻找平均时间。但是 Intel CPU 上的高分辨率计时器应该能够提供 ns 分辨率,并且有问题的函数不应该为 0。
  • 您对硬件要求的时间分辨率越高,它就越不准确。
【解决方案3】:

您的函数 Debug 什么都不做,您的编译器可能会弄清楚这一点,因此您要做的就是计时您可以连续两次调用 now 的速度。

采取措施确保您尝试计时的代码不会被优化掉。例如以某种方式使用它的输出,或者给它__attribute__((noinline))(如果你也不介意计算实际函数调用的成本)或其他东西。

(此外,如果您希望从计时中获得任何有用的精度,则您的功能需要比时钟分辨率长得多)

【讨论】:

  • 他还尝试了我的示例并获得了 0 次计时,所以这不是问题,尽管我确实在其他天真的示例中看到过这种情况。产生可衡量的副作用总是一个好主意。
  • @sfjac:你的函数也不做任何事情。
  • 它设置了一个全局变量,然后打印出来——编译器无法优化它......好吧,一个非常聪明的编译器可以设置total = 1000并摆脱函数调用,但是每次通话都必须这样做。我没见过这么聪明的。但它肯定会优化函数中的循环。
  • 他当然可以检查装配以确保安全。不过,我的猜测是,这是在调试模式下发生的。我怀疑是 VS 错误。
  • 我没有在调试中运行,我认为这是一个问题并更改为发布,但仍然有问题我会玩一会儿,并完成阅读其余部分
猜你喜欢
  • 1970-01-01
  • 2010-10-03
  • 2018-11-19
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
相关资源
最近更新 更多