लिनक्स पर सी ++ प्राप्त करने का समय - घड़ी () ठीक से काम नहीं करता है


102

विंडोज पर, clock()मिलीसेकेंड में समय देता है, लेकिन इस लिनक्स बॉक्स पर मैं काम कर रहा हूं, यह इसे निकटतम 1000 तक पहुंचाता है, इसलिए सटीक केवल "दूसरा" स्तर है और मिलीसेकंड स्तर तक नहीं।

मैंने QTimeकक्षा का उपयोग करते हुए क्यूटी के साथ एक समाधान पाया , किसी वस्तु को त्वरित किया और start()उस पर कॉल किया और फिर elapsed()मिलीसेकंड की संख्या को समाप्त करने के लिए कॉल किया।

मुझे इस तरह का सौभाग्य मिला क्योंकि मैं क्यूटी के साथ काम करना शुरू कर रहा हूं, लेकिन मैं ऐसा समाधान चाहूंगा जो तीसरे पक्ष के पुस्तकालयों पर निर्भर न हो,

क्या ऐसा करने का कोई मानक तरीका नहीं है?

अपडेट करें

कृपया बूस्ट की सिफारिश न करें ।।

अगर बूस्ट और क्यूटी यह कर सकते हैं, तो निश्चित रूप से यह जादू नहीं है, कुछ मानक होना चाहिए जो वे उपयोग कर रहे हैं!


2
एडिट के बारे में - लेकिन इसे पोर्टेबल तरीके से करने के लिए कुछ दर्द होता है।
अनाम

जवाबों:


37

आप अपनी पद्धति के आरंभ और अंत में गेटटाइमऑफ का उपयोग कर सकते हैं और फिर दो वापसी संरचनाओं में अंतर कर सकते हैं। आपको निम्न जैसा एक ढांचा मिलेगा:

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}

संपादित करें: नीचे दिए गए दो टिप्पणियों के रूप में, घड़ी_गेटाइम (CLOCK_MONOTONIC) आपके पास उपलब्ध होने पर एक बेहतर विकल्प है, जो इन दिनों लगभग हर जगह होना चाहिए।

संपादित करें: किसी और ने टिप्पणी की कि आप आधुनिक C ++ का उपयोग std :: chrono :: high_resolution_clock के साथ भी कर सकते हैं, लेकिन यह मोनोटोनिक होने की गारंटी नहीं है। इसके बजाय स्थिर_का उपयोग करें।


38
गंभीर काम के लिए भयानक। साल में दो बार बड़े मुद्दे, जब कोई तारीख करता है, और निश्चित रूप से एनटीपी सिंक। उपयोग clock_gettime (CLOCK_MONOTONIC,)
AndrewStone

9
@AndrewStone: UNIX का समय प्रति वर्ष दो बार नहीं बदलता है। या प्रति वर्ष एक बार भी। लेकिन, हाँ, CLOCK_MONOTONICस्थानीयकृत सिस्टम समय समायोजन से बचने के लिए बहुत अच्छा है।

138
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    struct timeval start, end;

    long mtime, seconds, useconds;    

    gettimeofday(&start, NULL);
    usleep(2000);
    gettimeofday(&end, NULL);

    seconds  = end.tv_sec  - start.tv_sec;
    useconds = end.tv_usec - start.tv_usec;

    mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;

    printf("Elapsed time: %ld milliseconds\n", mtime);

    return 0;
}

4
आप अंतर में +0.5 क्यों जोड़ते हैं?
महमूद अल-कुद्सी

19
@ कंप्यूटर गुरु, यह सकारात्मक मूल्यों को गोल करने के लिए एक सामान्य तकनीक है। जब मान पूर्णांक मान से छोटा हो जाता है, तो 0.0 और 0.4999 के बीच कुछ भी ... इसके अलावा 0 से छोटा हो जाता है, और 0.5 और 0.9999 के बीच ... 1 से छोटा हो जाता है
मार्क रैनसम

8
tv_usec मिलीसेकंड नहीं है, यह माइक्रोसेकंड है।
NebulaFox

13
गंभीर काम के लिए भयानक। साल में दो बार बड़े मुद्दे, जब कोई तारीख करता है, और निश्चित रूप से एनटीपी सिंक
एंड्रयूस्टोन

14
@AndrewStone सही है, उसी कंप्यूटर पर समय की तुलना करने के लिए CLOCK_REALTIME के ​​साथ घड़ी_गेटाइम (2) का उपयोग करें। Gettimeofday से (2) मैनपेज: POSIX.1-2008 marks gettimeofday() as obsolete, recommending the use of clock_gettime(2) instead. @CTT, आप को बदलने के द्वारा उदाहरण अद्यतन कर सकता struct timevalकरने के लिए struct timespec, और gettimeofday(&start, NULL)करने के लिए clock_gettime(CLOCK_MONOTONIC, &start), ताकि लोगों को मुसीबत में पड़ नहीं है?
बॉबी पॉवर्स

58

कृपया ध्यान दें कि clockहै नहीं दीवार घड़ी समय को मापने। इसका मतलब है कि यदि आपका कार्यक्रम 5 सेकंड लेता clockहै, तो आवश्यक 5 सेकंड नहीं मापेंगे, लेकिन अधिक (आपका प्रोग्राम कई थ्रेड चला सकता है और इसलिए वास्तविक समय की तुलना में अधिक सीपीयू का उपभोग कर सकता है) या कम। यह प्रयुक्त सीपीयू समय के एक अनुमान को मापता है । अंतर देखने के लिए इस कोड पर विचार करें

#include <iostream>
#include <ctime>
#include <unistd.h>

int main() {
    std::clock_t a = std::clock();
    sleep(5); // sleep 5s
    std::clock_t b = std::clock();

    std::cout << "difference: " << (b - a) << std::endl;
    return 0;
}

यह मेरे सिस्टम पर आउटपुट देता है

$ difference: 0

क्योंकि हमने जो भी किया वह सब सोने का था और किसी CPU समय का उपयोग नहीं करना था! हालाँकि, gettimeofdayहम जो चाहते हैं उसका उपयोग करके (?)

#include <iostream>
#include <ctime>
#include <unistd.h>
#include <sys/time.h>

int main() {
    timeval a;
    timeval b;

    gettimeofday(&a, 0);
    sleep(5); // sleep 5s
    gettimeofday(&b, 0);

    std::cout << "difference: " << (b.tv_sec - a.tv_sec) << std::endl;
    return 0;
}

मेरे सिस्टम पर आउटपुट

$ difference: 5

यदि आपको अधिक सटीकता की आवश्यकता है लेकिन सीपीयू समय प्राप्त करना चाहते हैं , तो आप getrusageफ़ंक्शन का उपयोग करने पर विचार कर सकते हैं ।


A उल्लेख के बारे में sleep()- मैं पहले से ही एक सवाल पूछ रहा हूँ (क्यों यह मेरे अलावा हर किसी के लिए ठीक काम करता है?) , जब आपका जवाब मिल गया।
हाय-एंजेल

18

मैं बूस्ट द्वारा पेश किए गए टूल की भी सिफारिश करता हूं। या तो उल्लिखित बूस्टर टाइमर, या Boost.DateTime से बाहर कुछ हैक करें या सैंडबॉक्स में नया प्रस्तावित पुस्तकालय है - Boost.Chrono : यह अंतिम टाइमर के लिए एक प्रतिस्थापन होगा और इसमें विशेषता होगी:

  • C ++ 0x मानक लाइब्रेरी की समय उपयोगिताओं, सहित:
    • कक्षा का खाका duration
    • कक्षा का खाका time_point
    • घड़ियों:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • timerटाइप टेम्पलेट के साथ वर्ग टेम्पलेट :
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • प्रक्रिया घड़ियाँ और टाइमर:
    • process_clock, वास्तविक, सीपीयू, और सिस्टम-सीपीयू बार कैप्चरिंग।
    • process_timer, कैप्चर किए गए वास्तविक, उपयोगकर्ता-सीपीयू, और सिस्टम-सीपीयू बार।
    • run_timer, सुविधाजनक रिपोर्टिंग | process_timer | परिणाम है।
  • C ++ 0x मानक लाइब्रेरी का संकलन-समय तर्कसंगत अंकगणित।

यहाँ सुविधा सूची का स्रोत है


अभी के लिए आप बूस्ट टाइमर का उपयोग कर सकते हैं और फिर इसे समीक्षा / स्वीकार किए जाने पर इनायत से क्रोनो की ओर पलायन कर सकते हैं।
अनाम

13

मैंने सीटीटी के उत्तर केTimer आधार पर एक वर्ग लिखा है । इसका उपयोग निम्न तरीके से किया जा सकता है:

Timer timer = Timer();
timer.start();
/* perform task */
double duration = timer.stop();
timer.printTime(duration);

यहाँ इसका कार्यान्वयन है:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
using namespace std;

class Timer {
private:

    timeval startTime;

public:

    void start(){
        gettimeofday(&startTime, NULL);
    }

    double stop(){
        timeval endTime;
        long seconds, useconds;
        double duration;

        gettimeofday(&endTime, NULL);

        seconds  = endTime.tv_sec  - startTime.tv_sec;
        useconds = endTime.tv_usec - startTime.tv_usec;

        duration = seconds + useconds/1000000.0;

        return duration;
    }

    static void printTime(double duration){
        printf("%5.6f seconds\n", duration);
    }
};

2
यह अच्छा है, लेकिन "nseconds" भ्रामक है क्योंकि समय-समय पर nanoseconds नहीं होता है, यह microseconds रखता है, इसलिए मेरा सुझाव है कि लोग इसे "useconds" कहेंगे।
ph00

धन्यवाद। सुधार किया गया।
क्रिस रेडफोर्ड

9

यदि आपको पुराने यूनियनों के लिए पोर्टेबल होने के लिए कोड की आवश्यकता नहीं है, तो आप clock_gettime () का उपयोग कर सकते हैं, जो आपको नैनोसेकंड में समय देगा (यदि आपका प्रोसेसर उस संकल्प का समर्थन करता है)। यह POSIX है, लेकिन 2001 से।


4

घड़ी () में अक्सर एक बहुत घटिया संकल्प होता है। यदि आप मिलीसेकंड स्तर पर समय को मापना चाहते हैं, तो एक विकल्प घड़ी_गेटाइम () का उपयोग करना है, जैसा कि इस प्रश्न में बताया गया है।

(याद रखें कि आपको लिनक्स पर लिंक के साथ लिंक करने की आवश्यकता है)।


4

C ++ 11 के साथ और std::chrono::high_resolution_clockआप यह कर सकते हैं:

#include <iostream>
#include <chrono>
#include <thread>
typedef std::chrono::high_resolution_clock Clock;

int main()
{
    std::chrono::milliseconds three_milliseconds{3};

    auto t1 = Clock::now();
    std::this_thread::sleep_for(three_milliseconds);
    auto t2 = Clock::now();

    std::cout << "Delta t2-t1: " 
              << std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count()
              << " milliseconds" << std::endl;
}

आउटपुट:

Delta t2-t1: 3 milliseconds

लिंक डेमो: http://cpp.sh/2zdtu


2

घड़ी () लिनेक्स पर मिलीसेकंड या सेकंड नहीं लौटाती है। आमतौर पर क्लॉक () एक लिनक्स सिस्टम पर माइक्रोसेकंड देता है। घड़ी द्वारा लौटाए गए मूल्य की व्याख्या करने का उचित तरीका (कितना समय बीत चुका है, यह जानने के लिए इसे CLOCKS_PER_SEC द्वारा विभाजित करना है।


मैं काम कर रहा हूँ बॉक्स में नहीं! प्लस, मैं कर रहा हूँ CLOCKS_PER_SEC से विभाजित है, लेकिन यह व्यर्थ है संकल्प केवल दूसरे के लिए नीचे है, क्योंकि
Hasen

अच्छी तरह से निष्पक्ष होना करने के लिए, इकाइयों है माइक्रोसेकंड (CLOCKS_PER_SEC 1000000 सभी POSIX सिस्टम पर है)। बस इसका सेकंड रेजोल्यूशन है। :-P।
इवान टेरान

1

यह काम करना चाहिए ... एक मैक पर परीक्षण ...

#include <stdio.h>
#include <sys/time.h>

int main() {
        struct timeval tv;
        struct timezone tz;
        struct tm *tm;
        gettimeofday(&tv,&tz);
        tm=localtime(&tv.tv_sec);
        printf("StartTime: %d:%02d:%02d %d \n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec);
}

हाँ ... इसे दो बार चलाएं और घटाएं ...


1

POSIX मानक clockमें CLOCKS_PER_SEC प्रतीक के संदर्भ में इसका रिटर्न वैल्यू परिभाषित किया गया है और किसी भी सुविधाजनक फैशन में इसे परिभाषित करने के लिए एक कार्यान्वयन मुफ़्त है। लिनक्स के तहत, मुझे times()फ़ंक्शन के साथ अच्छी किस्मत मिली है।


1

gettimeofday - समस्या यह है कि निम्न मान हो सकते हैं यदि आप हार्डवेयर घड़ी बदलते हैं (उदाहरण के लिए NTP के साथ) बूस्ट - इस प्रोजेक्ट घड़ी के लिए उपलब्ध नहीं है () - आमतौर पर 4 बाइट्स पूर्णांक देता है, जिसका अर्थ है कि इसकी कम क्षमता, और कुछ समय बाद यह नकारात्मक संख्या देता है।

मैं अपनी खुद की क्लास बनाना पसंद करता हूं और प्रत्येक 10 मिलिसेकंड को अपडेट करता हूं, इसलिए यह तरीका अधिक लचीला है, और मैं इसे सब्सक्राइब करने के लिए भी सुधार सकता हूं।

class MyAlarm {
static int64_t tiempo;
static bool running;
public:
static int64_t getTime() {return tiempo;};
static void callback( int sig){
    if(running){
        tiempo+=10L;
    }
}
static void run(){ running = true;}
};

int64_t MyAlarm::tiempo = 0L;
bool MyAlarm::running = false;

इसे ताज़ा करने के लिए मैं सेटिमीटर का उपयोग करता हूं:

int main(){
struct sigaction sa; 
struct itimerval timer; 

MyAlarm::run();
memset (&sa, 0, sizeof (sa)); 
sa.sa_handler = &MyAlarm::callback; 

sigaction (SIGALRM, &sa, NULL); 


timer.it_value.tv_sec = 0; 
timer.it_value.tv_usec = 10000; 



timer.it_interval.tv_sec = 0; 
timer.it_interval.tv_usec = 10000; 


setitimer (ITIMER_REAL, &timer, NULL); 
.....

सेटिमर और ITIMER_VIRTUAL और ITIMER_REAL को देखें।

अलार्म या ualarm फ़ंक्शन का उपयोग न करें, जब आपकी प्रक्रिया को कड़ी मेहनत मिलेगी, तो आपके पास कम सटीकता होगी।



0

अद्यतन के रूप में, यह दिखता है कि विंडोज़ घड़ी पर () दीवार घड़ी का समय (CLOCKS_PER_SEC परिशुद्धता के साथ) मापता है

 http://msdn.microsoft.com/en-us/library/4e2ess30(VS.71).aspx

लिनक्स पर रहते हुए यह वर्तमान प्रक्रिया द्वारा प्रयुक्त कोर के पार cpu समय को मापता है

http://www.manpagez.com/man/3/clock

और (यह प्रतीत होता है, और जैसा कि मूल पोस्टर द्वारा नोट किया गया है) वास्तव में CLOCKS_PER_SEC की तुलना में कम परिशुद्धता के साथ है , हालांकि शायद यह लिनक्स के विशिष्ट संस्करण पर निर्भर करता है।


0

मुझे गेटाइमोफ़डे () का उपयोग न करने का होला सोया तरीका पसंद है। यह मेरे लिए एक चल रहे सर्वर पर हुआ, व्यवस्थापक ने समयक्षेत्र बदल दिया। स्थानीय मान को समान (सही) दिखाने के लिए घड़ी को अपडेट किया गया था। इससे फ़ंक्शन समय () और गेटटाइमऑफ़डे () 2 घंटे शिफ्ट हो गया और कुछ सेवाओं में सभी टाइमस्टैम्प फंस गए।


0

मैंने एक C++क्लास लिखी timeb

#include <sys/timeb.h>
class msTimer 
{
public:
    msTimer();
    void restart();
    float elapsedMs();
private:
    timeb t_start;
};

सदस्य कार्य:

msTimer::msTimer() 
{ 
    restart(); 
}

void msTimer::restart() 
{ 
    ftime(&t_start); 
}

float msTimer::elapsedMs() 
{
    timeb t_now;
    ftime(&t_now);
    return (float)(t_now.time - t_start.time) * 1000.0f +
           (float)(t_now.millitm - t_start.millitm);
}

उपयोग का उदाहरण:

#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char** argv) 
{
    msTimer t;
    for (int i = 0; i < 5000000; i++)
        ;
    std::cout << t.elapsedMs() << endl;
    return 0;
}

मेरे कंप्यूटर पर आउटपुट '19' है। msTimerवर्ग की सटीकता मिलीसेकंड के क्रम की है। ऊपर उपयोग उदाहरण में, for-loop द्वारा उठाए गए निष्पादन का कुल समय ट्रैक किया गया है। इस बार ऑपरेटिंग सिस्टम में main()मल्टीटास्किंग के कारण निष्पादन के संदर्भ में स्विच करना शामिल था ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.