C ++에서 함수의 실행 시간 측정
특정 함수가 내 C ++ 프로그램에서 Linux 에서 실행되는 데 걸리는 시간을 알고 싶습니다 . 그 후에 속도 비교를하고 싶습니다. 나는 여러 시간 기능을 보았지만 부스트로 인해 끝났습니다. 크로노 :
process_user_cpu_clock, captures user-CPU time spent by the current process
이제 위의 기능을 사용하는지 확실하지 않습니다. CPU가 해당 기능에 소비 한 유일한 시간을 얻을 수 있습니까?
둘째, 위의 기능을 사용하는 예를 찾을 수 없습니다. 위의 기능을 사용하는 방법을 도와 주시겠습니까?
추신 : 지금 std::chrono::system_clock::now()
은 초 단위로 시간을 얻는 데 사용 하고 있지만 매번 다른 CPU 부하로 인해 다른 결과를 제공합니다.
C ++ 11에서 매우 사용하기 쉬운 방법입니다. 당신은 사용해야 std::chrono::high_resolution_clock
에서 <chrono>
헤더입니다.
다음과 같이 사용하십시오.
#include <iostream>
#include <chrono>
void function()
{
long long number = 0;
for( long long i = 0; i != 2000000; ++i )
{
number += 5;
}
}
int main()
{
auto t1 = std::chrono::high_resolution_clock::now();
function();
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
std::cout << duration;
return 0;
}
이것은 함수의 지속 시간을 측정합니다.
참고 : 함수에 대해 항상 동일한 타이밍을 얻을 수있는 것은 아닙니다. 이것은 컴퓨터에서 실행되는 다른 프로세스에서 컴퓨터의 CPU를 덜 사용하거나 더 많이 사용할 수 있기 때문입니다. 수학 연습을 풀 때 정신이 다소 집중 될 수 있기 때문입니다. 인간의 마음 속에서 우리는 수학 문제의 해답을 기억할 수 있지만 컴퓨터의 경우 동일한 과정이 항상 새로운 것이 될 것입니다. 따라서 내가 말했듯이 항상 동일한 결과를 얻는 것은 아닙니다!
다음은 인수로 전달 된 함수의 실행 시간을 측정하는 함수입니다.
#include <chrono>
#include <utility>
typedef std::chrono::high_resolution_clock::time_point TimeVar;
#define duration(a) std::chrono::duration_cast<std::chrono::nanoseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()
template<typename F, typename... Args>
double funcTime(F func, Args&&... args){
TimeVar t1=timeNow();
func(std::forward<Args>(args)...);
return duration(timeNow()-t1);
}
사용법 예 :
#include <iostream>
#include <algorithm>
typedef std::string String;
//first test function doing something
int countCharInString(String s, char delim){
int count=0;
String::size_type pos = s.find_first_of(delim);
while ((pos = s.find_first_of(delim, pos)) != String::npos){
count++;pos++;
}
return count;
}
//second test function doing the same thing in different way
int countWithAlgorithm(String s, char delim){
return std::count(s.begin(),s.end(),delim);
}
int main(){
std::cout<<"norm: "<<funcTime(countCharInString,"precision=10",'=')<<"\n";
std::cout<<"algo: "<<funcTime(countWithAlgorithm,"precision=10",'=');
return 0;
}
산출:
norm: 15555
algo: 2976
걸린 함수 실행 시간을 찾는 간단한 프로그램.
#include <iostream>
#include <ctime> // time_t
#include <cstdio>
void function()
{
for(long int i=0;i<1000000000;i++)
{
// do nothing
}
}
int main()
{
time_t begin,end; // time_t is a datatype to store time values.
time (&begin); // note time before execution
function();
time (&end); // note time after execution
double difference = difftime (end,begin);
printf ("time taken for function() %.2lf seconds.\n", difference );
return 0;
}
Scott Meyers의 책에서 함수 실행 시간을 측정하는 데 사용할 수있는 범용 일반 람다 식의 예를 찾았습니다. (C ++ 14)
auto timeFuncInvocation =
[](auto&& func, auto&&... params) {
// get time before function invocation
const auto& start = high_resolution_clock::now();
// function invocation using perfect forwarding
std::forward<decltype(func)>(func)(std::forward<decltype(params)>(params)...);
// get time after function invocation
const auto& stop = high_resolution_clock::now();
return stop - start;
};
문제는 하나의 실행 만 측정하므로 결과가 매우 다를 수 있다는 것입니다. 신뢰할 수있는 결과를 얻으려면 많은 수의 실행을 측정해야합니다. code :: dive 2015 컨퍼런스에서 Andrei Alexandrescu 강의에 따르면-Writing Fast Code I :
측정 시간 : tm = t + tq + tn + to
어디:
tm-측정 된 (관찰 된) 시간
t-실제 관심 시간
tq-양자화 잡음에 의해 추가 된 시간
tn-다양한 소음원에 의해 추가 된 시간
to-오버 헤드 시간 (측정, 루핑, 함수 호출)
강의 후반부에 그가 한 말에 따르면, 당신은 결과로이 많은 수의 실행을 최소한으로해야합니다. 그가 그 이유를 설명하는 강의를 보시길 바랍니다.
또한 google- https ://github.com/google/benchmark의 아주 좋은 라이브러리가 있습니다 . 이 라이브러리는 사용이 매우 간단하고 강력합니다. Chandler Carruth가 실제로이 라이브러리를 사용하는 YouTube에서 강의를 확인할 수 있습니다. 예를 들어 CppCon 2017 : Chandler Carruth "Going Nowhere Faster";
사용법 예 :
#include <iostream>
#include <chrono>
#include <vector>
auto timeFuncInvocation =
[](auto&& func, auto&&... params) {
// get time before function invocation
const auto& start = high_resolution_clock::now();
// function invocation using perfect forwarding
for(auto i = 0; i < 100000/*largeNumber*/; ++i) {
std::forward<decltype(func)>(func)(std::forward<decltype(params)>(params)...);
}
// get time after function invocation
const auto& stop = high_resolution_clock::now();
return (stop - start)/100000/*largeNumber*/;
};
void f(std::vector<int>& vec) {
vec.push_back(1);
}
void f2(std::vector<int>& vec) {
vec.emplace_back(1);
}
int main()
{
std::vector<int> vec;
std::vector<int> vec2;
std::cout << timeFuncInvocation(f, vec).count() << std::endl;
std::cout << timeFuncInvocation(f2, vec2).count() << std::endl;
std::vector<int> vec3;
vec3.reserve(100000);
std::vector<int> vec4;
vec4.reserve(100000);
std::cout << timeFuncInvocation(f, vec3).count() << std::endl;
std::cout << timeFuncInvocation(f2, vec4).count() << std::endl;
return 0;
}
편집 : 당연히 컴파일러가 무언가를 최적화 할 수 있는지 여부를 항상 기억해야합니다. perf와 같은 도구는 이러한 경우에 유용 할 수 있습니다.
이전 C ++ 또는 C를위한 쉬운 방법 :
#include <time.h> // includes clock_t and CLOCKS_PER_SEC
int main() {
clock_t start, end;
start = clock();
// ...code to measure...
end = clock();
double duration_sec = double(end-start)/CLOCKS_PER_SEC;
return 0;
}
초 단위의 타이밍 정밀도는 1.0/CLOCKS_PER_SEC
- C ++ 11에서 사용하기 매우 쉬운 방법입니다.
- 헤더에서 std :: chrono :: high_resolution_clock을 사용할 수 있습니다.
- 메서드 실행 시간을 읽기 쉬운 형식으로 인쇄하는 메서드를 작성할 수 있습니다.
예를 들어 1에서 1 억 사이의 모든 소수를 찾으려면 약 1 분 40 초가 걸립니다. 따라서 실행 시간은 다음과 같이 인쇄됩니다.
Execution Time: 1 Minutes, 40 Seconds, 715 MicroSeconds, 715000 NanoSeconds
코드는 다음과 같습니다.
#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;
typedef high_resolution_clock Clock;
typedef Clock::time_point ClockTime;
void findPrime(long n, string file);
void printExecutionTime(ClockTime start_time, ClockTime end_time);
int main()
{
long n = long(1E+8); // N = 100 million
ClockTime start_time = Clock::now();
// Write all the prime numbers from 1 to N to the file "prime.txt"
findPrime(n, "C:\\prime.txt");
ClockTime end_time = Clock::now();
printExecutionTime(start_time, end_time);
}
void printExecutionTime(ClockTime start_time, ClockTime end_time)
{
auto execution_time_ns = duration_cast<nanoseconds>(end_time - start_time).count();
auto execution_time_ms = duration_cast<microseconds>(end_time - start_time).count();
auto execution_time_sec = duration_cast<seconds>(end_time - start_time).count();
auto execution_time_min = duration_cast<minutes>(end_time - start_time).count();
auto execution_time_hour = duration_cast<hours>(end_time - start_time).count();
cout << "\nExecution Time: ";
if(execution_time_hour > 0)
cout << "" << execution_time_hour << " Hours, ";
if(execution_time_min > 0)
cout << "" << execution_time_min % 60 << " Minutes, ";
if(execution_time_sec > 0)
cout << "" << execution_time_sec % 60 << " Seconds, ";
if(execution_time_ms > 0)
cout << "" << execution_time_ms % long(1E+3) << " MicroSeconds, ";
if(execution_time_ns > 0)
cout << "" << execution_time_ns % long(1E+6) << " NanoSeconds, ";
}
다음은 함수 또는 코드 블록의 경과 시간을 측정하는 우수한 헤더 전용 클래스 템플릿입니다.
#ifndef EXECUTION_TIMER_H
#define EXECUTION_TIMER_H
template<class Resolution = std::chrono::milliseconds>
class ExecutionTimer {
public:
using Clock = std::conditional_t<std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock,
std::chrono::steady_clock>;
private:
const Clock::time_point mStart = Clock::now();
public:
ExecutionTimer() = default;
~ExecutionTimer() {
const auto end = Clock::now();
std::ostringstream strStream;
strStream << "Destructor Elapsed: "
<< std::chrono::duration_cast<Resolution>( end - mStart ).count()
<< std::endl;
std::cout << strStream.str() << std::endl;
}
inline void stop() {
const auto end = Clock::now();
std::ostringstream strStream;
strStream << "Stop Elapsed: "
<< std::chrono::duration_cast<Resolution>(end - mStart).count()
<< std::endl;
std::cout << strStream.str() << std::endl;
}
}; // ExecutionTimer
#endif // EXECUTION_TIMER_H
다음은 몇 가지 용도입니다.
int main() {
{ // empty scope to display ExecutionTimer's destructor's message
// displayed in milliseconds
ExecutionTimer<std::chrono::milliseconds> timer;
// function or code block here
timer.stop();
}
{ // same as above
ExecutionTimer<std::chrono::microseconds> timer;
// code block here...
timer.stop();
}
{ // same as above
ExecutionTimer<std::chrono::nanoseconds> timer;
// code block here...
timer.stop();
}
{ // same as above
ExecutionTimer<std::chrono::seconds> timer;
// code block here...
timer.stop();
}
return 0;
}
클래스는 템플릿이기 때문에 우리가 원하는 시간을 측정하고 표시하는 방법을 쉽게 지정할 수 있습니다. 이것은 벤치 마킹을 수행하기위한 매우 편리한 유틸리티 클래스 템플릿이며 사용하기 매우 쉽습니다.
steady_clock
.NET과는 달리 단조 롭다고 보장되는 사용 을 권장 high_resolution_clock
합니다.
#include <iostream>
#include <chrono>
using namespace std;
unsigned int stopwatch()
{
static auto start_time = chrono::steady_clock::now();
auto end_time = chrono::steady_clock::now();
auto delta = chrono::duration_cast<chrono::microseconds>(end_time - start_time);
start_time = end_time;
return delta.count();
}
int main() {
stopwatch(); //Start stopwatch
std::cout << "Hello World!\n";
cout << stopwatch() << endl; //Time to execute last line
for (int i=0; i<1000000; i++)
string s = "ASDFAD";
cout << stopwatch() << endl; //Time to execute for loop
}
산출:
Hello World!
62
163514
참고 URL : https://stackoverflow.com/questions/22387586/measuring-execution-time-of-a-function-in-c
'Programing' 카테고리의 다른 글
파일을 찾아 tar (공백 포함) (0) | 2020.08.07 |
---|---|
ASP.NET MVC가 빈보기를 반환합니다. (0) | 2020.08.07 |
cout은 동기화 / 스레드 안전합니까? (0) | 2020.08.06 |
멀티 프로세싱의 공유 메모리 개체 (0) | 2020.08.06 |
멀티 모듈 메이븐 프로젝트에서 모듈 간 src / test 클래스 공유 (0) | 2020.08.06 |