Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 29.03.2019, 13:28   #1
Tpai
 
Регистрация: 09.06.2018
Сообщений: 9
Сообщение Время выполнения функций

Как узнать время выполнения написанной мной функции?
Tpai вне форума Ответить с цитированием
Старый 29.03.2019, 13:36   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Запустите всб вашу программу в реальном сценарии под профилировщиком и посмотреть. Это если вам реально надо, а если поиграться, то: сами замеряйте время до и после, используйте готовые бенчмарки и т.д.
p51x вне форума Ответить с цитированием
Старый 05.04.2019, 11:20   #3
clever411
Новичок
Джуниор
 
Регистрация: 05.04.2019
Сообщений: 2
По умолчанию Дарю!

Пользоваться следующим образом:
Делаете свои функции, чтобы они принимали лишь один аргумент (можете, в принципе, изменить)
Делаете экземпляр TestSystem, вызываете operator()(fun1, arg1, n) или operator()(fun1, arg1, fun2, arg2, n, nn) - первый метод возвращает double (одна миллисекунда), второй структуру Result, в которой:
* first - время выполнения в миллисекундах первой функции
* second - также, но для второй
* ratio = first/second
* n (аргумент operator()) - количество повторений выполнения функции в тесте(время иначе будет слишком маленьким)
* nn (аргумент второго operator()'а) - количество повторений тестов (результаты можно получить в открытом члене results).
Вроде всё написал... Если есть вопросы - задавайте. Там ещё внизу Stopwatch.hpp

Код:
#ifndef TEST_SYSTEM_HPP
#define TEST_SYSTEM_HPP

#include <chrono>
#include <vector>

#include "Stopwatch.hpp"





struct TestSystem
{
	// types
	struct Result
	{
		double first, second, ratio;

		template<class Ostream>
		Ostream &print( Ostream &os ) const
		{
			os << first << '/' << second << " = " << ratio;
			return os;
		}
	};
	
	
	
	
	
	// data-members
	std::vector<Result> results;
	
	
	
	
	
	// methods
	template<typename Functor, typename Argument>
	double operator()(Functor f, Argument arg, int n = 1000000) const
	{
		clever::Stopwatch<std::chrono::system_clock> watch;
		watch.start();
		for(int i = 0; i < n; ++i)
			f(arg);
		watch.stop();
		std::chrono::duration<double, std::ratio<1, 1000>> dur =
			watch.duration();
		return dur.count();
	}

	template<
		typename FunctorFirst, typename ArgumentFirst,
		typename FunctorSecond, typename ArgumentSecond
	>
	Result operator()(
		FunctorFirst first, ArgumentFirst farg,
		FunctorSecond second, ArgumentSecond sarg,
		int n = 100000, int nn = 1
	)
	{
		Result res;
		results.clear();
		results.reserve(nn);
		for(int i = 0; i < nn; ++i)
		{
			res.first = operator()(first, farg, n);
			res.second = operator()(second, sarg, n);
			res.ratio = res.first / res.second;
			results.push_back(res);
		}
		return res;
	}
	
	
	
	void write(FILE *file) const
	{
		for(int i = 0, e = results.size(); i < e; ++i)
		{
			fprintf(
				file, "%i %f %f %f\n",
				i, results[i].first,
				results[i].second,
				results[i].ratio
			);
		}
		return;
	}






};





#endif







#ifndef STOPWATCH_HPP
#define STOPWATCH_HPP





namespace clever
{



/*
 * Использование происходит так:
 * чтобы начать отсчет, необходимо вызвать функцию start.
 * чтобы получить промежуток времени, для начала необходимо 
 * вызвать функцию stop(), и только потом, можно будет вызывать
 * duration(). Либо можно, не вызывая stop, вызвать update, после
 * этого можно будет использовать duration, но если после stop
 * необходимо вызывать start, то после update — нет.
 */

template<typename Clock>
class Stopwatch
{
public:
	typedef Clock clock_type;
	typedef typename Clock::time_point time_point_type;
	typedef typename Clock::duration duration_type;

	Stopwatch &start()
	{
		starttime_ = clock_type::now();
		return *this;
	}
	Stopwatch &stop()
	{
		duration_ += clock_type::now()-starttime_;
		return *this;
	}
	Stopwatch &update()
	{
		time_point_type now = clock_type::now();
		duration_ += now - starttime_;
		starttime_ = now;
		return *this;
	}
	Stopwatch &reset()
	{
		duration_ = duration_type::zero();
		return *this;
	}

	duration_type const &duration() const
	{
		return duration_;
	}

private:
	time_point_type starttime_ = clock_type::now();
	duration_type duration_ = duration_type::zero();


};




}





#endif
clever411 вне форума Ответить с цитированием
Старый 29.06.2019, 20:08   #4
CppLinux345
Пользователь
 
Регистрация: 26.09.2018
Сообщений: 23
По умолчанию

В начале функции:
time_t start = clock();
В конце:
time_t end() = clock();
std::cout << (end - start) / CLOCKS_PER_SEC << std::endl;
CppLinux345 вне форума Ответить с цитированием
Старый 30.06.2019, 18:23   #5
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,536
По умолчанию

1. Засечь время старта.
2. Организовать цикл, в котором N раз выполнится заданная функция.
3. Засечь время финиша.
4. Вычесть и разделить.
Получим приблизительное время (не учтены накладные расходы на выполнение самого цикла) . Если нужно точнее, то отдельно измерить время выполнения пустого цикла (выключить оптимизацию, чтобы пустой цикл компилятор вообще не выбросил) .
А точное время и не нужно, потому что при работе в реальной среде будет еще расход времени на функции операционной системы.
digitalis вне форума Ответить с цитированием
Старый 02.07.2019, 13:09   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от digitalis Посмотреть сообщение
1. Засечь время старта.
2. Организовать цикл, в котором N раз выполнится заданная функция.
3. Засечь время финиша.
4. Вычесть и разделить.
Получим
искаженный результат.
смазанный эффектом прогретой памяти.

Цитата:
Сообщение от digitalis Посмотреть сообщение
Если нужно точнее, то отдельно измерить время выполнения пустого цикла (выключить оптимизацию, чтобы пустой цикл компилятор вообще не выбросил) .
что именно ты таким образом пытаешься измерить?
шум на микросхемах?

тестить дебаг - мсье знает толк в извращениях.
_Bers вне форума Ответить с цитированием
Старый 02.07.2019, 13:47   #7
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,536
По умолчанию

Кто из нас мсье - это еще вопрос. Измеряя время "цикл + выполняемая функция" минус "чисто цикл", определяем чистое время выполнения N раз функции. И я не утверждал, что получим точное значение - оно невозможно в принципе. И каким боком тут "шум на микросхемах" ? Я измеряю это на ламповой "Урал-4"
Непонятно, почему такой простой и логичный метод вызывает такое отторжение. В давние времена, когда я делал реалтаймовый измерительный комплекс на СМ-4, этим способом спокойно настроились все критичные времянки - я же тогда не знал, что "так нииизя!"
А насчет "прогретой памяти" - это для меня открытие. Случаем, не путаешь с прогревом шин в Формуле-1 ?
А вообще говорить о времени выполнения функции в многозадачной системе можно только очень приблизительно. Сильно зависит от того, в каком контексте работает функция. Да и если брать чистое время выполнения - без ОС, только она - результаты могут плавать +- лапоть в зависимости от аргументов. Возьмем, к примеру, сортировку пузырьком и подсунем ей массив отсортированный, а потом - "анти-отсортированный" - отличие будет не в десятках процентов, а в разы.
Так что можно лишь оценить - функция работает сотни микросекунд или десятки миллисекунд.

Последний раз редактировалось digitalis; 02.07.2019 в 14:04.
digitalis вне форума Ответить с цитированием
Старый 02.07.2019, 16:30   #8
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от digitalis Посмотреть сообщение
Случаем, не путаешь с прогревом шин в Формуле-1 ?
гуглить что-нибудь типа benchmarking warmup, microbenchmarking warmup
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 02.07.2019, 19:59   #9
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от digitalis Посмотреть сообщение
Непонятно, почему такой простой и логичный метод вызывает такое отторжение.
потому что в реальном мире все не так просто.

Цитата:
Сообщение от digitalis Посмотреть сообщение
А насчет "прогретой памяти" - это для меня открытие.
пример:
(оригинал гуглится: std::shared_ptr БЫСТРЕЕ обыкновенного указателя?)

http://ideone.com/7zvVjP

Код:
#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
 
 
struct Vec
{
    double x, y, z;
};
 
 
int main()
{
    Vec* vec = new Vec{ 0,0,0 };
    std::shared_ptr<Vec> shvec{ new Vec{0,0,0} };
 
    std::this_thread::sleep_for(std::chrono::milliseconds{1000});
 
    double work;
    const int count = 10000;
    std::chrono::high_resolution_clock::time_point time, lastTime;
 
    lastTime = std::chrono::high_resolution_clock::now();
    for( int i=0; i<count; ++i )
    {
        work = vec->y;
        vec->z = work;
    }
    time = std::chrono::high_resolution_clock::now();
    std::cout << "standard pointer: " << (time - lastTime).count() << std::endl;
 
    lastTime = std::chrono::high_resolution_clock::now();
    for( int i=0; i<count; ++i )
    {
        work = shvec->y;
        shvec->z = work;
    }
    time = std::chrono::high_resolution_clock::now();
    std::cout << "  shared pointer: " << (time - lastTime).count() << std::endl;
 
	return 0;
}
Код:
standard pointer: 920
shared pointer: 573
создается впечатление,
что тяжеловесный shared pointer работает быстрее,
чем легковесный standard pointer

поменяешь местами циклы,
и показания сразу меняются.

http://ideone.com/tzPZQR

Код:
shared pointer: 255
standard pointer: 38
это связанно с особенностями работы железа.
современные камни - сложные штуки.
кэши разных уровней,
механизм предсказаний,
и тп.

в народе говорят: "холодный старт память прогрел"


поэтому,
если ты хочешь замерить работу функции,
а не шум на микросхемах,
бенчмарк готовить нужно грамотно.

на самом деле годный бенчмарк - это целая наука.
но есть два фундаментальных правила:

1.
тестить нужно релиз со всеми оптимизациями.

2.
каждый тест - отдельный запуск отдельного приложения.
что бы минимизировать эффект гретой памяти.

Последний раз редактировалось _Bers; 02.07.2019 в 20:04.
_Bers вне форума Ответить с цитированием
Старый 02.07.2019, 21:59   #10
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,536
По умолчанию

Вот оно как... Значит, подзадержался я в прошлом тысячелетии. Век живи - век учись. Хорошо, что моя старушка СМ-4 в те времена не знала таких тонкостей, а то сказала бы: "Выключай кулеры, щас мегафлопсы выдавать буду".
Мир сложнее, оказывается, чем он есть на самом деле.

Последний раз редактировалось digitalis; 02.07.2019 в 22:06.
digitalis вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Время выполнения алгоритма imbaTapac Общие вопросы C/C++ 3 06.06.2015 20:08
Скрытие выполнения Api функций LomoCoder Общие вопросы Delphi 10 26.01.2014 03:30
выполнения функций JS slikNET JavaScript, Ajax 0 19.02.2013 12:00
Время выполнения n00n Общие вопросы C/C++ 7 10.06.2010 15:05
Время выполнения Goodwin98 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 16 21.06.2009 08:41