Gettimeofday () মাইক্রোসেকেন্ড রেজোলিউশন হতে গ্যারান্টিযুক্ত?


97

আমি একটি গেম পোর্টিং করছি, যা মূলত উইন 32 এপিআইয়ের জন্য লিনাক্সে লেখা হয়েছিল (ভাল, উইন 32 পোর্টের ওএস এক্স পোর্টকে লিনাক্সে পোর্ট করা)।

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প্রোগ্রামটির শুরু হওয়ার পরে রয়েছে contains

তাহলে কি এই বহনযোগ্য? কার্নেলটি একটি নির্দিষ্ট উপায়ে বা এর মতো কিছু সংকলিত থাকলে আমি এটি আলাদাভাবে কাজ করতে চাই না। লিনাক্স ব্যতীত অন্য কোনও ক্ষেত্রে এটি বহনযোগ্য নয় বলে আমি ঠিক আছি।

উত্তর:


57

হতে পারে. তবে আপনার বড় সমস্যা রয়েছে। gettimeofday()আপনার সিস্টেমে টাইমার পরিবর্তন করার প্রক্রিয়া থাকলে (যেমন, এনটিপিডি) ভুল সময় নির্ধারণ করতে পারে। একটি "সাধারণ" লিনাক্সে, যদিও আমি বিশ্বাস করি যে এর রেজোলিউশন gettimeofday()10us is এটি আপনার সিস্টেমে চলমান প্রক্রিয়াগুলির ভিত্তিতে ফলস্বরূপ এবং পশ্চাদপসরণ এবং সময়কে লাফিয়ে উঠতে পারে। এটি কার্যকরভাবে আপনার নম্বর নং উত্তর দেয়।

আপনার clock_gettime(CLOCK_MONOTONIC)সময়সীমা অন্তর্ভুক্ত করা উচিত । মাল্টি-কোর সিস্টেম এবং বাহ্যিক ক্লক সেটিংসের মতো জিনিসের কারণে এটি বেশ কয়েকটি কম সমস্যার মধ্যে ভুগছে।

এছাড়াও, clock_getres()ফাংশনটি সন্ধান করুন।


4
ক্লক_জেটটাইম কেবলমাত্র নতুন লিনাক্সে উপস্থিত রয়েছে। অন্যান্য সিস্টেমে কেবল
গেটটাইম ডে

4
@ প্রাণবন্ত.ভি.সিচ এটি পসিক্স তাই এটি কেবল লিনাক্স এবং 'নতুনবাদী' নয়? এমনকি 'এন্টারপ্রাইজ' ডিগ্রোগুলি রেড হ্যাট এন্টারপ্রাইজ লিনাক্সের ভিত্তিতে 2.6.18 এর উপর ভিত্তি করে যার ক্লক_জেটটাইম রয়েছে তাই নয়, খুব নতুন নয় .. (আরএইচইএল-এ ম্যানপেজের তারিখ 2004-মার্চ -12 তাই কিছুক্ষণের জন্য হয়ে গেছে) যদি না আপনি সত্যিই বিস্মিত হওয়া পুরানো কার্নেলগুলি ডাব্লুটিএফ বলতে কি বোঝাতে চাইছেন?
স্পুড 86

ক্লক_জেটটাইম 2001-এ পসআইএক্স-এ অন্তর্ভুক্ত করা হয়েছিল currently যতদূর আমি জানি বর্তমানে ক্লিন_সেটটাইম () লিনাক্স ২.6 এবং কিউএনএক্সে প্রয়োগ করা হয়েছে। তবে লিনাক্স ২.৪ বর্তমানে অনেকগুলি উত্পাদন ব্যবস্থায় ব্যবহৃত হয়।
vitaly.v.ch

এটা তোলে 2001 সালে চালু করা হয়, কিন্তু POSIX পর্যন্ত বাধ্যতামূলক 2008. না
আর .. GitHub বন্ধ সাহায্য করা বরফ

4
লক_জেটটাইমের জন্য লিনাক্স এফকিউ থেকে (ডেভিড শ্লোসনাগলের উত্তর দেখুন) "ক্লক_মোনোটোনিক ... এনটিপি অ্যাডটাইমেক্স () এর মাধ্যমে সামঞ্জস্য করে is একেবারে সংশোধন করা হবে এবং হার্ডওয়্যার কাউন্টারগুলির সাথে লিনিয়ার পারস্পরিক সম্পর্ক থাকবে। " আমি মনে করি না যে _আরএডাব্লু ঘড়ি এটি কখনও কার্নেলের মধ্যে তৈরি করেছে (যদি এর নাম পরিবর্তন না করা হয়_এইচআর করা হয় তবে আমার গবেষণা থেকে বোঝা যাচ্ছে যে প্রচেষ্টাও ত্যাগ করা হবে)।
টনি ডেলরয়

41

উচ্চ রেজোলিউশন, ইনটেল প্রসেসরগুলির জন্য লো ওভারহেড সময়

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

মনে রাখবেন এটি সিপিইউ চক্রের সংখ্যা। লিনাক্সে আপনি সিপিইউ গতি / proc / cpuinfo থেকে পেতে পারেন এবং সেকেন্ডের সংখ্যা পেতে ভাগ করতে পারেন। এটিকে একটি দ্বিগুণ রূপান্তর করা বেশ সহজ।

আমি যখন এটি আমার বাক্সে চালাই, তখন আমি পাই

11867927879484732
11867927879692217
it took this long to call printf: 207485

এখানে ইন্টেল বিকাশকারীদের গাইড যা প্রচুর পরিমাণে বিশদ দেয়।

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

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);
}

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

12
কোর এবং তারপরের উপরের ইনটেল প্ল্যাটফর্মের টিএসসি একাধিক সিপিইউ এবং বর্ধনের উপর বিদ্যুৎ পরিচালনার রাজ্যগুলির থেকে পৃথক স্থির ফ্রিকোয়েনিতে সিঙ্ক্রোনাইজ করা হয় । ইন্টেল সফ্টওয়্যার বিকাশকারীর ম্যানুয়াল, খণ্ড দেখুন। 3 ধারা 18.10। তবে যে হারে কাউন্টার ইনক্রিমেন্টগুলি সিপিইউয়ের ফ্রিকোয়েন্সি হিসাবে একই নয় । "প্ল্যাটফর্মের সর্বাধিক সমাধানযোগ্য ফ্রিকোয়েন্সি, যা স্কেলযোগ্য বাস ফ্রিকোয়েন্সি এবং সর্বাধিক সমাধান হওয়া বাস অনুপাতের পণ্যের সমান" তে টিএসসি ইনক্রিমেন্টগুলি ইন্টেল সফটওয়্যার বিকাশকারীর ম্যানুয়াল, খণ্ড। 3 ধারা 18.18.5। আপনি সিপিইউর মডেল-নির্দিষ্ট রেজিস্টারগুলি (এমএসআর) থেকে এই মানগুলি পান।
26

7
আপনি সিপিইউর মডেল-নির্দিষ্ট রেজিস্টারগুলিকে (এমএসআর) জিজ্ঞাসা করে স্কেলেযোগ্য বাস ফ্রিকোয়েন্সি এবং সর্বাধিক সমাধান করা বাস অনুপাত পেতে পারেন: স্কেলযোগ্য বাস ফ্রিকোয়েন্সি == এমএসআর_এফএসবি_এফআরইউ [2: 0] আইডি 0xCD, সর্বাধিক সমাধান করা বাসের অনুপাত == এমএসআর_প্ল্যাটফরম_আইডি [12: 8] আইডি 0x17। নিবন্ধকের মানগুলি ব্যাখ্যা করতে ইন্টেল এসডিএম ভল্ট 3 পরিশিষ্ট B.1 এর সাথে পরামর্শ করুন। আপনি রেজিস্টারগুলিকে জিজ্ঞাসা করতে লিনাক্সে এমএসআর-সরঞ্জামগুলি ব্যবহার করতে পারেন। kernel.org/pub/linux/utils/cpu/msr-tools
সস্তার

4
CPUIDপ্রথম RDTSCনির্দেশের পরে এবং কোডটি বেঞ্চমার্ক করার পরে আপনার কোডটি আবার ব্যবহার করা উচিত নয় ? অন্যথায়, প্রথমে / সমান্তরাল-এর আগে RDTSCএবং এর ফলে RDTSCব- দ্বীপগুলিতে নিম্নরূপে উপস্থাপিত হওয়ার আগে বেঞ্চমার্ক কোডটি কী কার্যকর করা হবে ?
টনি ডেলরয়

18

@ বার্নার্ড:

আমাকে স্বীকার করতে হবে, আপনার বেশিরভাগ উদাহরণ সরাসরি আমার মাথার উপর দিয়ে গেল। এটি সংকলন করে, এবং কাজ করে বলে মনে হচ্ছে। এটি এসএমপি সিস্টেম বা স্পিডস্টেপের জন্য নিরাপদ?

এটি একটি ভাল প্রশ্ন ... আমি মনে করি কোড ঠিক আছে। ব্যবহারিক দৃষ্টিকোণ থেকে, আমরা এটি প্রতিদিন আমার সংস্থায় ব্যবহার করি এবং আমরা 2-8 কোর থেকে শুরু করে সমস্ত প্রশস্ত বক্সগুলিতে চলে। অবশ্যই, ওয়াইএমএমভি, ইত্যাদি, তবে এটি একটি নির্ভরযোগ্য এবং লো-ওভারহেড বলে মনে হচ্ছে (কারণ এটি সিস্টেম-স্পেসে প্রসঙ্গে স্যুইচ করে না) সময় পদ্ধতি।

সাধারণত এটি কীভাবে কাজ করে তা হল:

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

নির্দিষ্ট নোট:

  • আউট-অফ-অর্ডার এক্সিকিউশনটি ভুল ফলাফলের কারণ হতে পারে, সুতরাং আমরা "সিপিউইড" নির্দেশনাটি কার্যকর করি যা আপনাকে সিপিইউ সম্পর্কে কিছু তথ্য দেওয়ার পাশাপাশি কোনও আদেশ-বহির্ভূত নির্দেশনা কার্যকরকরণের সাথে সিঙ্ক্রোনাইজ করে।

  • বেশিরভাগ ওএসের সিপিইউতে যখন কাউন্টারগুলি শুরু হয় তখন তারা সিঙ্ক্রোনাইজ করে, তাই উত্তর কয়েক ন্যানো-সেকেন্ডের মধ্যে ভাল।

  • হাইবারনেটিং মন্তব্য সম্ভবত সত্য, তবে অনুশীলনে আপনি সম্ভবত হাইবারনেশন সীমানা জুড়ে সময় সম্পর্কে যত্নশীল হন না।

  • স্পিডস্টেপ সম্পর্কিত: নতুনতর ইন্টেল সিপিইউ গতি পরিবর্তনের জন্য ক্ষতিপূরণ দেয় এবং একটি সমন্বিত গণনা প্রদান করে। আমি আমাদের নেটওয়ার্কের কয়েকটি বাক্সে একটি দ্রুত স্ক্যান করেছি এবং কেবল একটি বাক্স পেয়েছি যা এতে নেই: পেন্টিয়াম 3 কিছু পুরানো ডাটাবেস সার্ভার চালাচ্ছে। (এগুলি লিনাক্স বাক্স, তাই আমি এটি দিয়ে পরীক্ষা করেছি: গ্রেপ ধ্রুবক_সেস্ক / প্রোক / সিপুইনফো)

  • আমি এএমডি সিপিইউ সম্পর্কে নিশ্চিত নই, আমরা প্রাথমিকভাবে একটি ইন্টেল শপ, যদিও আমি জানি আমাদের কয়েকটি নিম্ন স্তরের সিস্টেম গুরুগুলি একটি এএমডি মূল্যায়ন করেছে।

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


4
... কার্নেল লোকেদের কিছুক্ষণের জন্য rdtsc ব্যবহার বন্ধ করার জন্য লোকদের চেষ্টা করা হয়েছে ... এবং সাধারণত কার্নেলের মধ্যে এটি ব্যবহার করা এড়ানো কারণ এটি কেবলমাত্র অবিশ্বাস্য।
স্পুড86

4
রেফারেন্সের জন্য, আমি যে প্রশ্নটি জিজ্ঞাসা করেছি (একটি পৃথক উত্তরে - মন্তব্যের আগে) ছিল: "আমাকে স্বীকার করতে হবে, আপনার বেশিরভাগ উদাহরণ সরাসরি আমার মাথার উপরে গিয়েছিল It এটি সংকলন করে এবং মনে হয়, যদিও এটি নিরাপদ? এসএমপি সিস্টেম বা স্পিডস্টেপ? "
বার্নার্ড


11

ওয়াইন আসলে কোয়েরি পারফরম্যান্স কাউন্টার () বাস্তবায়নের জন্য গেটটাইম ডে () ব্যবহার করে এবং এটি অনেকগুলি উইন্ডোজ গেমগুলি লিনাক্স এবং ম্যাকের জন্য কাজ করে বলে জানা যায়।

Http://source.winehq.org/source/dlls/kernel32/cpu.c#L312 শুরু হয়

http://source.winehq.org/source/dlls/ntdll/time.c#L448 এ নিয়ে যায়


9

সুতরাং এটি মাইক্রোসেকেন্ডগুলিকে স্পষ্টভাবে বলেছে, তবে সিস্টেম ঘড়ির রেজোলিউশন অনির্দিষ্ট। আমি মনে করি এই প্রসঙ্গে রেজোলিউশনের অর্থ হল এর ক্ষুদ্রতম পরিমাণটি কীভাবে বাড়ানো হবে?

ডেটা স্ট্রাকচারটি পরিমাপের একক হিসাবে মাইক্রোসেকেন্ডগুলি হিসাবে সংজ্ঞায়িত করা হয় তবে এর অর্থ এই নয় যে ঘড়ি বা অপারেটিং সিস্টেমটি সেই সূক্ষ্মভাবে পরিমাপ করতে সক্ষম।

অন্যান্য ব্যক্তিদের মত পরামর্শ দেওয়াও gettimeofday()খারাপ, কারণ সময় নির্ধারণ করা ঘড়ির কাটা সৃষ্টি করতে পারে এবং আপনার গণনাটি ফেলে দিতে পারে। clock_gettime(CLOCK_MONOTONIC)আপনি যা চান তা হ'ল এবং clock_getres()আপনাকে আপনার ঘড়ির সূক্ষ্মতা জানাবে।


সুতরাং যখন গেটটাইমডে () দিবালোক সঞ্চয় দিয়ে এগিয়ে বা পিছনে লাফ দেয় তখন আপনার কোডটিতে কী ঘটে?
এমপিজে ০৩

4
ক্লক_জেটটাইম কেবলমাত্র নতুন লিনাক্সে উপস্থিত রয়েছে। অন্যান্য সিস্টেমে কেবল gettimeofday () থাকে
vitaly.v.ch

8

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

আমি এই উত্তরটি উচ্চ রেজোলিউশন সময় পরিমাপ এবং টাইমার্স, প্রথম ভাগের কাছ থেকে পেয়েছি


6

এই উত্তরে ঘড়ির সামঞ্জস্য হওয়ার সমস্যাগুলির উল্লেখ রয়েছে। টিক ইউনিটগুলির গ্যারান্টিযুক্ত আপনার উভয় সমস্যা এবং সময়ের সাথে সামঞ্জস্য হওয়ার সমস্যাগুলির সাথে C ++ 11 এ সমাধান করা হয়েছে<chrono> লাইব্রেরির ।

ঘড়িটি std::chrono::steady_clockসামঞ্জস্য না করার গ্যারান্টিযুক্ত, এবং তদুপরি এটি বাস্তব সময়ের তুলনায় স্থির হারে অগ্রসর হবে, সুতরাং স্পিডস্টেপের মতো প্রযুক্তিগুলি এটিকে প্রভাবিত করবে না।

আপনি কোনও std::chrono::durationবিশেষায়নে রূপান্তর করে টাইপসেফ ইউনিট পেতে পারেন , যেমন std::chrono::microseconds। এই ধরণের সাথে টিক মান দ্বারা ব্যবহৃত ইউনিটগুলি সম্পর্কে কোনও অস্পষ্টতা নেই। তবে, মনে রাখবেন যে ঘড়ির অগত্যা এই রেজোলিউশনটি নেই। আপনি যথাযথভাবে এমন একটি ঘড়ি না রেখে কোনও সময়কালকে অ্যাটসেকেন্ডে রূপান্তর করতে পারেন।


4

আমার অভিজ্ঞতা থেকে এবং আমি ইন্টারনেটে যা পড়েছি তা থেকে উত্তরটি "না," এটির কোনও গ্যারান্টিযুক্ত নয়। এটি সিপিইউ গতি, অপারেটিং সিস্টেম, লিনাক্সের স্বাদ ইত্যাদির উপর নির্ভর করে


3

আরডিটিএসসি পড়া এসএমপি সিস্টেমগুলিতে নির্ভরযোগ্য নয়, যেহেতু প্রতিটি সিপিইউ তাদের নিজস্ব কাউন্টার বজায় রাখে এবং প্রতিটি কাউন্টারকে অন্য সিপিইউতে সম্মতি সহ সুসংগত করে গ্যারান্টিযুক্ত হয় না।

আমি চেষ্টা করার পরামর্শ দিতে পারে clock_gettime(CLOCK_REALTIME)। পোস্টিক্স ম্যানুয়ালটি নির্দেশ করে যে এটি সমস্ত আনুগত্যমূলক সিস্টেমে প্রয়োগ করা উচিত। এটি ন্যানোসেকেন্ডের গণনা সরবরাহ করতে পারে clock_getres(CLOCK_REALTIME)তবে প্রকৃত রেজোলিউশনটি কী তা সম্ভবত আপনি সম্ভবত আপনার সিস্টেমে পরীক্ষা করতে চান ।


clock_getres(CLOCK_REALTIME)আসল রেজোলিউশন দেবে না। এটা সবসময় আসতে "1 NS" (এক ন্যানোসেকেন্ড) যখন hrtimers পাওয়া যায়, চেক include/linux/hrtimer.hজন্য ফাইল define HIGH_RES_NSEC 1(এ আরো stackoverflow.com/a/23044075/196561 )
osgx
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.