এই নতুন উত্তরটিতে সি ++ 11 এর <chrono>
সুবিধা ব্যবহার করা হয়েছে। যদিও অন্যান্য উত্তর রয়েছে যা কীভাবে ব্যবহার করতে <chrono>
হয় তা দেখায়, তাদের মধ্যে কেউই এখানে অন্য উত্তরগুলির কয়েকটিতে উল্লিখিত সুবিধাটি কীভাবে ব্যবহার করতে <chrono>
হয় তা দেখায় না RDTSC
। তাই আমি ভাবলাম কীভাবে ব্যবহার করবেন তা দেখাতে হবে RDTSC
সঙ্গে <chrono>
। উপরন্তু আমি প্রমান করবে কিভাবে বুঝবেন আপনার দ্রুত মধ্যে সুইচ করতে পারেন ঘড়িতে পরীক্ষামূলক কোড templatize করতে পারেন যাতে RDTSC
এবং আপনার সিস্টেম বিল্ট-ইন ঘড়িটি সুবিধা (যা সম্ভবত উপর ভিত্তি করে করা হবে clock()
, clock_gettime()
এবং / অথবা QueryPerformanceCounter
।
লক্ষ করুন যে RDTSC
নির্দেশটি x86- নির্দিষ্ট। QueryPerformanceCounter
শুধুমাত্র উইন্ডোজ। এবং clock_gettime()
কেবল পসিক্স। নীচে আমি দুটি নতুন ঘড়ি পরিচয় করিয়ে দিচ্ছি: std::chrono::high_resolution_clock
এবং std::chrono::system_clock
, যদি আপনি সি ++ 11 ধরে নিতে পারেন তবে এখন ক্রস প্ল্যাটফর্ম।
প্রথমত, এখানে আপনি কীভাবে ইন্টেল rdtsc
সমাবেশ নির্দেশাবলীর বাইরে একটি C ++ 11- সামঞ্জস্যপূর্ণ ঘড়ি তৈরি করবেন । আমি এটি কল করব x::clock
:
#include <chrono>
namespace x
{
struct clock
{
typedef unsigned long long rep;
typedef std::ratio<1, 2'800'000'000> period; // My machine is 2.8 GHz
typedef std::chrono::duration<rep, period> duration;
typedef std::chrono::time_point<clock> time_point;
static const bool is_steady = true;
static time_point now() noexcept
{
unsigned lo, hi;
asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
return time_point(duration(static_cast<rep>(hi) << 32 | lo));
}
};
} // x
এই সমস্ত ঘড়িটি সিপিইউ চক্র গণনা করা এবং এটি স্বাক্ষরবিহীন 64৪-বিট পূর্ণসংখ্যায় সঞ্চয় করে। আপনার সংকলকটির জন্য আপনার বিধানসভা ভাষার সিনট্যাক্সটি সামলানো দরকার। অথবা আপনার সংকলক একটি অভ্যন্তরীণ প্রস্তাব দিতে পারে যার পরিবর্তে আপনি ব্যবহার করতে পারেন (যেমন now() {return __rdtsc();}
)।
একটি ঘড়ি তৈরি করতে আপনাকে এটিকে উপস্থাপনা (স্টোরেজ টাইপ) দিতে হবে। আপনার মেশিনটি বিভিন্ন পাওয়ার মোডে ঘড়ির গতি পরিবর্তন করতে পারে তার পরেও আপনাকে অবশ্যই ক্লক পিরিয়ড সরবরাহ করতে হবে which এবং এগুলি থেকে আপনি আপনার ঘড়ির "নেটিভ" সময়কাল এবং সময়সূত্রগুলি এই মৌলিক বিষয়গুলির ভিত্তিতে সহজেই সংজ্ঞায়িত করতে পারেন।
যদি আপনি যা করতে চান তা হ'ল ক্লক টিকের সংখ্যা আউটপুট করা হয় তবে আপনি ঘড়ির সময়কালের জন্য কোন নম্বর দিবেন তা আসলেই গুরুত্বপূর্ণ নয়। এই ধ্রুবকটি কেবলমাত্র খেলায় আসে যদি আপনি ঘড়ির টিকের সংখ্যাটিকে কিছু রিয়েল-টাইম ইউনিটে যেমন ন্যানোসেকেন্ডগুলিতে রূপান্তর করতে চান। এবং সেক্ষেত্রে আপনি যত বেশি ঘড়ির গতি সরবরাহ করতে সক্ষম হবেন তত বেশি সঠিক হ'ল ন্যানোসেকেন্ডে (মিলিসেকেন্ড, যাই হোক না কেন) রূপান্তর।
নীচে উদাহরণ কোড রয়েছে যা কীভাবে ব্যবহার করতে হয় তা দেখায় x::clock
। আসলে আমি ঘড়িতে কোডটি টেম্পলেট করেছি যেহেতু আপনি ঠিক একই সিনট্যাক্সের সাহায্যে আপনি কীভাবে আরও অনেকগুলি ঘড়ি ব্যবহার করতে পারেন তা দেখাতে চাই। এই নির্দিষ্ট পরীক্ষাটি দেখায় যে আপনি যখন লুপের নীচে সময় কাটাতে চান তা চালানোর সময় লুপিং ওভারহেডটি কী:
#include <iostream>
template <class clock>
void
test_empty_loop()
{
// Define real time units
typedef std::chrono::duration<unsigned long long, std::pico> picoseconds;
// or:
// typedef std::chrono::nanoseconds nanoseconds;
// Define double-based unit of clock tick
typedef std::chrono::duration<double, typename clock::period> Cycle;
using std::chrono::duration_cast;
const int N = 100000000;
// Do it
auto t0 = clock::now();
for (int j = 0; j < N; ++j)
asm volatile("");
auto t1 = clock::now();
// Get the clock ticks per iteration
auto ticks_per_iter = Cycle(t1-t0)/N;
std::cout << ticks_per_iter.count() << " clock ticks per iteration\n";
// Convert to real time units
std::cout << duration_cast<picoseconds>(ticks_per_iter).count()
<< "ps per iteration\n";
}
এই কোডটি প্রথম কাজটি করে ফলাফলগুলি প্রদর্শন করার জন্য একটি "রিয়েল টাইম" ইউনিট তৈরি করে I've উদাহরণ হিসাবে একটি প্রাক-তৈরি std::chrono::nanoseconds
ইউনিট আমি ব্যবহার করতে পারতাম।
অন্য একটি উদাহরণ হিসাবে আমি পুনরাবৃত্তি প্রতি ঘড়ির চক্রের গড় সংখ্যা একটি ভাসমান বিন্দু হিসাবে মুদ্রণ করতে চাই, তাই আমি দ্বিগুণের ভিত্তিতে আরেকটি সময়কাল তৈরি করি, যেটির ঘড়ির টিকের মতো একই ইউনিট থাকে (কোডটিতে বলা Cycle
হয়)।
লুপটি clock::now()
উভয় পক্ষের কলগুলির সাথে সমাপ্ত হয়। আপনি যদি এই ফাংশন থেকে ফিরে আসা টাইপের নাম রাখতে চান তবে তা হ'ল:
typename clock::time_point t0 = clock::now();
( x::clock
উদাহরণে যেমন স্পষ্টভাবে দেখানো হয়েছে , এবং এটি সিস্টেম-সরবরাহকৃত ঘড়িগুলির ক্ষেত্রেও সত্য)।
ভাসমান পয়েন্ট ক্লক টিকের ক্ষেত্রে একটি সময়কাল পেতে একজন কেবল দুটি সময় পয়েন্টকে বিয়োগ করে এবং প্রতি পুনরাবৃত্তির মান পেতে, সেই সময়কালকে পুনরাবৃত্তির সংখ্যার দ্বারা ভাগ করে।
count()
সদস্য ফাংশনটি ব্যবহার করে আপনি যে কোনও সময়কালে গণনা পেতে পারেন । এটি অভ্যন্তরীণ উপস্থাপনা ফেরত দেয়। অবশেষে আমি std::chrono::duration_cast
সময়কালকে সময়কালে রূপান্তর করতে এবং এটি মুদ্রণ Cycle
করতে ব্যবহার করি picoseconds
।
এই কোডটি ব্যবহার করা সহজ:
int main()
{
std::cout << "\nUsing rdtsc:\n";
test_empty_loop<x::clock>();
std::cout << "\nUsing std::chrono::high_resolution_clock:\n";
test_empty_loop<std::chrono::high_resolution_clock>();
std::cout << "\nUsing std::chrono::system_clock:\n";
test_empty_loop<std::chrono::system_clock>();
}
উপরে আমি আমাদের বাড়ির তৈরি ব্যবহার করে পরীক্ষাটি করি x::clock
এবং সিস্টেম-সরবরাহ করা দুটি ঘড়ি ব্যবহার করে সেই ফলাফলগুলি তুলনা করি: std::chrono::high_resolution_clock
এবং std::chrono::system_clock
। আমার জন্য এটি প্রিন্ট করে:
Using rdtsc:
1.72632 clock ticks per iteration
616ps per iteration
Using std::chrono::high_resolution_clock:
0.620105 clock ticks per iteration
620ps per iteration
Using std::chrono::system_clock:
0.00062457 clock ticks per iteration
624ps per iteration
এটি দেখায় যে এই ঘড়ির প্রত্যেকটির আলাদা আলাদা টিক পিরিয়ড রয়েছে, কারণ প্রতিটি ঘড়ির জন্য পুনরাবৃত্তির জন্য টিকগুলি সম্পূর্ণ আলাদা। যাইহোক যখন সময়ের একটি পরিচিত ইউনিটে রূপান্তরিত হয় (যেমন পিকোসেকেন্ডস), আমি প্রতিটি ঘড়ির জন্য প্রায় একই ফলাফল পাই (আপনার মাইলেজ আলাদা হতে পারে)।
আমার কোডটি কীভাবে "ম্যাজিক রূপান্তর ধ্রুবকগুলি" থেকে সম্পূর্ণ মুক্ত তা নোট করুন। প্রকৃতপক্ষে পুরো উদাহরণটিতে কেবল দুটি ম্যাজিক সংখ্যা রয়েছে:
- সংজ্ঞায়িত করতে আমার মেশিনের ঘড়ির গতি
x::clock
।
- পরীক্ষা করার জন্য পুনরাবৃত্তির সংখ্যা। যদি এই সংখ্যাটি পরিবর্তন করে আপনার ফলাফলগুলি ব্যাপকভাবে পরিবর্তিত হয়, তবে সম্ভবত আপনার পুনরাবৃত্তির সংখ্যা আরও বেশি হওয়া উচিত, বা পরীক্ষার সময় আপনার কম্পিউটারটি প্রতিদ্বন্দ্বী প্রক্রিয়াগুলি খালি করা উচিত।