การวัดเวลาดำเนินการของฟังก์ชันใน C ++


138

ฉันต้องการที่จะหาวิธีการมากเวลาฟังก์ชั่นบางอย่างต้องใช้เวลาในการฉัน C ++ โปรแกรมที่จะรันบนลินุกซ์ หลังจากนั้นฉันต้องการเปรียบเทียบความเร็ว ฉันเห็นฟังก์ชั่นหลายครั้ง แต่จบลงด้วยสิ่งนี้จากการเพิ่ม Chrono:

process_user_cpu_clock, captures user-CPU time spent by the current process

ตอนนี้ฉันยังไม่ชัดเจนถ้าฉันใช้ฟังก์ชั่นด้านบนฉันจะได้รับเฉพาะซีพียูที่ใช้ในฟังก์ชั่นนั้นหรือไม่

ประการที่สองฉันไม่พบตัวอย่างการใช้ฟังก์ชั่นด้านบน คนใดคนหนึ่งโปรดช่วยฉันวิธีการใช้ฟังก์ชั่นดังกล่าวข้างต้น?

PS: ตอนนี้ฉันใช้std::chrono::system_clock::now()เพื่อรับเวลาในไม่กี่วินาที แต่สิ่งนี้ทำให้ฉันผลลัพธ์ที่แตกต่างเนื่องจากการโหลด CPU ที่แตกต่างกันทุกครั้ง


2
สำหรับการใช้งานลินุกซ์: clock_gettime.. GCC กำหนดนาฬิกาอื่น ๆ เช่น: typedef system_clock steady_clock; typedef system_clock high_resolution_clock;บน Windows, QueryPerformanceCounterการใช้งาน
แบรนดอน

คำถามนี้ไม่ใช่คำถามที่ซ้ำกันของภาพจำลองนี้หรือสถานการณ์จำลองทำให้การแก้ปัญหาแตกต่างกันหรือไม่
เหนือ

ฉันมีการใช้งานสองฟังก์ชั่นและต้องการที่จะหาที่มีประสิทธิภาพดีกว่า
เหนือ

ที่สำคัญมาก: ให้แน่ใจว่าคุณเปิดใช้งานการเพิ่มประสิทธิภาพ รหัสที่ไม่ได้รับการปรับปรุงให้ดีที่สุดมีคอขวดที่แตกต่างจากรหัสที่ได้รับการปรับให้เหมาะสมตามปกติและจะไม่บอกสิ่งใดที่มีความหมาย C เพิ่มประสิทธิภาพห่วงความช่วยเหลือสำหรับการกำหนดขั้นสุดท้าย (กับการเพิ่มประสิทธิภาพของคอมไพเลอร์ปิดการใช้งาน) และใน microbenchmarking ทั่วไปมีข้อผิดพลาดมากมายโดยเฉพาะอย่างยิ่งความล้มเหลวในการวนลูปอุ่นเครื่องก่อนสำหรับ CPU-frequency และ page faults: วิธีการประเมินประสิทธิภาพที่เป็นเอกลักษณ์? . และคำตอบนี้
Peter Cordes

ดูเพิ่มเติมคุณจะวัดประสิทธิภาพของฟังก์ชันได้อย่างไร สำหรับ Google Benchmark ที่หลีกเลี่ยงข้อผิดพลาดมากมายในการกลิ้ง microbenchmark ของคุณเอง นอกจากนี้ยังง่ายสำหรับ () มาตรฐานวงใช้เวลาในเวลาเดียวกันกับวงใด ๆ ที่ถูกผูกไว้สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการเพิ่มประสิทธิภาพการปฏิสัมพันธ์กับลูปมาตรฐานและสิ่งที่จะทำอย่างไรกับมัน
Peter Cordes

คำตอบ:


264

มันเป็นวิธีที่ใช้งานง่ายมากใน 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 ของเครื่องของคุณสามารถใช้งานได้น้อยลงหรือมากขึ้นโดยกระบวนการอื่น ๆ ที่ทำงานบนคอมพิวเตอร์ของคุณเช่นเดียวกับที่ใจของคุณจะเข้มข้นมากขึ้นหรือน้อยลงเมื่อคุณแก้โจทย์คณิตศาสตร์ ในใจมนุษย์เราสามารถจำวิธีแก้ปัญหาคณิตศาสตร์ได้ แต่สำหรับคอมพิวเตอร์กระบวนการเดียวกันจะเป็นสิ่งใหม่เสมอ ดังนั้นอย่างที่ฉันพูดคุณจะไม่ได้ผลลัพธ์เดียวกันเสมอไป!


เมื่อฉันใช้ฟังก์ชั่นนี้ในการเรียกใช้ครั้งแรกมันให้ฉัน 118440535 ไมโครวินาทีและในการทำงานครั้งที่สองของฟังก์ชั่นเดียวกันมันให้ฉัน 83221031 ไมโครวินาที การวัดสองครั้งไม่ควรเท่ากันเมื่อฉันวัดระยะเวลาของฟังก์ชันนั้นเท่านั้นหรือ
Xara

1
ไม่ตัวประมวลผลของคอมพิวเตอร์ของคุณสามารถใช้งานได้น้อยลง high_resolution_clockจะให้เวลาทางกายภาพและจริงที่ทำงานของคุณใช้เวลาในการทำงาน ดังนั้นในการใช้งานครั้งแรก CPU ของคุณจึงถูกใช้งานน้อยกว่าการใช้งานครั้งต่อไป โดย "ใช้" ฉันหมายถึงแอปพลิเคชันอื่นที่ใช้งาน CPU
Victor

1
ใช่ถ้าคุณต้องการเวลาโดยเฉลี่ยนั่นเป็นวิธีที่ดีที่จะได้มา ใช้เวลาสามวิ่งและคำนวณค่าเฉลี่ย
Victor

3
คุณช่วยกรุณาโพสต์รหัสโดยไม่ต้อง "ใช้ namespace" โดยทั่วไป ทำให้ง่ายต่อการดูว่าอะไรมาจากที่ไหน
Snowman

1
ไม่ควรที่นี้จะเป็นsteady_clock? เป็นไปได้หรือไม่ว่าhigh_resolution_clockอาจเป็นนาฬิกาที่ไม่ใช่ระบบโมโนโทนิก
Gillespie

15

นี่คือฟังก์ชันที่จะวัดเวลาดำเนินการของฟังก์ชันใด ๆ ที่ส่งผ่านเป็นอาร์กิวเมนต์:

#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

2
@ RestlessC0bra: เป็นการนำมาใช้งานที่กำหนดไว้high_resolution_clockอาจเป็นนามแฝงของsystem_clock(นาฬิกาแขวนผนัง) steady_clockหรือนาฬิกาอิสระที่สาม ดูรายละเอียดที่นี่ สำหรับนาฬิกา cpu std::clockสามารถใช้ได้
Jahid

2
มาโครสองตัวและโกลบอล typedef - ไม่มีสิ่งใดที่ปลอดภัยในการกดแป้นเดียว - แน่นอนว่าไม่มีอะไรที่ฉันจะเรียกว่าสง่างามนอกจากนี้ยังผ่านวัตถุฟังก์ชั่นและส่งต่อข้อโต้แย้งอย่างสมบูรณ์แบบแยกเป็นบิตของ overkill (และในกรณี ไม่สะดวก) เมื่อคุณต้องการเพียงแค่กำหนดรหัสเวลาในแลมบ์ดา แต่ก็ตราบใดที่การส่งผ่านอาร์กิวเมนต์เป็นทางเลือก
MikeMB

2
และนี่เป็นข้ออ้างสำหรับการละเมิดหลักเกณฑ์ทุกข้อเกี่ยวกับการตั้งชื่อมาโครหรือไม่ คุณไม่ได้ใส่คำนำหน้าพวกเขาไม่ใช้ตัวพิมพ์ใหญ่คุณเลือกชื่อที่มีความเป็นไปได้สูงในการชนกับสัญลักษณ์ท้องถิ่นและส่วนใหญ่: ทำไมคุณถึงใช้แมโครเลย (แทนที่จะเป็นฟังก์ชั่น )? และในขณะที่เราอยู่ที่: ทำไมคุณกลับมาเป็นระยะเวลาสองเท่าเป็นตัวแทนของนาโนวินาทีในตอนแรก? เราควรเห็นด้วยว่าเราไม่เห็นด้วย ความคิดเห็นดั้งเดิมของฉันย่อมาจาก: "นี่ไม่ใช่สิ่งที่ฉันเรียกว่ารหัสที่หรูหรา"
MikeMB

1
ปัญหาคือพวกเขาไม่ถูก จำกัด ขอบเขตสิ่งที่ฉันกังวลคือมาโครนั้นจบลงในไฟล์ส่วนหัวที่ได้รับ (อาจเป็นส่วนหนึ่งของห้องสมุดทางอ้อม) ที่รวมอยู่ในรหัสของฉันหากคุณต้องการลิ้มรสสิ่งที่เกิดขึ้นถ้า ชื่อทั่วไปใช้สำหรับมาโครรวมwindows.hอยู่ในโครงการ c ++ ที่ไม่สำคัญ เกี่ยวกับข้อassertแรก: "quod licet iovi ไม่ใช่ licet bovi";) ประการที่สองไม่ใช่การตัดสินใจทั้งหมดในห้องสมุดมาตรฐาน (บางครั้งย้อนหลังไปหลายสิบปี) จริง ๆ แล้วถือว่าเป็นความคิดที่ดีโดยมาตรฐานสมัยใหม่ มีเหตุผลว่าทำไมตัวออกแบบโมดูล c ++ พยายามอย่างหนักที่จะไม่ส่งออกมาโครโดยปริยาย
MikeMB

2
@Jahid: ขอบคุณ ในกรณีนั้นให้พิจารณาความเห็นของฉันเป็นโมฆะและเป็นโมฆะ
MikeMB

9

โปรแกรมง่ายๆในการค้นหาเวลาดำเนินการฟังก์ชั่น

#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;
}

6
มันไม่ถูกต้องมากแสดงเพียงไม่กี่วินาที แต่ไม่มีมิลลิวินาที
25

7

ในหนังสือ Scott Meyers ฉันพบตัวอย่างของการแสดงออกแลมบ์ดาสากลทั่วไปที่สามารถใช้ในการวัดเวลาการทำงานของฟังก์ชัน (C ++ 14)

auto timeFuncInvocation = 
    [](auto&& func, auto&&... params) {
        // get time before function invocation
        const auto& start = std::chrono::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 = std::chrono::high_resolution_clock::now();
        return stop - start;
     };

ปัญหาคือคุณวัดการดำเนินการเพียงครั้งเดียวเพื่อให้ผลลัพธ์ที่แตกต่างกันมาก เพื่อให้ได้ผลลัพธ์ที่เชื่อถือได้คุณควรวัดจำนวนการดำเนินการเป็นจำนวนมาก จากการบรรยายของ Andrei Alexandrescu ที่รหัส :: dive 2015 conference - การเขียน Fast Code I:

เวลาที่วัดได้: tm = t + tq + tn + ถึง

ที่อยู่:

tm - วัดเวลา (สังเกต)

t - เวลาที่สนใจจริง

tq - เวลาที่เพิ่มขึ้นโดยเสียงรบกวนควอนไทซ์

tn - time ถูกเพิ่มเข้ามาด้วยแหล่งกำเนิดเสียงที่หลากหลาย

ถึง - เหนือเวลา (การวัดการวนลูปการเรียกฟังก์ชัน)

ตามที่เขาพูดไว้ในการบรรยายคุณควรใช้เวลาอย่างน้อยที่สุดในการดำเนินการตามผลของคุณ ฉันขอแนะนำให้คุณดูการบรรยายที่เขาอธิบายว่าทำไม

นอกจากนี้ยังมีห้องสมุดที่ดีมากจาก google - https://github.com/google/benchmark https://github.com/google/benchmarkห้องสมุดนี้ใช้งานง่ายและทรงพลัง คุณสามารถชำระเงินการบรรยายของ Chandler Carruth บน youtube ซึ่งเขาใช้ห้องสมุดนี้ในทางปฏิบัติ ตัวอย่างเช่น CppCon 2017: Chandler Carruth“ กำลังไปได้เร็วขึ้น”;

ตัวอย่างการใช้งาน:

#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 อาจมีประโยชน์ในกรณีเช่นนี้


น่าสนใจ - ประโยชน์ของการใช้แลมบ์ดาที่นี่เหนือแม่แบบฟังก์ชันคืออะไร
user48956

1
ความแตกต่างที่สำคัญคือมันเป็นวัตถุ callable แต่แน่นอนคุณสามารถได้รับสิ่งที่คล้ายกันมากกับแม่แบบ variadic และ std :: result_of_t
Krzysztof Sommerfeld

@KrzysztofSommerfeld วิธีการทำอย่างนี้สำหรับวิธีการฟังก์ชั่นเมื่อฉันผ่านเวลา (Object.Method1) มันกลับข้อผิดพลาด "ไวยากรณ์ที่ไม่ได้มาตรฐานใช้ '&' เพื่อสร้างตัวชี้ไปยังสมาชิก"
RobinAtTech

timeFuncInvocation ([& objectName] (auto && ... args) {objectName.methodName (std :: forward <decltype (args)> (args) ... () args ... );}, arg1, arg2, ... ); หรือ ommit & sign ก่อน objectName (จากนั้นคุณจะมีสำเนาของวัตถุ)
Krzysztof Sommerfeld

4

วิธีง่ายๆสำหรับ 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


1
นี่ไม่ใช่พกพา มันวัดเวลาตัวประมวลผลบน Linux และเวลานาฬิกาบน Windows
BugSquasher

2
  • มันเป็นวิธีที่ใช้งานง่ายมากใน C ++ 11
  • เราสามารถใช้ std :: chrono :: high_resolution_clock จากส่วนหัว
  • เราสามารถเขียนวิธีการพิมพ์เวลาดำเนินการของวิธีการในรูปแบบที่อ่านได้มาก

ตัวอย่างเช่นหากต้องการค้นหาหมายเลขเฉพาะทั้งหมดระหว่าง 1 ถึง 100 ล้านจะใช้เวลาประมาณ 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, ";
}

0

นี่คือเทมเพลตคลาสที่ยอดเยี่ยมสำหรับการวัดเวลาที่ผ่านไปของฟังก์ชั่นหรือบล็อคโค้ดใด ๆ :

#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;
}

เนื่องจากคลาสเป็นเทมเพลตเราสามารถระบุจริงได้อย่างง่ายดายในวิธีที่เราต้องการวัดและแสดงเวลาของเรา นี่คือเทมเพลตคลาสยูทิลิตี้ที่มีประโยชน์มากสำหรับการทำเครื่องหมายบนโต๊ะและใช้งานง่ายมาก


ส่วนตัวstop()ฟังก์ชั่นสมาชิกไม่จำเป็นเพราะ destructor หยุดจับเวลาสำหรับคุณ
Casey

@Casey การออกแบบของคลาสไม่จำเป็นต้องมีฟังก์ชั่นหยุด แต่ก็มีเหตุผลเฉพาะ โครงสร้างเริ่มต้นเมื่อสร้างวัตถุก่อนtest codeเริ่มจับเวลา จากนั้นหลังจากที่test codeคุณใช้วัตถุตัวจับเวลาอย่างชัดเจนและเรียกใช้วิธีการหยุด คุณต้องเรียกใช้งานด้วยตนเองเมื่อคุณต้องการstopตั้งเวลา ชั้นไม่ได้ใช้พารามิเตอร์ใด ๆ นอกจากนี้ถ้าคุณใช้ชั้นนี้เช่นเดียวกับผมได้แสดงคุณจะเห็นว่ามีการพ้นที่น้อยที่สุดของเวลาระหว่างการเรียกและobj.stop destructor
ฟรานซิส Cugler

@Casey ... สิ่งนี้ยังอนุญาตให้มีวัตถุตัวจับเวลาหลายตัวภายในขอบเขตเดียวกันไม่ใช่วัตถุที่ต้องการจริงๆ แต่เป็นเพียงอีกตัวเลือกหนึ่งที่ทำงานได้
ฟรานซิส Cugler

ตัวอย่างนี้ไม่สามารถรวบรวมได้ในแบบฟอร์มที่นำเสนอ ข้อผิดพลาดเกี่ยวข้องกับ "ไม่ตรงกับผู้ให้บริการ << ... "!
Celdor

@Celdor คุณต้องรวมถึงสิ่งที่เหมาะสมหรือไม่ เช่น<chrono>?
ฟรานซิส Cugler

0

ผมขอแนะนำให้ใช้steady_clockซึ่งเป็น guarunteed 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

0

คุณสามารถมีคลาสแบบง่าย ๆ ซึ่งสามารถใช้สำหรับการวัดแบบนี้

class duration_printer {
public:
    duration_printer() : __start(std::chrono::high_resolution_clock::now()) {}
    ~duration_printer() {
        using namespace std::chrono;
        high_resolution_clock::time_point end = high_resolution_clock::now();
        duration<double> dur = duration_cast<duration<double>>(end - __start);
        std::cout << dur.count() << " seconds" << std::endl;
    }
private:
    std::chrono::high_resolution_clock::time_point __start;
};

สิ่งเดียวที่ต้องทำคือสร้างวัตถุในฟังก์ชันของคุณที่จุดเริ่มต้นของฟังก์ชันนั้น

void veryLongExecutingFunction() {
    duration_calculator dc;
    for(int i = 0; i < 100000; ++i) std::cout << "Hello world" << std::endl;
}

int main() {
    veryLongExecutingFunction();
    return 0;
}

และนั่นคือมัน ชั้นสามารถแก้ไขได้เพื่อให้เหมาะกับความต้องการของคุณ


0

เนื่องจากไม่มีคำตอบที่ให้ถูกต้องหรือให้ผลลัพธ์ที่ทำซ้ำได้ฉันจึงตัดสินใจเพิ่มลิงก์ไปยังโค้ดของฉันที่มีความแม่นยำระดับนาโนวินาทีและสถิติทางวิทยาศาสตร์

โปรดทราบว่านี่จะทำงานเพื่อวัดโค้ดที่ใช้เวลาสั้นมากในการรัน (หรือไม่กี่รอบนาฬิกาเป็นสองสามพัน): หากพวกเขาใช้งานนานจนมีโอกาสที่จะถูกขัดจังหวะโดยบางส่วน จึงไม่สามารถให้ผลลัพธ์ที่ทำซ้ำได้และแม่นยำ ผลที่ตามมาก็คือการวัดไม่เคยเสร็จสิ้น: กล่าวคือมันจะทำการวัดต่อไปจนกว่าจะมีสถิติ 99.9% มั่นใจว่ามีคำตอบที่ถูกต้องซึ่งไม่เคยเกิดขึ้นบนเครื่องที่มีกระบวนการอื่นทำงานเมื่อรหัสใช้เวลานานเกินไป

https://github.com/CarloWood/cwds/blob/master/benchmark.h#L40


0

หากคุณต้องการเวลาที่ปลอดภัยและบรรทัดของรหัสคุณสามารถทำการวัดเวลาการดำเนินการฟังก์ชั่นแมโครหนึ่งบรรทัด:

a)ใช้คลาสการวัดเวลาตามที่แนะนำไว้ข้างต้น (นี่คือการใช้งานของฉันสำหรับ Android):

class MeasureExecutionTime{
private:
    const std::chrono::steady_clock::time_point begin;
    const std::string caller;
public:
    MeasureExecutionTime(const std::string& caller):caller(caller),begin(std::chrono::steady_clock::now()){}
    ~MeasureExecutionTime(){
        const auto duration=std::chrono::steady_clock::now()-begin;
        LOGD("ExecutionTime")<<"For "<<caller<<" is "<<std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()<<"ms";
    }
};

b)เพิ่มมาโครที่ใช้งานได้สะดวกซึ่งใช้ชื่อฟังก์ชั่นปัจจุบันเป็น TAG (การใช้มาโครที่นี่มีความสำคัญมิฉะนั้น__FUNCTION__จะประเมินเป็นMeasureExecutionTimeแทนฟังก์ชั่นที่คุณต้องการวัด

#ifndef MEASURE_FUNCTION_EXECUTION_TIME
#define MEASURE_FUNCTION_EXECUTION_TIME const MeasureExecutionTime measureExecutionTime(__FUNCTION__);
#endif

c)เขียนแมโครของคุณที่จุดเริ่มต้นของฟังก์ชันที่คุณต้องการวัด ตัวอย่าง:

 void DecodeMJPEGtoANativeWindowBuffer(uvc_frame_t* frame_mjpeg,const ANativeWindow_Buffer& nativeWindowBuffer){
        MEASURE_FUNCTION_EXECUTION_TIME
        // Do some time-critical stuff 
}

ซึ่งจะส่งผลให้ int ผลลัพธ์ต่อไปนี้:

ExecutionTime: For DecodeMJPEGtoANativeWindowBuffer is 54ms

โปรดทราบว่าสิ่งนี้ (เหมือนกับโซลูชันที่แนะนำอื่น ๆ ทั้งหมด) จะวัดเวลาระหว่างที่ฟังก์ชันของคุณถูกเรียกใช้และเมื่อถูกส่งคืนไม่ใช่เวลาที่ CPU ของคุณกำลังเรียกใช้ฟังก์ชัน อย่างไรก็ตามหากคุณไม่ได้กำหนดให้มีการเปลี่ยนแปลงใด ๆ ในการระงับรหัสการทำงานของคุณโดยการโทร sleep () หรือคล้ายกันก็ไม่มีความแตกต่างระหว่าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.