2015-04-18 3 views
2

Я создал простую функцию для преобразования любой строчной буквы az в верхний регистр, проблема может не быть проблемой, но каждый тест возвращает 0. Если я добавлю систему («пауза»), я могу видеть новое значение, указывающее продолжительность паузы.Тестирование Функция для скорости в CPP

Есть ли более точный способ проверить скорость, или это действительно правильно? Я хотел бы сравнить его с другими функциями, чтобы узнать, преобразует ли он быстрее, чем стандартные функции.

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); 
} 
+1

Вы смотрели на 'станд :: хроно :: high_resolution_clock'? – sfjac

+0

У меня есть и все еще вернулось 0. Я начал задаваться вопросом, может ли скорость быть быстрой (четырехъядерный процессор i7 cpu), и поэтому я использовал это: start high_res_clock для (int i = 0; i <1000; i ++) MyStringControl :: ToUppercase (буфер); cout << end high_res_clock Выполнение этого Я получил результат 17008 – TheStart101

+0

Имеет ли мой код ниже 0 в вашей системе? Я тоже на быстром ядре i7 (3,5 ГГц) - все равно не должен быть 0. :) (Я только что отредактировал, чтобы иметь время выпуска вместо Debug, а у меня все еще нет нуля.) – sfjac

ответ

2

Запуск функции 1000000 раз и разделить результат на 1000000. Вы можете использовать таймер высокой точности, но он будет более склонным к неточностям из-за аппаратной причудливости.

Edit:

Вы хотите 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(); 
+0

Выполнение этого способа выводит число с 500 000 итераций, которые я получил 14 с high_res – TheStart101

+0

Я добавил эту идею в ответ, потому что вы не можете форматировать комментарии. –

+0

Согласитесь, что это хорошая идея, если вы ищете среднее время. Но высокочастотные таймеры на процессорах Intel должны иметь возможность давать ns-разрешение, а функция, о которой идет речь, не должна быть равна 0. – sfjac

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. 
+0

Этот код, записанный как выходы Рассчитанный итог = 1000 в 0 нс. на каждый вызов цикла. Я использую сообщество vs2013 в режиме выпуска. – TheStart101

+0

Похоже, ваш код прав, и VS каким-то образом сломался. В настоящее время у меня нет Windows-dev-машины, поэтому я не могу проверить. – sfjac

+0

Вы видите, что произойдет, если вы удалите 'duration_cast'? Я видел некоторые упоминания о том, что это багги в VS, хотя примеры, которые я видел, вызовут проблемы с компиляцией, я думаю. – sfjac

0

Ваша функция Debug ничего не делает, и ваш компилятор может быть в состоянии понять, что из, и, следовательно, все, что вы делаете как быстро вы можете позвонить now дважды подряд.

Сделайте что-нибудь, чтобы убедиться, что код, который вы пытаетесь сделать, не оптимизирован. например используйте его выход каким-то образом или дайте ему __attribute__((noinline)) (если вы не возражаете, чтобы время было связано с фактическим вызовом функции) или что-то в этом роде.

(также, вам нужно ваша функция взять существенно больше, чем разрешение на ваши часы, если вы хотите какое-либо полезное количество точности от ваших таймингов)

+0

Он также попробовал мой пример и получил 0 таймингов, так что это не проблема, хотя я определенно видел, как это происходит в других наивных примерах. Всегда хорошая идея иметь измеримый побочный эффект. – sfjac

+0

@sfjac: Ваша функция ничего не делает. – Hurkyl

+0

Он устанавливает глобальную переменную, которая затем печатается - компилятор не может ее оптимизировать ... Ну, действительно умный компилятор может просто установить 'total = 1000' и ​​избавиться от вызова функции, но это должно было бы сделать это для каждого звонка. Я не видел такого умного. Но это определенно может оптимизировать цикл в функции. – sfjac

Смежные вопросы