এএনএসআই সি ব্যবহার করে মিলি সেকেন্ডে সময় কীভাবে পরিমাপ করা যায়?


127

শুধুমাত্র এএনএসআই সি ব্যবহার করে, মিলিসেকেন্ড যথার্থতা বা আরও কিছু দিয়ে সময়কে মাপার কোনও উপায় আছে কি? আমি টাইম ব্রাউজ করছিলাম but তবে আমি কেবল দ্বিতীয় স্পষ্টতা ফাংশন পেয়েছি।


4
নির্ভুলতা এবং নির্ভুলতার মধ্যে পার্থক্যটি নোট করুন। সেকেন্ডে সময় নিয়ে এবং 1000 দিয়ে গুণ করে আপনি মিলিসেকেন্ড নির্ভুলতার সাথে একটি সময় পেতে পারেন , তবে এটি কোনও কাজে আসেনি। এমএস যথার্থ ফাংশনগুলির অগত্যা এমএস নির্ভুলতা নেই - যদিও তারা সাধারণত 1 এস নির্ভুলতার চেয়ে ভাল করে।
স্টিভ জেসোপ

2
সহজ উত্তরটি হ'ল না, এএনএসআই সি মিলিসেকেন্ড নির্ভুলতা বা আরও ভাল সমর্থন করে না। আরও জটিল উত্তর আপনি যা করার চেষ্টা করছেন তার উপর নির্ভর করে - স্পষ্টতই পুরো অঞ্চলটি একটি দুঃস্বপ্ন - এমনকি যদি আপনি বহুল পরিমাণে পজিক্স ফাংশন ব্যবহারের অনুমতি দেন। আপনি "পরিমাপ" শব্দটি ব্যবহার করেন তাই আমি ধরে নিই যে আপনি "প্রাচীরের ঘড়ি" সময়ের চেয়ে সময়ের ব্যবধানে আগ্রহী। কিন্তু আপনি কি আপনার প্রক্রিয়া দ্বারা একটি নিরঙ্কুশ সময়কাল বা সিপিইউ ব্যবহার পরিমাপ করার চেষ্টা করছেন?
ডিপস্টিক

উত্তর:


92

এমন কোনও এএনএসআই সি ফাংশন নেই যা 1 টি দ্বিতীয় বারের চেয়ে ভাল রেজোলিউশন সরবরাহ করে তবে পসিক্স ফাংশনটি gettimeofdayমাইক্রোসেকেন্ড রেজোলিউশন সরবরাহ করে। ক্লক ফাংশন কেবলমাত্র একটি প্রক্রিয়া চালাতে ব্যয় করেছে এবং অনেক সিস্টেমে সঠিক নয়।

আপনি এই ফাংশনটি এভাবে ব্যবহার করতে পারেন:

struct timeval tval_before, tval_after, tval_result;

gettimeofday(&tval_before, NULL);

// Some code you want to time, for example:
sleep(1);

gettimeofday(&tval_after, NULL);

timersub(&tval_after, &tval_before, &tval_result);

printf("Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);

এটি Time elapsed: 1.000870আমার মেশিনে ফিরে আসে ।


30
সামান্য সতর্কতামূলক: gettimeofday () একঘেয়ে নয়, অর্থাত্ এটি চারপাশে লাফিয়ে উঠতে পারে (এবং এমনকি পিছনের দিকেও যেতে পারে), উদাহরণস্বরূপ, যদি আপনার মেশিন কোনও নেটওয়ার্ক টাইম সার্ভার বা অন্য কোনও সময়ের উত্সের সাথে সিঙ্ক্রোনাইজেশন রাখার চেষ্টা করে।
ডিপস্টিক

3
সুনির্দিষ্ট হতে হবে: আইএসও সি 99 (যা আমি মনে করি এএনএসআই সি এর সাথে এই অংশে সামঞ্জস্যপূর্ণ) কোনও সময় রেজোলিউশনের গ্যারান্টিও নেই । (আইএসও সি 99, 7.23.1p4)
রোল্যান্ড ইলিগ

6
এটি লক্ষণীয় যে timeval::tv_usecএটি সর্বদা এক সেকেন্ডের নীচে থাকে, এটি লুপ হয়। অর্থাত্ 1 সেকেন্ডের চেয়ে বড় সময়ের পার্থক্য নিতে, আপনার উচিত:long usec_diff = (e.tv_sec - s.tv_sec)*1000000 + (e.tv_usec - s.tv_usec);
আলেকজান্ডার মালাখভ

4
@ ডিসপস্টিক: তবে মনে রাখবেন যে এনটিপি আপনার ঘড়িটিকে কখনই পিছনের দিকে সরিয়ে দেয় না যতক্ষণ না আপনি স্পষ্টভাবে এটি করতে বলছেন।
thejh

1
অ্যালেক্সান্দার মালাখভ সময় বিয়োগের যুক্তি timersubকার্যকারিতা ভিতরে অন্তর্ভুক্ত করা হয়। আমরা tval_resultমান হিসাবে (টিভি_সেক এবং টিভি_সেক) ব্যবহার করতে পারি ।
x4444

48
#include <time.h>
clock_t uptime = clock() / (CLOCKS_PER_SEC / 1000);

CLOCKS_PER_SEC অনেক সিস্টেমে 1000000 এ সেট করা আছে। আপনি এই ফ্যাশনে এটি ব্যবহার করার আগে তার মানটি মুদ্রণ করুন।
ysap

16
যেহেতু এটি প্রতি সেকেন্ডে ঘড়িগুলি এটির মূল্য কী তা বিবেচনা করে না, ঘড়ির () / CLOCKS_PER_SEC থেকে প্রাপ্ত ফলাফলটি সেকেন্ডে হবে (কমপক্ষে এটি হওয়া উচিত)। 1000 টি দ্বারা ভাগ করে এটি মিলিসেকেন্ডে পরিণত হয়।
ডেভিড ইয়ং

14
সি রেফারেন্স ম্যানুয়াল অনুসারে, ক্লক_টি মানগুলি প্রায় 36 মিনিটের শুরুতে মোড়ানো হতে পারে। আপনি যদি একটি দীর্ঘ গণনা পরিমাপ করেন তবে আপনার এটি সম্পর্কে সচেতন হওয়া দরকার।
সাইবারস্কুল

4
এছাড়াও সাবধান হোন যে পূর্ণসংখ্যা বিভাগ CLOCKS_PER_SEC / 1000সম্ভবত নিখুঁত হতে পারে যা শেষ ফলাফলকে প্রভাবিত করতে পারে (যদিও আমার অভিজ্ঞতায় CLOCKS_PER_SECসর্বদা 1000 এর একাধিক হয়েছে)। এরকম (1000 * clock()) / CLOCKS_PER_SECকম বিভাজন inexactness সমর্থ হয়, কিন্তু অন্যদিকে ওভারফ্লো আরো সমর্থ হয়। কিছু বিষয় বিবেচনা করার জন্য।
কর্নস্টালক

4
এই সিপিইউ সময় এবং প্রাচীর সময় না পরিমাপ করে না?
krs013

27

আমি সবসময় ক্লক_মোনটোনিক ক্লক থেকে সময় ফিরিয়ে ক্লক_জেটটাইম () ফাংশনটি ব্যবহার করি। অতীত কিছু অনির্দিষ্ট পয়েন্ট যেমন, যুগের সিস্টেম প্রারম্ভের মতো কিছু সময়, নির্দিষ্ট সময়, সেকেন্ড এবং ন্যানোসেকেন্ডে ফিরে আসার সময়।

#include <stdio.h>
#include <stdint.h>
#include <time.h>

int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
  return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
           ((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}

int main(int argc, char **argv)
{
  struct timespec start, end;
  clock_gettime(CLOCK_MONOTONIC, &start);

  // Some code I am interested in measuring 

  clock_gettime(CLOCK_MONOTONIC, &end);

  uint64_t timeElapsed = timespecDiff(&end, &start);
}

5
ক্লক_জেটটাইম () এএনএসআই সি নয়
পাওয়ার অ্যাপ্লিকেশন 1

1
এছাড়াও CLOCK_MONOTONIC অনেক সিস্টেমে প্রয়োগ করা হয় না (অনেকগুলি লিনাক্স প্ল্যাটফর্ম সহ)।
ডিপস্টিক

2
@ পাওয়ারএপ 1010 এটি করার কোনও ভাল / শক্তিশালী এএনএসআই সি উপায় নেই। অন্যান্য উত্তরগুলির অনেকগুলি এএনসিআই সি এর চেয়ে পোসিক্সের উপর নির্ভর করে যা বলা হচ্ছে, আমি আজকে বিশ্বাস করি। @ ডিপস্টিক টুডে, আমি বিশ্বাস করি বেশিরভাগ আধুনিক প্ল্যাটফর্মগুলি [উদ্ধৃতি প্রয়োজন] সমর্থন clock_gettime(CLOCK_MONOTONIC, ...)এবং এখানে বৈশিষ্ট্য পরীক্ষার ম্যাক্রোও রয়েছে _POSIX_MONOTONIC_CLOCK
omninonsense

22

একটি পোর্টেবল সমাধান কার্যকর করা হচ্ছে

এখানে যেমন আগেই উল্লেখ করা হয়েছিল যে সময় পরিমাপ সমস্যার জন্য যথাযথ নির্ভুলতার সাথে কোনও যথাযথ এএনএসআই সমাধান নেই, আমি কীভাবে পোর্টেবল পাব এবং কীভাবে সম্ভব, একটি উচ্চ-রেজোলিউশনের সময় পরিমাপ সমাধানের উপায়গুলি সম্পর্কে লিখতে চাই।

একঘেয়ে ঘড়ি বনাম টাইম স্ট্যাম্প

সাধারণভাবে বলতে গেলে সময় পরিমাপের দুটি উপায় রয়েছে:

  • একঘেয়ে ঘড়ি;
  • বর্তমান (তারিখ) সময় স্ট্যাম্প।

প্রথমটি একঘেয়ে ঘড়ি কাউন্টার ব্যবহার করে (কখনও কখনও এটি টিক কাউন্টারও বলা হয়) যা পূর্বনির্ধারিত ফ্রিকোয়েন্সি সহ টিক্স গণনা করে, তাই যদি আপনার টিক্সের মান থাকে এবং ফ্রিকোয়েন্সিটি জানা যায়, আপনি টিক্সকে সহজেই অতিবাহিত সময়ে রূপান্তর করতে পারবেন। এটি আসলে কোনও গ্যারান্টিযুক্ত নয় যে কোনও একঘেয়ে ঘড়ি বর্তমান সিস্টেম সময়কে যে কোনও উপায়ে প্রতিবিম্বিত করে, এটি সিস্টেম শুরুর পর থেকে টিকগুলিও গণনা করতে পারে। তবে এটি গ্যারান্টি দেয় যে সিস্টেমের অবস্থা নির্বিশেষে একটি ঘড়ি বর্ধমান ফ্যাশনে সর্বদা চালিত হয়। সাধারণত ফ্রিকোয়েন্সি একটি হার্ডওয়্যার উচ্চ-রেজোলিউশন উত্সের সাথে আবদ্ধ থাকে, এ কারণেই এটি একটি উচ্চ নির্ভুলতা সরবরাহ করে (হার্ডওয়ারের উপর নির্ভর করে, তবে বেশিরভাগ আধুনিক হার্ডওয়্যারকে হাই-রেজোলিউশন ক্লক সোর্সগুলির সাথে কোনও সমস্যা নেই)।

দ্বিতীয় উপায়টি বর্তমান সিস্টেম ঘড়ির মানের উপর ভিত্তি করে একটি (তারিখ) সময় মান সরবরাহ করে। এটির একটি উচ্চ রেজোলিউশনও থাকতে পারে তবে এর একটি বড় ত্রুটি রয়েছে: এই জাতীয় সময় মান বিভিন্ন সিস্টেম টাইম অ্যাডজাস্টমেন্ট দ্বারা প্রভাবিত হতে পারে, যেমন সময় অঞ্চল পরিবর্তন, দিবালোক সংরক্ষণ সময় (ডিএসটি) পরিবর্তন, এনটিপি সার্ভার আপডেট, সিস্টেম হাইবারনেশন এবং তাই চালু. কিছু পরিস্থিতিতে আপনি একটি নেতিবাচক অতিবাহিত সময় মূল্য পেতে পারেন যা একটি অপরিজ্ঞাত আচরণের দিকে পরিচালিত করতে পারে। আসলে এই জাতীয় সময় উত্সটি প্রথমটির চেয়ে কম নির্ভরযোগ্য।

সুতরাং সময় ব্যবধান পরিমাপের প্রথম নিয়ম হ'ল সম্ভব হলে একঘেয়ে ঘড়ি ব্যবহার করা। এটিতে একটি উচ্চ নির্ভুলতা থাকে এবং এটি নকশা দ্বারা নির্ভরযোগ্য।

ফলব্যাক কৌশল

পোর্টেবল সমাধানটি প্রয়োগ করার সময় একটি ফ্যালব্যাক কৌশল বিবেচনা করা উচিত: যদি উপলব্ধ থাকে তবে একরোটিক ঘড়ি ব্যবহার করুন এবং সিস্টেমে কোনও একঘেয়ে ঘড়ি না থাকলে টাইম স্ট্যাম্পগুলির কাছে ফ্যালব্যাক পাওয়া যায়।

উইন্ডোজ

উইন্ডোজে সময় পরিমাপ সম্পর্কে এমএসডিএন - তে উচ্চ-রেজোলিউশনের টাইম স্ট্যাম্পগুলি অর্জন করার নামে একটি দুর্দান্ত নিবন্ধ রয়েছে যা সফ্টওয়্যার এবং হার্ডওয়্যার সমর্থন সম্পর্কে আপনার প্রয়োজনীয় সমস্ত বিবরণ বর্ণনা করে। উইন্ডোজে উচ্চ নির্ভুলতার জন্য স্ট্যাম্প অর্জন করার জন্য আপনার উচিত:

  • কোয়েরি পারফরম্যান্স ফ্রিকোয়েন্সি সহ টাইমার ফ্রিকোয়েন্সি (প্রতি সেকেন্ডে টিক্স) জিজ্ঞাসা করুন :

    LARGE_INTEGER tcounter;
    LARGE_INTEGER freq;    
    
    if (QueryPerformanceFrequency (&tcounter) != 0)
        freq = tcounter.QuadPart;

    টাইম ফ্রিকোয়েন্সি সিস্টেম বুটে স্থির করা হয়েছে যাতে আপনার এটি একবারে নেওয়া দরকার।

  • কোয়েরি পারফরম্যান্স কাউন্টার দিয়ে বর্তমান টিক্স মানটি জিজ্ঞাসা করুন :

    LARGE_INTEGER tcounter;
    LARGE_INTEGER tick_value;
    
    if (QueryPerformanceCounter (&tcounter) != 0)
        tick_value = tcounter.QuadPart;
  • বিচ্ছিন্ন সময়গুলিতে টিক্সগুলি স্কেল করুন, অর্থাৎ মাইক্রোসেকেন্ডগুলিতে:

    LARGE_INTEGER usecs = (tick_value - prev_tick_value) / (freq / 1000000);

মাইক্রোসফ্টের মতে আপনার উইন্ডোজ এক্সপি এবং বেশিরভাগ ক্ষেত্রে পরবর্তী সংস্করণগুলিতে এই পদ্ধতির সাথে কোনও সমস্যা নেই। তবে আপনি উইন্ডোজটিতে দুটি ফ্যালব্যাক সমাধান ব্যবহার করতে পারেন:

  • সিস্টেমটি শুরু হওয়ার পর থেকে গেটটিকাউন্টটি মিলিসেকেন্ডগুলির সংখ্যা সরবরাহ করে যা কেটে গেছে। এটি প্রতি 49.7 দিন মোড়ানো হয়, তাই দীর্ঘ বিরতি পরিমাপে সতর্কতা অবলম্বন করুন।
  • গেটটিকাউন্ট 64 একটি 64-বিট সংস্করণ GetTickCount, তবে এটি উইন্ডোজ ভিস্তা এবং তারপরের থেকে শুরু করে উপলভ্য।

ওএস এক্স (ম্যাকোস)

ওএস এক্স (ম্যাকোস) এর নিজস্ব ম্যাক পরম সময় ইউনিট রয়েছে যা একঘেয়ে ঘড়ি উপস্থাপন করে। আরম্ভ করার সর্বোত্তম উপায় হ'ল অ্যাপল এর নিবন্ধটি প্রযুক্তিগত প্রশ্নোত্তর QA1398: ম্যাক পরম সময় ইউনিট যা বর্ণনা করে (কোড উদাহরণ সহ) একঘেয়ে টিকগুলি পাওয়ার জন্য মাচ-নির্দিষ্ট এপিআই কীভাবে ব্যবহার করবেন। এটি সম্পর্কে ম্যাক ওএস এক্স-এর ক্লক_জেটটাইম বিকল্প হিসাবে স্থানীয় একটি প্রশ্ন রয়েছে যা শেষে আপনাকে সম্ভাব্য মান ওভারফ্লো নিয়ে কী করতে হবে তা কিছুটা বিভ্রান্ত করতে পারে কারণ কাউন্টার ফ্রিকোয়েন্সিটি সংখ্যার এবং ডিনোমিনেটরের আকারে ব্যবহৃত হয়। সুতরাং, কীভাবে সময় কাটানো যায় তার একটি ছোট উদাহরণ:

  • ঘড়ির ফ্রিকোয়েন্সি সংখ্যার এবং ডিনোমিনেটর পান:

    #include <mach/mach_time.h>
    #include <stdint.h>
    
    static uint64_t freq_num   = 0;
    static uint64_t freq_denom = 0;
    
    void init_clock_frequency ()
    {
        mach_timebase_info_data_t tb;
    
        if (mach_timebase_info (&tb) == KERN_SUCCESS && tb.denom != 0) {
            freq_num   = (uint64_t) tb.numer;
            freq_denom = (uint64_t) tb.denom;
        }
    }

    আপনার এটি একবারেই করা দরকার।

  • বর্তমান টিক মানটি এর সাথে জিজ্ঞাসা করুন mach_absolute_time:

    uint64_t tick_value = mach_absolute_time ();
  • বিগত সময়গুলিতে টিক্সগুলি স্কেল করুন, অর্থাৎ মাইক্রোসেকেন্ডগুলিতে, পূর্বের অনুসন্ধানী সংখ্যা এবং ডিনোমিনেটর ব্যবহার করে:

    uint64_t value_diff = tick_value - prev_tick_value;
    
    /* To prevent overflow */
    value_diff /= 1000;
    
    value_diff *= freq_num;
    value_diff /= freq_denom;

    একটি ওভারফ্লো রোধ করার মূল ধারণাটি হল অঙ্কগুলি এবং ডিনোমিনেটর ব্যবহারের আগে টিক্সকে পছন্দসই নির্ভুলতার জন্য স্কেল করা। প্রাথমিক টাইমার রেজোলিউশন যেমন ন্যানোসেকেন্ডে রয়েছে, তাই আমরা 1000মাইক্রোসেকেন্ডগুলি পেতে এর দ্বারা বিভাজন করি । আপনি ক্রোমিয়ামের সময়_ম্যাক.সি . তে একই পদ্ধতি ব্যবহার করতে পারেন । আপনার যদি সত্যিই ন্যানোসেকেন্ডের নির্ভুলতার প্রয়োজন হয় তবে আমি কীভাবে উপচে না পড়ে mach_absolve_Time ব্যবহার করতে পারি?

লিনাক্স এবং ইউনিক্স

clock_gettimeকলে যেকোনো POSIX বান্ধব সিস্টেমে আপনার ভাল উপায়। এটি বিভিন্ন ঘড়ির উত্স থেকে সময় জিজ্ঞাসা করতে পারে এবং আমাদের যা প্রয়োজন তা হ'ল CLOCK_MONOTONIC। সমস্ত সিস্টেম যা clock_gettimeসমর্থন করে না CLOCK_MONOTONIC, তাই আপনাকে প্রথমে যা করতে হবে তা হ'ল তার উপলভ্যতা যাচাই করা:

  • যদি _POSIX_MONOTONIC_CLOCKকোনও মানকে সংজ্ঞায়িত করা হয় >= 0তবে এর অর্থ এটি CLOCK_MONOTONICউপলব্ধ;
  • যদি এটির _POSIX_MONOTONIC_CLOCKসংজ্ঞা দেওয়া হয় 0তার অর্থ এটি রানটাইম এ কাজ করে কিনা তা অতিরিক্তভাবে আপনার পরীক্ষা করা উচিত, আমি ব্যবহার করার পরামর্শ দিই sysconf:

    #include <unistd.h>
    
    #ifdef _SC_MONOTONIC_CLOCK
    if (sysconf (_SC_MONOTONIC_CLOCK) > 0) {
        /* A monotonic clock presents */
    }
    #endif
  • অন্যথায় একটি একঘেয়ে ঘড়ি সমর্থিত নয় এবং আপনার ফ্যালব্যাক কৌশল ব্যবহার করা উচিত (নীচে দেখুন)।

এর ব্যবহার clock_gettimeবেশ সোজা এগিয়ে রয়েছে:

  • সময় মান পেতে:

    #include <time.h>
    #include <sys/time.h>
    #include <stdint.h>
    
    uint64_t get_posix_clock_time ()
    {
        struct timespec ts;
    
        if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0)
            return (uint64_t) (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
        else
            return 0;
    }

    আমি এখানে মাইক্রোসেকেন্ডে সময় কমিয়ে আছি।

  • পূর্ববর্তী সময় মানের সাথে একইভাবে প্রাপ্ত পার্থক্যের গণনা করুন:

    uint64_t prev_time_value, time_value;
    uint64_t time_diff;
    
    /* Initial time */
    prev_time_value = get_posix_clock_time ();
    
    /* Do some work here */
    
    /* Final time */
    time_value = get_posix_clock_time ();
    
    /* Time difference */
    time_diff = time_value - prev_time_value;

gettimeofdayকলটি ব্যবহার করা সবচেয়ে ভাল ফ্যালব্যাক কৌশল : এটি একঘেয়ে নয়, তবে এটি বেশ ভাল রেজোলিউশন সরবরাহ করে। ধারণাটি একই সাথে clock_gettimeতবে একটি সময় মূল্য পেতে আপনার উচিত:

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

uint64_t get_gtod_clock_time ()
{
    struct timeval tv;

    if (gettimeofday (&tv, NULL) == 0)
        return (uint64_t) (tv.tv_sec * 1000000 + tv.tv_usec);
    else
        return 0;
}

আবার, সময়ের মানটি মাইক্রোসেকেন্ডগুলিতে কমিয়ে দেওয়া হয়।

এসজিআই আইআরএক্স

IRIX ব্যবহৃত হয়েছে clock_gettimeকল, কিন্তু এটা অভাব আছে CLOCK_MONOTONIC। এর পরিবর্তে এটা নিজস্ব একঘেয়ে ঘড়ি উৎস সংজ্ঞায়িত হয়েছে CLOCK_SGI_CYCLEযা আপনি পরিবর্তে ব্যবহার করা উচিত CLOCK_MONOTONICসঙ্গে clock_gettime

সোলারিস এবং এইচপি-ইউএক্স

সোলারিসের নিজস্ব উচ্চ-রেজোলিউশন টাইমার ইন্টারফেস রয়েছে gethrtimeযা ন্যানোসেকেন্ডে বর্তমান টাইমার মান প্রদান করে। সোলারিসের নতুন সংস্করণগুলি থাকতে পারে clock_gettime, আপনার gethrtimeযদি পুরানো সোলারিস সংস্করণগুলি সমর্থন করার প্রয়োজন হয় তবে আপনি আটকে থাকতে পারেন।

ব্যবহার সহজ:

#include <sys/time.h>

void time_measure_example ()
{
    hrtime_t prev_time_value, time_value;
    hrtime_t time_diff;

    /* Initial time */
    prev_time_value = gethrtime ();

    /* Do some work here */

    /* Final time */
    time_value = gethrtime ();

    /* Time difference */
    time_diff = time_value - prev_time_value;
}

এইচপি-ইউএক্সের অভাব রয়েছে clock_gettimeতবে এটি gethrtimeআপনাকে সমর্থন করে যা সোলারিসের মতো একইভাবে ব্যবহার করা উচিত।

BeOS

বিওএসের নিজস্ব উচ্চ-রেজোলিউশন টাইমার ইন্টারফেস রয়েছে system_timeযা কম্পিউটার বুট হওয়ার পরে মাইক্রোসেকেন্ডগুলির সংখ্যা কেটে গেছে returns

ব্যবহারের উদাহরণ:

#include <kernel/OS.h>

void time_measure_example ()
{
    bigtime_t prev_time_value, time_value;
    bigtime_t time_diff;

    /* Initial time */
    prev_time_value = system_time ();

    /* Do some work here */

    /* Final time */
    time_value = system_time ();

    /* Time difference */
    time_diff = time_value - prev_time_value;
}

ওএস / 2

উচ্চ-নির্ভুল সময়ের স্ট্যাম্পগুলি পুনরুদ্ধার করতে ওএস / 2 এর নিজস্ব এপিআই রয়েছে:

  • DosTmrQueryFreq(জিসিসি সংকলকের জন্য ) সহ টাইমার ফ্রিকোয়েন্সি (প্রতি ইউনিট টিক্স) জিজ্ঞাসা করুন :

    #define INCL_DOSPROFILE
    #define INCL_DOSERRORS
    #include <os2.h>
    #include <stdint.h>
    
    ULONG freq;
    
    DosTmrQueryFreq (&freq);
  • বর্তমান টিক্সের মানটি এখানে জিজ্ঞাসা করুন DosTmrQueryTime:

    QWORD    tcounter;
    unit64_t time_low;
    unit64_t time_high;
    unit64_t timestamp;
    
    if (DosTmrQueryTime (&tcounter) == NO_ERROR) {
        time_low  = (unit64_t) tcounter.ulLo;
        time_high = (unit64_t) tcounter.ulHi;
    
        timestamp = (time_high << 32) | time_low;
    }
  • বিচ্ছিন্ন সময়গুলিতে টিক্সগুলি স্কেল করুন, অর্থাৎ মাইক্রোসেকেন্ডগুলিতে:

    uint64_t usecs = (prev_timestamp - timestamp) / (freq / 1000000);

উদাহরণ বাস্তবায়ন

আপনি প্লবসিস গ্রন্থাগারটি একবার দেখে নিতে পারেন যা উপরে বর্ণিত সমস্ত কৌশল বাস্তবায়িত করে (বিশদ বিবরণের জন্য পিটিটাইম প্রোফাইল * .সি দেখুন)।


C11 আছে: "সেখানে সময় পরিমাপ সমস্যার জন্য যথেষ্ট স্পষ্টতা সঙ্গে কোন সঠিক ANSI সমাধান" timespec_get: stackoverflow.com/a/36095407/895245
সিরো Santilli郝海东冠状病六四事件法轮功

1
কোড প্রয়োগের সময় পরিমাপ করার জন্য এটি এখনও একটি ভুল উপায়। timespec_getএকঘেয়ে না।
আলেকজান্ডার সাপ্রিনকিন

11

timespec_get সি 11 থেকে

বাস্তবায়নের রেজোলিউশনে গোল করে ন্যানোসেকেন্ডে ফিরে আসে।

POSIX 'থেকে একটি এএনএসআই রিপফের মতো মনে হচ্ছে clock_gettime

উদাহরণ: printfউবুন্টু 15.10 এ প্রতি 100 মিমি একটি করা হয়:

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

static long get_nanos(void) {
    struct timespec ts;
    timespec_get(&ts, TIME_UTC);
    return (long)ts.tv_sec * 1000000000L + ts.tv_nsec;
}

int main(void) {
    long nanos;
    long last_nanos;
    long start;
    nanos = get_nanos();
    last_nanos = nanos;
    start = nanos;
    while (1) {
        nanos = get_nanos();
        if (nanos - last_nanos > 100000000L) {
            printf("current nanos: %ld\n", nanos - start);
            last_nanos = nanos;
        }
    }
    return EXIT_SUCCESS;
}

C11 N1570 মান খসড়া 7.27.2.5 "timespec_get ফাংশন বলছেন":

যদি বেসটি TIME_UTC হয়, তবে টিভি_সেস্ক সদস্যটি নির্ধারিত সময় থেকে একটি নির্ধারিত সময়কে সেকেন্ডের সংখ্যায় সেট করা হয়, পুরো মান হিসাবে কেটে যায় এবং টিভি_এনএসসি সদস্য ন্যানোসেকেন্ডের অবিচ্ছেদ্য সংখ্যায় সেট করা হয়, এটি সিস্টেম ঘড়ির রেজোলিউশনের জন্য গোলাকার হয়। (321)

321) যদিও স্ট্রাক্ট টাইমস্পেক অবজেক্টটি ন্যানোসেকেন্ড রেজোলিউশনের সাথে সময়ের বর্ণনা দেয়, উপলব্ধ রেজোলিউশনটি সিস্টেম নির্ভর এবং এমনকি এটি 1 সেকেন্ডেরও বেশি হতে পারে।

সি ++ ১১ টিও পেয়েছে std::chrono::high_resolution_clock: সি ++ ক্রস-প্ল্যাটফর্ম হাই রেজোলিউশন টাইমার

glibc 2.21 বাস্তবায়ন

এর অধীনে পাওয়া যাবে sysdeps/posix/timespec_get.c:

int
timespec_get (struct timespec *ts, int base)
{
  switch (base)
    {
    case TIME_UTC:
      if (__clock_gettime (CLOCK_REALTIME, ts) < 0)
        return 0;
      break;

    default:
      return 0;
    }

  return base;
}

খুব স্পষ্ট:

  • শুধুমাত্র TIME_UTCবর্তমানে সমর্থিত

  • এটি এগিয়ে যায় __clock_gettime (CLOCK_REALTIME, ts), যা একটি পসিক্স এপিআই: http://pubs.opengroup.org/onlinepubs/9699919799/funitions/ ॉक_ getres.html

    লিনাক্স x86-64 এর একটি clock_gettimeসিস্টেম কল রয়েছে।

    মনে রাখবেন যে এটি একটি ব্যর্থ-প্রমাণ মাইক্রো-বেঞ্চমার্কিং পদ্ধতি নয় কারণ:

    • man clock_gettimeবলেছে যে আপনার প্রোগ্রামটি চলাকালীন আপনি যদি কিছু সিস্টেমের সময় সেটিংস পরিবর্তন করেন তবে এই পদক্ষেপের বিচ্ছিন্নতা থাকতে পারে। এটি অবশ্যই একটি বিরল ঘটনা হওয়া উচিত এবং আপনি এটিকে উপেক্ষা করতে সক্ষম হতে পারেন।

    • এটি প্রাচীরের সময় পরিমাপ করে, সুতরাং যদি শিডিয়ুলার আপনার কাজটি ভুলে যাওয়ার সিদ্ধান্ত নেয় তবে এটি বেশি দিন চলবে।

    এই কারণগুলির জন্য getrusage()মাইক্রোসেকেন্ড সর্বাধিক যথাযথতা কম হওয়া সত্ত্বেও আরও ভাল পসিক্স বেঞ্চমার্কিং সরঞ্জাম হতে পারে।

    আরও তথ্যে: লিনাক্সে সময় পরিমাপ করুন - সময় বনাম ঘড়ি বনাম গেরুসেজ বনাম ক্লক_সেটটাইম বনাম গেটটাইম ডে বনাম টাইমস্পেক_জেট?


এটি 2017 এর সঠিক উত্তর, এমনকি এমএসভিসিরও এই ফাংশন রয়েছে; বেঞ্চমার্কিংয়ের পরিপ্রেক্ষিতে এমন কিছু সন্ধান করুন যা চিপ রেজিস্টার (পিটি এক্সটেনশন সহ এক্স 86 প্রসেসরের নতুন সংস্করণ এবং লিনাক্স কার্নেল / পারফ সম্পর্কিত নতুন সংস্করণ)

4

আপনি সম্ভবত সর্বোত্তম নির্ভুলতা পেতে পারেন x86- কেবল "rdtsc" নির্দেশের ব্যবহারের মাধ্যমে, যা ক্লক-লেভেল রেজোলিউশন সরবরাহ করতে পারে (অবশ্যই অবশ্যই rdtsc কলের মূল্য বিবেচনা করা উচিত, যা সহজেই পরিমাপ করা যেতে পারে অ্যাপ্লিকেশন সূচনা)।

এখানে প্রধান ধরাটি প্রতি সেকেন্ডে ঘড়ির সংখ্যা পরিমাপ করছে, যা খুব বেশি শক্ত হওয়া উচিত নয়।


3
প্রসেসর সম্পর্কিত সম্পর্কে আপনারও উদ্বিগ্ন হওয়ার দরকার হতে পারে, কারণ কিছু মেশিনে আপনি একাধিক প্রসেসরের কাছে আরডিটিএসসি কল পাঠাতে পারেন এবং তাদের আরডিটিএসসি কাউন্টারগুলি সংহত নাও হতে পারে।
উইল ডিন

1
এবং তদ্ব্যতীত, কিছু প্রসেসরের একঘেয়েভাবে বাড়ানো টিএসসি নেই - ভাবেন পাওয়ার-সঞ্চয় মোডগুলি যা সিপিইউ ফ্রিকোয়েন্সি হ্রাস করে। খুব সংক্ষিপ্ত স্থানীয় সময় নির্ধারণের জন্য আরডিটিএসসি ব্যবহার করা খুব খারাপ ধারণা।
স্নেমার্চ

বিটিডব্লিউ, @ উইলডিয়ান দ্বারা উল্লিখিত কোর ড্রিফট এবং টাইমিংয়ের জন্য আরডিটিএসসি ব্যবহারের কারণে বেশ কয়েকটি গেমগুলি (প্রারম্ভিক?) মাল্টি-কোর এএমডি 64 সিপিইউতে কাজ করতে ব্যর্থ হয়েছিল - আমাকে আমার এক্স 2 4400+ এর জন্য একক-কোর সখ্যতা সীমাবদ্ধ করতে হয়েছিল শিরোনাম একটি সংখ্যা।
স্নেমারচ

2

স্বীকৃত উত্তরটি যথেষ্ট ভাল ut তবে আমার সমাধানটি আরও সহজ I

Alse ব্যবহার gettimeofday, tv_secদ্বিতীয় অংশ, এবং tv_usecহয় মাইক্রোসেকেন্ড , না মিলিসেকেন্ড

long currentTimeMillis() {
  struct timeval time;
  gettimeofday(&time, NULL);

  return time.tv_sec * 1000 + time.tv_usec / 1000;
}

int main() {
  printf("%ld\n", currentTimeMillis());
  // wait 1 second
  sleep(1);
  printf("%ld\n", currentTimeMillis());
  return 0;
 }

এটি মুদ্রণ:

1522139691342 1522139692342ঠিক এক সেকেন্ড


-4

উইন্ডোজ অধীনে:

SYSTEMTIME t;
GetLocalTime(&t);
swprintf_s(buff, L"[%02d:%02d:%02d:%d]\t", t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);

1
অনুরোধ অনুসারে এই আনসি সি?
জিওম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.