Страницы

Поиск по вопросам

четверг, 19 декабря 2019 г.

Как измерить скорость работы программы?

#cpp #алгоритм #производительность


Подскажите, пожалуйста, как можно точно проверить скорость выполнения какой-то части
кода и всей программы на С++.
    


Ответы

Ответ 1



В общем, вам нужен профайлер, который покажет сколько какой участок кода работал, сколько раз вызывался и т.п. Если профайлер по каким-то причинам не пригоден - можно использовать получение времени в начале и конце участка кода, но время исполнения участка кода должно быть много больше кванта времени. Конкретные способы: time() - кроссплатформенно, квант 1 с. GetTickCount() - Win, квант 1 мс. QueryPerformanceCounter() - Win, кванты мелкие. rdtsc - любая ос на x86/x64, считает такты процессора

Ответ 2



std::chrono Для измерения интервалов времени в С++ есть std::chrono::steady_clock и high_resolution_clock: #include #include int main() { auto start_time = std::chrono::steady_clock::now(); delete new int(1); auto end_time = std::chrono::steady_clock::now(); auto elapsed_ns = std::chrono::duration_cast(end_time - start_time); std::cout << elapsed_ns.count() << " ns\n"; } Точность зависит от ОС, high_resolution_clock может быть точнее чем steady_clock, однако они могут быть не монотонными (на них может влиять синхронизация времени ОС). Инструкция rdtsc Для очень маленьких интервалов времени можно использовать инструкцию процессора rdtsc (ReaD TicS Counter), которая возвращает количество тактов процессора. В VC++ для этого есть интринсик __rdtsc(), в G++ надо использовать встроенный ассемблер. Однако для правильных измерений с помощью rdtsc надо соблюсти несколько условий: перед rdtsc надо выполнить инструкцию cpuid, чтобы очистить конвейер процессора надо отключить Hyper-Threading, если он включен надо исключить влияние переключения контекстов потока - измерение должно быть коротким (менее 20 мс на Windows), надо принудительно переключить контекст потока перед началом измерений (SwitchToThread в Windows), желательно привязать поток к одному ядру процессора (у каждого ядра свой счетчик тактов). не надо пытаться переводить такты во время, т.к. частота процессора может меняться. из результата надо вычесть время работы инструкций cpuid и rdtsc (~100 тактов). Примерный код выглядит следующим образом (Windows, MS VC++): #include #include #include #include template long long measure(F&& f) { const auto N = 10; long long results[N]; for (auto& r : results) { std::this_thread::yield(); __asm xor eax, eax __asm cpuid // есть интринсик, но мы хотим проигнорировать результат cpuid auto start_time = __rdtsc(); f(); __asm xor eax, eax __asm cpuid r = __rdtsc() - start_time; } auto median = results + N / 2; std::nth_element(results, median, results + N); return *median; } int main() { auto overhead = measure([]{}); auto ticks = measure([]{ delete new int(1); }); std::cout << ticks - overhead << " ticks\n"; }

Ответ 3



вот код замера времени для консольных приложений #include using namespace std; inline _int64 HightTime(){ _asm{ rdtsc } } _int64 pft_start; _int64 pft_finish; #define SPEED_START_CONSOLE pft_start = HightTime(); #define SPEED_FINISH_CONSOLE pft_finish = HightTime(); cout << pft_finish - pft_start << endl; int main(){ SPEED_START_CONSOLE // точка времени старта замера скорости for (int i = 0; i < 200; i++); // запускаем цикл для примера SPEED_FINISH_CONSOLE // конец измерения, выводит потрченное процессорное время (в тактах) return 0; }

Комментариев нет:

Отправить комментарий