সি ++ লিনাক্সে মিলিসেকেন্ড সময় অর্জন - ঘড়ি () সঠিকভাবে কাজ করছে বলে মনে হয় না


102

উইন্ডোজে, clock()সময়টি মিলি সেকেন্ডে ফেরত দেয়, তবে এই লিনাক্স বাক্সে আমি কাজ করছি এটি এটি নিকটতম 1000 এ পরিণত হয় যাতে নির্ভুলতা কেবল "দ্বিতীয়" স্তরের হয়, মিলিসেকেন্ডের স্তরে নয়।

আমি QTimeক্লাসটি ব্যবহার করে কিউটিটি দিয়ে একটি সমাধান পেয়েছি , কোনও বস্তুকে তাত্ক্ষণিকভাবে কল start()করেছিলাম এবং তারপরে কল করে তারপরে কল পেয়েছিলাম elapsed()মিলিসেকেন্ডের সংখ্যাটি ব্যয় করতে get

আমি এক ধরণের ভাগ্যবান হয়েছি কারণ আমি Qt এর সাথে কাজ করতে শুরু করছি, তবে আমি এমন একটি সমাধান চাই যা তৃতীয় পক্ষের লাইব্রেরিতে নির্ভর না করে,

এটি করার কোনও মানক উপায় নেই?

হালনাগাদ

বুস্ট সুপারিশ করবেন না দয়া করে ..

যদি বুস্ট এবং কিউটি এটি করতে পারে তবে অবশ্যই এটি যাদু নয়, এমন কিছু মানক থাকতে হবে যা তারা ব্যবহার করছে!


2
সম্পাদনা সম্পর্কে - তবে পোর্টেবল উপায়ে এটি করা কিছুটা ব্যথা।
বেনামে

উত্তর:


37

আপনি আপনার পদ্ধতির শুরু এবং শেষে গেটটাইম ডে ব্যবহার করতে পারেন এবং তারপরে দুটি রিটার্ন স্ট্রাকের মধ্যে পার্থক্য করতে পারেন। আপনি নিম্নলিখিতগুলির মতো কাঠামো পাবেন:

struct timeval {
  time_t tv_sec;
  suseconds_t tv_usec;
}

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

সম্পাদনা: অন্য কেউ মন্তব্য করেছেন যে আপনি আধুনিক সি ++ স্ট্যান্ডার্ড :: ক্রোনো :: হাই_রেসোলিউশন_ ক্লক দিয়েও ব্যবহার করতে পারেন, তবে এটি একঘেয়ে হওয়ার গ্যারান্টিযুক্ত নয়। পরিবর্তে স্থির_ঘড়ি ব্যবহার করুন।


38
গুরুতর কাজের জন্য ভয়ানক। বছরে দু'বার বড় সমস্যাগুলি, যখন কেউ তারিখ করে এবং অবশ্যই এনটিপি সিঙ্ক করে। ক্লক_জেটটাইম (CLOCK_MONOTONIC,) ব্যবহার করুন
অ্যান্ড্রুস্টোন

9
@ অ্যান্ড্রুস্টোন: ইউনিক্স সময় বছরে দুবার পরিবর্তন হয় না। বা এমনকি বছরে একবার। তবে, হ্যাঁ, 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
@ কম্পিউটার গুরু, ইতিবাচক মূল্যবোধকে গোল করার জন্য এটি একটি সাধারণ কৌশল। মানটি যখন একটি পূর্ণসংখ্যার মানকে ছেঁটে ফেলা হয়, ০.০ থেকে ০.৪৯৯৯৯ এর মধ্যে কিছু ... সংযোজনের আগে ০ থেকে কমিয়ে দেওয়ার আগে এবং ০.০ এবং ০.৯৯৯৯৯ এর মধ্যে ... ১ কেটে ছাড়ে
মার্ক র্যানসোম

8
টিভি_উসেকটি মিলিসেকেন্ড নয়, এটি মাইক্রোসেকেন্ডস।
নেবুলাফক্স

13
গুরুতর কাজের জন্য ভয়ানক। বছরে দু'বার বড় ইস্যু, যখন কেউ তারিখ করে - এবং অবশ্যই এনটিপি সিঙ্ক করে
অ্যান্ড্রুস্টোন

14
@ অ্যান্ড্রুস্টোন ঠিক আছে, একই কম্পিউটারে সময়ের তুলনা করতে ক্লক_জেটটাইম (2) ব্যবহার করুন CLOCK_REALTIME এর সাথে। Gettimeofday থেকে (2) র manpage: 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

কারণ আমরা যা করেছি তা ঘুমিয়ে ছিল এবং কোনও সিপিইউ সময় ব্যবহার করে না! তবে, 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ফাংশনটি ব্যবহার করে বিবেচনা করতে পারেন ।


Mention সম্পর্কে একটি উল্লেখ করার জন্য sleep()- আমি ইতিমধ্যে একটি প্রশ্ন জিজ্ঞাসা করার জন্য ভাবছি (কেন এটি আমার ব্যতীত সকলের পক্ষে ভাল কাজ করে?!) , যখন আপনার উত্তর পাওয়া গেল।
হাই-এঞ্জেল

18

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

  • সি ++ 0 এক্স স্ট্যান্ডার্ড লাইব্রেরির সময় উপযোগিতা সহ:
    • ক্লাস টেম্পলেট duration
    • ক্লাস টেম্পলেট time_point
    • ঘড়ি:
      • system_clock
      • monotonic_clock
      • high_resolution_clock
  • timerটাইপডেফ সহ ক্লাস টেম্পলেট :
    • system_timer
    • monotonic_timer
    • high_resolution_timer
  • প্রক্রিয়া ঘড়ি এবং টাইমার:
    • process_clock, বাস্তব, ব্যবহারকারী-সিপিইউ এবং সিস্টেম-সিপিইউ সময়গুলি ক্যাপচার করছে।
    • process_timer, অতিবাহিত বাস্তব, ব্যবহারকারী-সিপিইউ এবং সিস্টেম-সিপিইউ সময়গুলি ক্যাপচার করছে।
    • run_timer, প্রক্রিয়াজাতকরণের সুবিধাজনক প্রতিবেদন ফলাফল নেই।
  • সি ++ 0 এক্স স্ট্যান্ডার্ড লাইব্রেরির সংকলন-সময় যৌক্তিক পাটিগণিত।

বৈশিষ্ট্য তালিকার উত্স এখানে


আপাতত আপনি বুস্ট টাইমারটি ব্যবহার করতে পারেন এবং তারপরে পর্যালোচনা / স্বীকৃত হয়ে ক্রেণো ক্রোনোতে স্থানান্তরিত করতে পারেন।
বেনামে

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
এটি দুর্দান্ত তবে "এনসেকেন্ডস" বিভ্রান্ত করছে কারণ সময়কাল ন্যানোসেকেন্ডগুলি ধরে রাখে না, এটি মাইক্রোসেকেন্ডগুলি ধারণ করে, তাই আমি লোকদের এই "ইউজকন্ডস" বলার পরামর্শ দেব।
pho0

ধন্যবাদ। সংশোধন করা হয়েছে।
ক্রিস রেডফোর্ড

9

পুরানো ইউনিক্সগুলিতে পোর্টেবল হওয়ার জন্য যদি আপনার কোডের প্রয়োজন না হয় তবে আপনি ক্লক_জেটটাইম () ব্যবহার করতে পারেন, যা আপনাকে ন্যানোসেকেন্ডে সময় দেবে (যদি আপনার প্রসেসর সেই রেজোলিউশন সমর্থন করে)। এটি পসিক্স, তবে ২০০১ সাল থেকে।


4

ঘড়ির () প্রায়শই বেশ লম্পট রেজোলিউশন থাকে। আপনি যদি মিলিসেকেন্ড পর্যায়ে সময়টি পরিমাপ করতে চান তবে এই বিকল্পটিতে বর্ণিত হিসাবে ক্লক_জেটটাইম () ব্যবহার করার একটি বিকল্প হ'ল

(মনে রাখবেন যে আপনাকে লিনাক্সে -lrt এর সাথে লিঙ্ক করতে হবে)।


4

সি ++ 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 দ্বারা বিভাজন করছি , তবে এটি অর্থহীন কারণ রেজুলেশনটি কেবল দ্বিতীয়ের চেয়ে কম রয়েছে
হেসেন

ভাল পরিষ্কার করা, ইউনিট হয় মাইক্রোসেকেন্ড (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

clockপসআইএক্স স্ট্যান্ডার্ডে তার রিটার্নের মানটি CLOCKS_PER_SEC চিহ্নের সাথে সংজ্ঞায়িত করা হয়েছে এবং কোনও বাস্তবায়ন যে কোনও সুবিধাজনক ফ্যাশনে এটি সংজ্ঞায়িত করতে বিনামূল্যে। লিনাক্সের অধীনে, আমি times()ফাংশনটি দিয়ে শুভ কামনা করেছি ।


1

গেটটাইমডে - সমস্যাটি হ'ল যদি আপনি হার্ডওয়ার ক্লক পরিবর্তন করেন তবে নিম্ন মানের মান থাকতে পারে (উদাহরণস্বরূপ এনটিপি সহ) বুস্ট - এই প্রকল্পের ঘড়ির জন্য উপলব্ধ নয় () - সাধারণত একটি 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

লিনাক্স এ থাকাকালীন এটি বর্তমান প্রক্রিয়া দ্বারা ব্যবহৃত কোরগুলিতে সিপিইউ সময় পরিমাপ করে

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

এবং (এটি প্রদর্শিত হবে এবং মূল পোস্টার দ্বারা উল্লিখিত) আসলে CLOCKS_PER_SEC এর চেয়ে কম নির্ভুলতা সহ, যদিও এটি লিনাক্সের নির্দিষ্ট সংস্করণে নির্ভর করে।


0

আমি গেটটাইম ডে () ব্যবহার না করার হোলা সয়া পদ্ধতিটি পছন্দ করি। এটি আমার চলমান সার্ভারে ঘটেছিল প্রশাসক সময় অঞ্চলটি পরিবর্তন করেছিলেন changed একই (সঠিক) স্থানীয় মানটি দেখানোর জন্য ঘড়িটি আপডেট করা হয়েছিল। এর ফলে ফাংশনের সময় () এবং গেটটাইমডে () 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-লুপ কর্তৃক গৃহীত মৃত্যুর কার্যকর সময়টি ট্র্যাক করা হয়। এই main()সময়টিতে মাল্টিটাস্কিংয়ের কারণে নির্বাহের প্রেক্ষাপটে স্যুইচিং এবং আউট করা অপারেটিং সিস্টেম অন্তর্ভুক্ত ।

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