2012-01-28 22 views
5

पर सी में शॉर्ट टाइम अंतराल मापना मैं मिलीसेकंड के कुछ क्रम में, कम समय अंतराल को मापने की कोशिश कर रहा हूं। यह कुछ अनौपचारिक कार्य साबित होता है, क्योंकि सर्वव्यापी time() फ़ंक्शन पूरे सेकंड परिशुद्धता पर काम करता है। कुछ शोध के बाद मैं नीचे दिए गए कोड नमूने में देखा चार विधियों के साथ बाहर आया:उबंटू/वीएमवेयर

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

int main(int argc, char *argv[]) 
{ 
    clock_t t0, t1; 
    double dt0; 

    struct timespec t2, t3; 
    double dt1; 

    struct timespec t4, t5; 
    double dt2; 

    struct timeval t6, t7; 
    double dt3; 

    volatile long long i; 

    t2.tv_sec = 0; 
    t2.tv_nsec = 0; 
    clock_settime(CLOCK_MONOTONIC, &t2); 
    clock_settime(CLOCK_REALTIME, &t2); 

    t0 = clock(); 
    clock_gettime(CLOCK_REALTIME, &t2); 
    clock_gettime(CLOCK_MONOTONIC, &t4); 
    gettimeofday(&t6, NULL); 

    getchar(); 
    for (i=0; i<1e9; i++) {}; 

    gettimeofday(&t7, NULL); 
    clock_gettime(CLOCK_MONOTONIC, &t5); 
    clock_gettime(CLOCK_REALTIME, &t3); 
    t1 = clock(); 

    dt0 = (double) (t1 - t0)/CLOCKS_PER_SEC; 
    dt1 = (double) (t3.tv_nsec - t2.tv_nsec)/1e9; 
    dt2 = (double) (t5.tv_nsec - t4.tv_nsec)/1e9; 
    dt3 = (double) (t7.tv_usec - t6.tv_usec)/1e6; 

    printf("1. clock():   [0]=%10.0f, [1]=%10.0f, [1-0]=%10.6f sec\n", (double) t0, (double) t1, dt0); 
    printf("2. clock_gettime(R): [2]=%10ld, [3]=%10ld, [3-2]=%10f sec\n", (long) t2.tv_nsec, (long) t3.tv_nsec, dt1); 
    printf("3. clock_gettime(M): [2]=%10ld, [3]=%10ld, [3-2]=%10f sec\n", (long) t4.tv_nsec, (long) t5.tv_nsec, dt2); 
    printf("4. gettimeofday(): [4]=%10ld, [5]=%10ld, [5-4]=%10f sec\n", (long) t6.tv_usec, (long) t7.tv_usec, dt3); 

    return 0; 
} 

फिर, मैं संकलित और साथ इसे चलाने:

gcc -lrt -o timer.e timer.c; time ./timer.e 

मैं के एक जोड़े को पेश करने getchar() कॉल का इस्तेमाल किया सेकंड real और user समय रिपोर्ट के बीच एक अंतर देखने के लिए देरी, और परिणाम था:

1. clock():   [0]=   0, [1]= 3280000, [1-0]= 3.280000 sec 
2. clock_gettime(R): [2]= 823922476, [3]= 478650549, [3-2]= -0.345272 sec 
3. clock_gettime(M): [2]= 671137949, [3]= 325864897, [3-2]= -0.345273 sec 
4. gettimeofday(): [4]= 823924, [5]= 478648, [5-4]= -0.345276 sec 

real 0m6.659s 
user 0m3.280s 
sys  0m0.010s 

आप देख सकते हैं, केवल सार्थक परिणाम time कमांड द्वारा विधि 1 और user समय के बीच सहसंबंध है।

यह कुछ प्रश्न लाता है: 1. परिणाम 2-4 अर्थहीन क्यों हैं? 2. मैं प्रोग्राम चलाने में व्यतीत वास्तविक समय को कैसे मापूं, जैसे real संख्या time रिपोर्ट?

मेरा पर्यावरण एएमडी आधारित एचपी लैपटॉप पर विंडोज 7 पर वीएमवेयर पर उबंटू 10.04 एलटीएस 64-बिट है।

+0

यदि यह परीक्षण के लिए है, आप देख सकते यह उपयोगी पुनरावृत्तियों की संख्या में वृद्धि के रूप में घड़ी सेट की जरूरत नहीं है। यह निश्चित रूप से परीक्षण को लंबे समय तक चलाएगा, लेकिन कम रिज़ॉल्यूशन समय माप का उपयोग कर सकता है। –

+0

@MichaelMior - इसका उपयोग बहुत मोटा बेंचमार्किंग के लिए किया जाता है - मैं मेजबान (लिनक्स) पर निष्पादित कुछ एल्गोरिदम के रन टाइम की तुलना करने और यूएसबी के माध्यम से जुड़े हार्डवेयर त्वरक पर तुलना करने की कोशिश कर रहा हूं। दोनों मामलों में, कॉलर एक ही प्रोग्राम है, होस्ट प्रोग्राम है, और मुझे बाहरी हार्डवेयर के काम को पूरा करने के लिए बस "बैठता है और इंतजार करता है" कुल समय प्राप्त करने का एक तरीका चाहिए। यही कारण है कि घड़ी() जवाब नहीं है, बी/सी यह प्रतीक्षा समय के लिए गिनती नहीं है (जैसा कि यहां प्राप्तकर्ता() कॉल द्वारा दिखाया गया है)। – ysap

उत्तर

12

आप clock_gettime() के साथ सही रास्ते पर हैं।

हालांकि, आपको उन clock_settime() कॉल से छुटकारा पाना चाहिए: कोड के ब्लॉक से पहले और बाद में बस clock_gettime() पर कॉल करें, और अंतर देखें।

इसके अलावा, अंतर की गणना करते समय, आपको tv_sec और tv_nsec दोनों खाते में लेना चाहिए; आपका वर्तमान कोड सिर्फ नैनोसेकंद घटक को देखता है और पूर्ण सेकंड को अनदेखा करता है।

मेरी Ubuntu पर निम्नलिखित कोड बार यह पाश निष्पादित करने के लिए ले जाता है की एक बहुत सही माप देता है:

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

int main(int argc, char *argv[]) 
{ 
    struct timespec t2, t3; 
    double dt1; 

    volatile long long i; 

    clock_gettime(CLOCK_MONOTONIC, &t2); 
    for (i=0; i<1e9; i++) {}; 
    clock_gettime(CLOCK_MONOTONIC, &t3); 
    //time in seconds 
    dt1 = (t3.tv_sec - t2.tv_sec) + (double) (t3.tv_nsec - t2.tv_nsec) * 1e-9; 
    printf("%f\n", dt1); 

    return 0; 
} 
+0

धन्यवाद! यह सुधार वह है जो मैं ढूंढ रहा हूं। हर बार एक बार में बस स्पष्ट देखने के लिए याद आती है। मैंने सोचा कि _sec और _nsec फ़ील्ड एक ही डेटा को अलग-अलग परिशुद्धता में रखते हैं, लेकिन अब मैं देखता हूं कि यह टाइम स्टैंप का पूरा और नैनोसेक भाग है। – ysap

1

समय सूक्ष्म और यहां तक ​​कि नैनो सेकंड http://en.wikipedia.org/wiki/Time_Stamp_Counter

+0

rdtsc पर एक स्पष्टीकरण की ओर इशारा करते हुए धन्यवाद। कुछ संदर्भों में उपयोगी हो सकता है, लेकिन मैं यह पता लगाने की कोशिश कर रहा हूं कि मैंने जो कोड लिखा है वह अपेक्षित परिणाम नहीं देता है। – ysap

1

करने के लिए नीचे मापने के बारे में कुछ संकेत आपके clock_settime कॉल आपको नहीं लगता कि वे क्या करते हैं। अगर आपको अनुमति मिलती है तो वे सिस्टम की विस्तृत घड़ी को 0 पर सेट कर सकते हैं, शायद आप जो चाहते हैं उसे नहीं। लगभग सभी POSIX फ़ंक्शंस में रिटर्न वैल्यू होता है जो आपको बताता है कि कॉल सफल हुआ है या नहीं। आम तौर पर उस मूल्य को अनदेखा करना एक बुरा विचार है। विशेष रूप से अपने मामले के लिए मुझे लगता है कि यह मूल्य यह देखते हुए कि जाना चाहिए था के रूप में यह man पेज में पाया जा सकता:

EPERM clock_settime() घड़ी संकेत दिया स्थापित करने के लिए अनुमति नहीं है।

सौभाग्य से आपको अनुमति बस के रूप में इस :)

+0

मैंने गेटटाइम से अजीब परिणाम प्राप्त करने के बाद सेटटाइम जोड़ा। जाहिर है, इसका परिणाम पर कोई प्रभाव नहीं पड़ा। – ysap

+0

@ysap, यह वही है जो मैं कह रहा हूं। इसका परिणाम इस पर कोई प्रभाव नहीं पड़ता है क्योंकि यह ** विफल रहता है **। अन्यथा यह आपके मशीन के लिए नाटकीय परिणाम होगा, आपके सिस्टम घड़ी को 1 जनवरी, 1 9 70 या उससे कुछ की तरह स्थापित करेगा। ऐसा मत करो। यह देखने के लिए कि क्या वे सफल हैं या नहीं, सिस्टम कॉल की वापसी की जांच करें। –

+0

हां, बिंदु ले लिया गया और कोड प्रोग्राम से हटा दिया गया था। – ysap