Saya ingin mengetahui berapa banyak waktu tertentu fungsi dalam C++ program untuk mengeksekusi pada Linux. Setelah itu, saya ingin membuat perbandingan kecepatan . Saya melihat beberapa fungsi waktu tapi berakhir dengan hal ini dari boost. Chrono:
process_user_cpu_clock, captures user-CPU time spent by the current process
Sekarang, saya tidak jelas jika saya menggunakan fungsi di atas, saya akan mendapatkan waktu CPU yang dihabiskan untuk itu fungsi?
Kedua, saya tidak bisa menemukan contoh penggunaan fungsi di atas. Ada yang bisa tolong bantu saya bagaimana untuk menggunakan fungsi di atas?
P. S: sekarang , saya menggunakan std::chrono::system_clock::sekarang()
untuk mendapatkan waktu dalam detik, tapi ini memberi saya hasil yang berbeda karena berbeda beban CPU setiap waktu.
Ini adalah sangat mudah-untuk-gunakan metode dalam C++11. Anda harus menggunakan std::chrono::high_resolution_clock
dari <chrono>
header.
Menggunakannya seperti:
#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;
}
Ini akan mengukur durasi fungsi.
CATATAN: Anda tidak akan selalu mendapatkan waktu yang sama untuk suatu fungsi. Hal ini karena CPU dari mesin anda bisa kurang atau lebih digunakan oleh proses-proses lain yang berjalan pada komputer anda, seperti pikiran anda dapat menjadi lebih atau kurang terkonsentrasi ketika anda memecahkan matematika latihan. Dalam pikiran manusia, kita dapat mengingat solusi dari masalah matematika, tetapi untuk komputer proses yang sama akan selalu menjadi sesuatu yang baru; dengan demikian, seperti yang saya katakan, anda tidak akan selalu mendapatkan hasil yang sama!
Berikut ini's fungsi yang akan mengukur waktu eksekusi dari setiap fungsi yang dilewatkan sebagai argumen:
#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);
}
Contoh penggunaan:
#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;
}
Output:
norm: 15555
algo: 2976
program sederhana untuk menemukan fungsi waktu eksekusi yang diambil.
#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;
}
Di Scott Meyers buku saya menemukan sebuah contoh dari universal generik lambda expression yang dapat digunakan untuk mengukur fungsi waktu eksekusi. (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;
};
Masalahnya adalah bahwa anda mengukur hanya satu eksekusi sehingga hasilnya bisa sangat berbeda. Untuk mendapatkan hasil yang dapat diandalkan, anda harus mengukur sejumlah besar eksekusi. Menurut Andrei Alexandrescu kuliah di code::dive 2015 conference - Menulis Cepat Kode saya:
Diukur waktu: tm = t + tq + tn + untuk
dimana:
tm - diukur (diamati) waktu
t - waktu yang sebenarnya dari bunga
tq - waktu ditambahkan oleh quantization noise
tn - waktu ditambahkan oleh berbagai sumber dari kebisingan
ke - overhead waktu (pengukuran, perulangan, memanggil fungsi)
Menurut apa katanya nanti di kuliah, anda harus mengambil minimal ini sejumlah besar eksekusi sebagai hasil anda. Saya mendorong anda untuk melihat kuliah di mana ia menjelaskan mengapa.
Juga ada perpustakaan yang baik dari google - https://github.com/google/benchmark. Perpustakaan ini sangat mudah digunakan dan kuat. Anda dapat checkout beberapa ceramah dari Chandler Carruth di youtube di mana ia menggunakan perpustakaan ini dalam praktek. Misalnya CppCon 2017: Chandler Carruth "ke mana-Mana lebih Cepat";
Contoh penggunaan:
#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;
}
EDIT: Ofcourse anda harus selalu ingat bahwa anda penyusun dapat mengoptimalkan sesuatu yang keluar atau tidak. Alat-alat seperti perf dapat berguna dalam kasus tersebut.
Cara mudah untuk yang lebih tua C++, atau 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;
}
Waktu presisi dalam detik adalah 1.0/CLOCKS_PER_SEC
- ini adalah sangat mudah untuk menggunakan metode dalam C++11.
- Kita dapat menggunakan std::chrono::high_resolution_clock dari
header - Kita dapat menulis sebuah metode untuk mencetak metode waktu eksekusi dalam banyak bentuk yang dapat dibaca.
Misalnya, untuk menemukan semua bilangan prima antara 1 dan 100 juta, dibutuhkan waktu sekitar 1 menit dan 40 detik. Jadi waktu eksekusi bisa dicetak sebagai:
Execution Time: 1 Minutes, 40 Seconds, 715 MicroSeconds, 715000 NanoSeconds
Kode berikut ini:
#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, ";
}
Berikut ini adalah header hanya kelas template untuk mengukur waktu yang telah berlalu dari suatu fungsi atau kode blok:
#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
Berikut ini adalah beberapa kegunaan dari itu:
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;
}
Sejak kelas adalah template yang dapat kita tentukan nyata mudah dalam cara kita ingin waktu kita untuk dapat diukur & ditampilkan. Ini adalah sebuah utilitas yang sangat berguna template class untuk melakukan bench marking dan sangat mudah digunakan.
Saya sarankan menggunakan steady_clock
yang guarunteed untuk menjadi monoton, tidak seperti 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
}
Output:
Hello World!
62
163514