Gettimeofday () microsecond संकल्प होने की गारंटी है?

तो मैं खुद को एक गेम पोर्टिंग करता हूं, जिसे मूल रूप से Win32 API के लिए लिनक्स में लिखा गया था (ठीक है, Win32 पोर्ट के ओएस एक्स पोर्ट को लिनक्स में पोर्ट करना)। प्रक्रिया शुरू होने के बाद से मैंने यूसेकंड देकर QueryPerformanceCounter लागू किया है:

BOOL QueryPerformanceCounter(LARGE_INTEGER* performanceCount)
{
    gettimeofday(&currentTimeVal, NULL);
    performanceCount->QuadPart = (currentTimeVal.tv_sec - startTimeVal.tv_sec);
    performanceCount->QuadPart *= (1000 * 1000);
    performanceCount->QuadPart += (currentTimeVal.tv_usec - startTimeVal.tv_usec);

    return true;
}

यह QueryPerformanceFrequency() आवृत्ति के रूप में निरंतर 1000000 देने के साथ मिलकर, मेरी मशीन पर अच्छी तरह से काम करता है, मुझे एक 64 बिट चर प्रदान करता है जिसमें uSeconds कार्यक्रम शुरू होने के बाद से। तो यह पोर्टेबल है? मैं यह नहीं खोजना चाहता कि यह अलग-अलग काम करता है अगर कर्नेल को किसी निश्चित तरीके से या उस तरह से कुछ भी संकलित किया गया था। हालांकि, मैं लिनक्स के अलावा किसी अन्य चीज़ के लिए गैर-पोर्टेबल होने के साथ ठीक हूं।

0
जोड़ा संपादित
विचारों: 8

10 उत्तर

मेरे अनुभव से, और जो मैंने इंटरनेट पर पढ़ा है, जवाब "नहीं" है, इसकी गारंटी नहीं है। यह सीपीयू की गति, ऑपरेटिंग सिस्टम, लिनक्स के स्वाद आदि पर निर्भर करता है।

0
जोड़ा

gettimeofday() का वास्तविक संकल्प हार्डवेयर आर्किटेक्चर पर निर्भर करता है। इंटेल प्रोसेसर के साथ-साथ एसपीएआरसी मशीन उच्च रिज़ॉल्यूशन टाइमर प्रदान करती हैं जो माइक्रोसेकंड को मापती हैं। अन्य हार्डवेयर आर्किटेक्चर सिस्टम के टाइमर पर वापस आते हैं, जो आमतौर पर 100 हर्ट्ज पर सेट होता है। ऐसे मामलों में, समय संकल्प कम सटीक होगा।

I obtained this answer from High Resolution Time Measurement and Timers, Part I

0
जोड़ा

शायद। लेकिन आपको बड़ी समस्याएं हैं। gettimeofday() का परिणाम गलत समय हो सकता है यदि आपके सिस्टम पर प्रक्रियाएं हैं जो टाइमर (यानी, एनटीपीडी) बदलती हैं। हालांकि, "सामान्य" लिनक्स पर, मुझे विश्वास है कि gettimeofday() का संकल्प 10us है। यह आपके सिस्टम पर चल रही प्रक्रियाओं के आधार पर आगे और पिछड़ा और समय कूद सकता है। यह प्रभावी ढंग से आपके प्रश्न संख्या का उत्तर देता है।

समय अंतराल के लिए आपको clock_gettime (CLOCK_MONOTONIC) में देखना चाहिए। बहु-कोर सिस्टम और बाहरी घड़ी सेटिंग्स जैसी चीजों के कारण यह कई कम मुद्दों से ग्रस्त है।

साथ ही, clock_getres() फ़ंक्शन में देखें।

0
जोड़ा
इसे 2001 में पेश किया गया था, लेकिन POSIX 2008 तक अनिवार्य नहीं है।
जोड़ा लेखक R.., स्रोत
लॉक_getटाइम के लिए लिनक्स एफएक्यू से (डेविड श्लोस्नागल का जवाब देखें) "CLOCK_MONOTONIC ... एनटीपी द्वारा एडीटीएक्सएक्स() के माध्यम से समायोजित आवृत्ति है। भविष्य में (मैं अभी भी पैच प्राप्त करने की कोशिश कर रहा हूं) एक CLOCK_MONOTONIC_RAW होगा जो नहीं होगा बिल्कुल संशोधित किया जा सकता है, और हार्डवेयर काउंटर के साथ एक रैखिक सहसंबंध होगा। " मुझे नहीं लगता कि _RAW घड़ी ने इसे कभी भी कर्नेल में बना दिया है (जब तक इसका नाम बदलकर _HR किया गया हो, लेकिन मेरे शोध से पता चलता है कि प्रयासों को भी त्याग दिया जा रहा है)।
जोड़ा लेखक Tony Delroy, स्रोत
@ vitaly.v.ch यह पॉज़िक्स है इसलिए यह केवल लिनक्स और 'न्यूस्ट' नहीं है? यहां तक ​​कि 'एंटरप्राइज़' डिस्ट्रोज़ जैसे कि Red Hat Enterprise Linux 2.6.18 पर आधारित है जिसमें घड़ी_gettime है, नहीं, बहुत नया नहीं .. (आरएचईएल में मैनपेज दिनांक 2004-मार्च -12 है, इसलिए यह थोड़ी देर के लिए रहा है) जब तक कि आप वास्तव में फिसलने वाले पुराने कर्नेल डब्ल्यूटीएफ के बारे में बात करना क्या आपका मतलब है?
जोड़ा लेखक Spudd86, स्रोत
clock_gettime केवल नवीनतम लिनक्स पर मौजूद है। अन्य प्रणाली केवल gettimeofday() है
जोड़ा लेखक vitaly.v.ch, स्रोत
2001 में POSIX में clock_gettime शामिल किया गया था। जहां तक ​​मुझे वर्तमान में clock_gettime() लिनक्स 2.6 और qnx में लागू किया गया है। लेकिन लिनक्स 2.4 वर्तमान में कई उत्पादन प्रणालियों में उपयोग किया जाता है।
जोड़ा लेखक vitaly.v.ch, स्रोत

शराब वास्तव में QueryPerformanceCounter() को लागू करने के लिए gettimeofday() का उपयोग कर रहा है और यह कई विंडोज गेम लिनक्स और मैक पर काम करने के लिए जाना जाता है।

Starts http://source.winehq.org/source/dlls/kernel32/cpu.c#L312

leads to http://source.winehq.org/source/dlls/ntdll/time.c#L448

0
जोड़ा

उच्च संकल्प, इंटेल प्रोसेसर के लिए कम ओवरहेड समय

यदि आप इंटेल हार्डवेयर पर हैं, तो यहां सीपीयू रीयल-टाइम निर्देश काउंटर को पढ़ने का तरीका बताया गया है। यह आपको प्रोसेसर बूट होने के बाद निष्पादित CPU चक्रों की संख्या बताएगा। यह शायद बेहतरीन माप वाला काउंटर है जिसे आप प्रदर्शन माप के लिए प्राप्त कर सकते हैं।

ध्यान दें कि यह CPU चक्रों की संख्या है। लिनक्स पर आप CPU की गति / proc / cpuinfo से प्राप्त कर सकते हैं और सेकंड की संख्या प्राप्त करने के लिए विभाजित कर सकते हैं। इसे एक डबल में परिवर्तित करना काफी आसान है।

जब मैं इसे अपने बॉक्स पर चलाता हूं, तो मुझे मिलता है

11867927879484732
11867927879692217
it took this long to call printf: 207485

यहां इंटेल डेवलपर की मार्गदर्शिका है जो बहुत सारी जानकारी देता है।

#include 
#include 

inline uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx");
    return (uint64_t)hi << 32 | lo;
}

main()
{
    unsigned long long x;
    unsigned long long y;
    x = rdtsc();
    printf("%lld\n",x);
    y = rdtsc();
    printf("%lld\n",y);
    printf("it took this long to call printf: %lld\n",y-x);
}
0
जोड़ा
क्या आपका कोड पहले RDTSC निर्देश के बाद CPUID का उपयोग नहीं करना चाहिए और कोड को बेंचमार्क किए जाने से पहले? अन्यथा, बेंचमार्क किए गए कोड को पहले RDTSC के साथ पहले / समानांतर के साथ निष्पादित किया जा रहा है, और इसके परिणामस्वरूप RDTSC डेल्टा में प्रस्तुत किया गया है?
जोड़ा लेखक Tony Delroy, स्रोत
ध्यान दें कि टीएससी को कोर के बीच हमेशा सिंक्रनाइज़ नहीं किया जा सकता है, जब प्रोसेसर कम पावर मोड में प्रवेश करता है (और आपके पास ऐसा करने का कोई तरीका नहीं है), और सामान्य रूप से हमेशा विश्वसनीय नहीं होता है, तो इसकी आवृत्ति को रोक या बदल सकता है। कर्नेल विश्वसनीय होने पर पता लगाने में सक्षम है, एचपीईटी और एसीपीआई पीएम टाइमर जैसे अन्य विकल्पों का पता लगाएं, और स्वचालित रूप से सर्वश्रेष्ठ का चयन करें। समय के लिए कर्नेल का हमेशा उपयोग करना एक अच्छा विचार है जब तक कि आप वास्तव में सुनिश्चित नहीं हैं कि टीएससी स्थिर और मोनोटोनिक है।
जोड़ा लेखक CesarB, स्रोत
कोर और इंटेल प्लेटफार्मों के ऊपर टीएससी पावर प्रबंधन राज्यों से स्वतंत्र निरंतर आवृत्ति पर कई CPUs और वृद्धिओं में सिंक्रनाइज़ किया जाता है। इंटेल सॉफ्टवेयर डेवलपर मैनुअल, वॉल्यूम देखें। 3 धारा 18.10। हालांकि जिस दर पर काउंटर वृद्धि हुई है वह नहीं सीपीयू की आवृत्ति के समान है। टीएससी प्लेटफार्म की अधिकतम हल आवृत्ति पर वृद्धि करता है, जो स्केलेबल बस आवृत्ति और अधिकतम हल किए गए बस अनुपात के उत्पाद के बराबर है? इंटेल सॉफ्टवेयर डेवलपर मैनुअल, वॉल्यूम। 3 खंड 18.18.5। आप उन मानों को सीपीयू के मॉडल-विशिष्ट रजिस्टरों (एमएसआर) से प्राप्त करते हैं।
जोड़ा लेखक sstock, स्रोत
आप सीपीयू के मॉडल-विशिष्ट रजिस्टरों (एमएसआर) से पूछताछ करके स्केलेबल बस आवृत्ति और अधिकतम हल किए गए बस अनुपात प्राप्त कर सकते हैं: स्केलेबल बस आवृत्ति == एमएसआर_एफएसबी_एफआरक्यू [2: 0] आईडी 0xCD, अधिकतम हल किए गए बस अनुपात == एमएसआर_PLATFORM_ID [ 12: 8] आईडी 0x17। रजिस्टर मूल्यों की व्याख्या करने के लिए इंटेल एसडीएम वॉल्यूम 3 परिशिष्ट बी .1 से परामर्श लें। आप रजिस्टरों से पूछने के लिए लिनक्स पर एमएसआर-टूल्स का उपयोग कर सकते हैं। kernel.org/pub/linux/utils/cpu/msr-tools
जोड़ा लेखक sstock, स्रोत

@Bernard:

मुझे स्वीकार करना है, आपका अधिकांश उदाहरण सीधे मेरे सिर पर चला गया। यह संकलित करता है, और काम करता है, हालांकि। क्या यह एसएमपी सिस्टम या स्पीडस्टेप के लिए सुरक्षित है?

यह एक अच्छा सवाल है ... मुझे लगता है कि कोड ठीक है। एक व्यावहारिक दृष्टिकोण से, हम इसे हर दिन मेरी कंपनी में उपयोग करते हैं, और हम 2-8 कोर से सब कुछ, बक्से की एक विस्तृत चौड़ी सरणी पर चलते हैं। बेशक, वाईएमएमवी, आदि, लेकिन यह एक विश्वसनीय और कम ओवरहेड लगता है (क्योंकि यह सिस्टम-स्पेस में संदर्भ स्विच नहीं करता है) विधि समय का

आम तौर पर यह कैसे काम करता है:

  • कोड के ब्लॉक को असेंबलर घोषित करें (और अस्थिर, तो अनुकूलक इसे अकेला छोड़ देगा)।
  • CPUID निर्देश निष्पादित करें। कुछ सीपीयू जानकारी प्राप्त करने के अलावा (जो हम कुछ भी नहीं करते हैं) यह सीपीयू के निष्पादन बफर को सिंक्रनाइज़ करता है ताकि समय-समय पर निष्पादन निष्पादन से प्रभावित न हो।
  • rdtsc (timestamp पढ़ें) निष्पादन निष्पादित करें। यह संख्या प्राप्त करता है प्रोसेसर रीसेट होने के बाद से मशीन चक्र निष्पादित। यह एक 64-बिट है मूल्य, इसलिए मौजूदा सीपीयू गति के साथ यह हर 1 9 4 साल या उससे भी अधिक समय तक लपेट जाएगा। दिलचस्प बात यह है कि मूल पेंटियम संदर्भ में, वे ध्यान देते हैं कि यह हर किसी के आसपास लपेटता है 5800 साल या उससे भी अधिक।
  • पंक्तियों की अंतिम जोड़ी रजिस्टरों से मूल्यों को संग्रहित करती है चर और लो चर, और इसे 64-बिट रिटर्न मान में डाल दिया।

विशिष्ट नोट्स:

  • आउट ऑफ़ ऑर्डर निष्पादन गलत परिणाम दे सकता है, इसलिए हम निष्पादित करते हैं "cpuid" निर्देश जो आपको कुछ जानकारी देने के अलावा सीपीयू के बारे में किसी भी ऑर्डर ऑफ ऑर्डर निर्देश निष्पादन को सिंक्रनाइज़ करता है।

  • अधिकांश ओएस सीपीयू पर काउंटर को सिंक्रनाइज़ करते समय सिंक्रनाइज़ करते हैं, इसलिए जवाब दो नैनो-सेकंड के भीतर अच्छा है।

  • हाइबरनेटिंग टिप्पणी शायद सच है, लेकिन अभ्यास में आप शायद हाइबरनेशन सीमाओं में समय के बारे में परवाह नहीं है।

  • स्पीडस्टेप के संबंध में: नए इंटेल CPUs गति की भरपाई करते हैं परिवर्तन और एक समायोजित गिनती देता है। मैंने एक त्वरित स्कैन किया था हमारे नेटवर्क पर कुछ बक्से और केवल एक बॉक्स मिला यह नहीं था: एक पेंटियम 3 कुछ पुराने डेटाबेस सर्वर चला रहा है। (ये लिनक्स बॉक्स हैं, इसलिए मैंने जांच की: grep constant_tsc / proc / cpuinfo)

  • मुझे एएमडी सीपीयू के बारे में निश्चित नहीं है, हम मुख्य रूप से एक इंटेल की दुकान हैं, हालांकि मुझे पता है कि हमारे कुछ निम्न-स्तरीय सिस्टम गुरु ने किया था एएमडी मूल्यांकन।

उम्मीद है कि यह आपकी जिज्ञासा को संतुष्ट करता है, यह एक दिलचस्प है और (आईएमएचओ) प्रोग्रामिंग के अधीन अध्ययन क्षेत्र। आप जानते हैं जब जेफ और जोएल थे इस बारे में बात करते हुए कि प्रोग्रामर को सी पता होना चाहिए या नहीं? मैं था उन पर चिल्लाना, "अरे भूल जाओ कि उच्च स्तरीय सी सामान ... assembler अगर आप जानना चाहते हैं कि कंप्यूटर क्या है, तो आपको क्या सीखना चाहिए करते हुए!"

0
जोड़ा
संदर्भ के लिए, मैंने जो प्रश्न पूछा (एक अलग उत्तर में - टिप्पणियों से पहले) था: "मुझे यह मानना ​​है कि आपका अधिकांश उदाहरण सीधे मेरे सिर पर चला गया। यह संकलित करता है, और काम करता है, हालांकि। क्या यह सुरक्षित है एसएमपी सिस्टम या स्पीडस्टेप? "
जोड़ा लेखक Bernard, स्रोत
... कर्नेल लोग थोड़ी देर के लिए लोगों को rdtsc का उपयोग बंद करने की कोशिश कर रहे हैं ... और आमतौर पर कर्नेल में इसका उपयोग करने से बचें क्योंकि यह केवल अविश्वसनीय है।
जोड़ा लेखक Spudd86, स्रोत

तो यह स्पष्ट रूप से microseconds कहते हैं, लेकिन कहते हैं कि सिस्टम घड़ी का संकल्प अनिर्दिष्ट है। मुझे लगता है कि इस संदर्भ में संकल्प का अर्थ है कि यह कितनी छोटी राशि को कभी बढ़ाया जाएगा?

डेटा संरचना को माप की इकाई के रूप में माइक्रोसॉन्ड होने के रूप में परिभाषित किया जाता है, लेकिन इसका मतलब यह नहीं है कि घड़ी या ऑपरेटिंग सिस्टम वास्तव में उस माप को मापने में सक्षम है।

अन्य लोगों की तरह सुझाव दिया गया है, gettimeofday() खराब है क्योंकि समय निर्धारित करने से घड़ी की कमी हो सकती है और आपकी गणना फेंक सकती है। clock_gettime (CLOCK_MONOTONIC) जो आप चाहते हैं, और clock_getres() आपको आपकी घड़ी की सटीकता बताएगा।

0
जोड़ा
@ mpez0 यह नहीं करता है
जोड़ा लेखक Spudd86, स्रोत
तो gettimeofday() डेलाइट बचत के साथ आगे या पीछे कूदते समय आपके कोड में क्या होता है?
जोड़ा लेखक mpez0, स्रोत
clock_gettime केवल नवीनतम लिनक्स पर मौजूद है। अन्य प्रणाली केवल gettimeofday() है
जोड़ा लेखक vitaly.v.ch, स्रोत

This answer mentions problems with the clock being adjusted. Both your problems guaranteeing tick units and the problems with the time being adjusted are solved in C++11 with the library.

घड़ी std :: chrono :: steady_clock को समायोजित नहीं किया गया है, और इसके अलावा यह वास्तविक समय के सापेक्ष स्थिर दर पर आगे बढ़ेगा, इसलिए स्पीडस्टेप जैसी तकनीकों को इसे प्रभावित नहीं करना चाहिए।

आप std :: chrono :: अवधि विशेषज्ञता जैसे std :: chrono :: microseconds में परिवर्तित करके टाइपएफ़ इकाइयां प्राप्त कर सकते हैं। इस प्रकार के साथ टिक मूल्य द्वारा उपयोग की जाने वाली इकाइयों के बारे में कोई अस्पष्टता नहीं है। हालांकि, ध्यान रखें कि घड़ी में यह संकल्प आवश्यक नहीं है। आप एक घड़ी को वास्तव में घड़ी के बिना एटोजकंड में परिवर्तित कर सकते हैं।

0
जोड़ा

आरडीटीएससी पढ़ना एसएमपी सिस्टम में विश्वसनीय नहीं है, क्योंकि प्रत्येक सीपीयू अपना काउंटर बनाए रखता है और प्रत्येक काउंटर को किसी अन्य सीपीयू के संबंध में सिंक्रनाइज़ करके गारंटी नहीं दी जाती है।

मैं clock_gettime (CLOCK_REALTIME) को आजमाने का सुझाव दे सकता हूं। पॉज़िक्स मैनुअल इंगित करता है कि यह सभी अनुपालन प्रणालियों पर लागू किया जाना चाहिए। यह एक नैनोसेकंद गिनती प्रदान कर सकता है, लेकिन संभवतया यह देखने के लिए कि आप वास्तविक रिज़ॉल्यूशन क्या है, आप शायद clock_getres (CLOCK_REALTIME) को अपने सिस्टम पर देखना चाहेंगे।

0
जोड़ा
clock_getres (CLOCK_REALTIME) वास्तविक रिज़ॉल्यूशन नहीं देगा। Hrtimers उपलब्ध होने पर यह हमेशा "1 एनएस" (एक नैनोसेकंद) लौटाता है, शामिल करें / linux / hrtimer.h फ़ाइल HIGH_RES_NSEC 1 परिभाषित करें (अधिक stackoverflow.com/a/23044075/196561 )
जोड़ा लेखक osgx, स्रोत
0
जोड़ा