আমি এখানে সাধারণ জ্ঞানের বিরুদ্ধে যাচ্ছি যে এতে std::copy
সামান্য, প্রায় দুর্ভেদ্য পারফরম্যান্স ক্ষতি হবে। আমি কেবল একটি পরীক্ষা করেছি এবং এটি অসত্য বলে মনে করেছি: আমি একটি পারফরম্যান্সের পার্থক্য লক্ষ্য করেছি। তবে, বিজয়ী ছিল std::copy
।
আমি একটি সি ++ এসএইচএ -2 বাস্তবায়ন লিখেছি। আমার পরীক্ষায়, আমি চারটি SHA-2 সংস্করণ (224, 256, 384, 512) ব্যবহার করে 5 টি স্ট্রিং করেছি এবং আমি 300 বার লুপ করেছি। আমি বুস্ট.টিমার ব্যবহারের সময়গুলি পরিমাপ করি। 300 টি লুপের কাউন্টারটি আমার ফলাফলগুলি পুরোপুরি স্থিতিশীল করতে যথেষ্ট। আমি প্রতিবার 5 বার পরীক্ষা চালিয়েছি, memcpy
সংস্করণ এবং std::copy
সংস্করণে একসাথে ঘুরছি। আমার কোড সম্ভব (অন্যান্য অনেক বাস্তবায়নের যেমন খন্ডে বৃহৎ যেমন ডাটা দখল সুবিধা নেয় চালিত char
/ char *
, আমি সঙ্গে কাজ যেহেতু T
/ T *
(যেখানে T
ব্যবহারকারীর বাস্তবায়ন সর্ববৃহৎ টাইপ সঠিক ওভারফ্লো আচরণ নেই) যে, উপর এত দ্রুত মেমরি অ্যাক্সেস সবচেয়ে বড় ধরণের যা আমি করতে পারি তা আমার অ্যালগোরিদমের পারফরম্যান্সের কেন্দ্রীয় is এগুলি আমার ফলাফল:
SHA-2 পরীক্ষা চালানোর জন্য সময় (সেকেন্ডে)
std::copy memcpy % increase
6.11 6.29 2.86%
6.09 6.28 3.03%
6.10 6.29 3.02%
6.08 6.27 3.03%
6.08 6.27 3.03%
স্টাডির গতিতে মোট গড় বৃদ্ধি: মেমকপির উপর অনুলিপি: ২.৯৯%
আমার সংকলক ফেডোরা 16 x86_64 এ জিসিসি 4.6.3। আমার অপটিমাইজেশন পতাকাগুলি -Ofast -march=native -funsafe-loop-optimizations
।
আমার SHA-2 বাস্তবায়নের জন্য কোড।
আমি আমার এমডি 5 বাস্তবায়ন সম্পর্কেও একটি পরীক্ষা চালানোর সিদ্ধান্ত নিয়েছি। ফলাফলগুলি খুব কম স্থিতিশীল ছিল, তাই আমি 10 রান করার সিদ্ধান্ত নিয়েছিলাম। যাইহোক, আমার প্রথম কয়েকটি চেষ্টার পরে, আমি এমন ফলাফল পেয়েছি যা এক রান থেকে শুরু করে পরের দফায় দুরকমভাবে পরিবর্তিত হয়েছিল, তাই আমি অনুমান করছি যে সেখানে কোনও ধরণের ওএস ক্রিয়াকলাপ চলছে। আমি আবার শুরু করার সিদ্ধান্ত নিয়েছে।
একই সংকলক সেটিংস এবং পতাকা। এমডি 5 এর কেবল একটি সংস্করণ রয়েছে এবং এটি SHA-2 এর চেয়েও দ্রুত, সুতরাং আমি 5 টি পরীক্ষার স্ট্রিংয়ের অনুরূপ সেটটিতে 3000 লুপ করেছি।
এগুলি আমার চূড়ান্ত 10 ফলাফল:
এমডি 5 পরীক্ষা চালানোর জন্য সময় (সেকেন্ডে)
std::copy memcpy % difference
5.52 5.56 +0.72%
5.56 5.55 -0.18%
5.57 5.53 -0.72%
5.57 5.52 -0.91%
5.56 5.57 +0.18%
5.56 5.57 +0.18%
5.56 5.53 -0.54%
5.53 5.57 +0.72%
5.59 5.57 -0.36%
5.57 5.56 -0.18%
স্টাডির গতিতে মোট গড় হ্রাস :: মেমকপির উপর অনুলিপি: 0.11%
আমার এমডি 5 বাস্তবায়নের জন্য কোড
এই ফলাফলগুলির মধ্যে এমন কিছু অপ্টিমাইজেশন রয়েছে যা আমার এসএডিএ -২ টেস্টে স্ট্যান্ডার্ড :: অনুলিপি ব্যবহার করা হয়েছে যা std::copy
আমার এমডি 5 পরীক্ষায় ব্যবহার করতে পারেনি। রয়েছে SHA-2 পরীক্ষা এ উভয় অ্যারে যে বলা একই ফাংশন এ তৈরি হওয়া std::copy
/ memcpy
। আমার এমডি 5 পরীক্ষায়, অ্যারেগুলির মধ্যে একটি ফাংশন প্যারামিটার হিসাবে ফাংশনে স্থানান্তরিত হয়েছিল।
আমি std::copy
আবার দ্রুত তৈরি করতে কী করতে পারি তা দেখার জন্য আমি আরও কিছুটা পরীক্ষা করেছি । উত্তরটি সরল হয়ে উঠল: লিঙ্ক টাইম অপ্টিমাইজেশন চালু করুন। এলটিও চালু হওয়ার সাথে সাথে আমার ফলাফলগুলি (বিকল্পটি জিসিসি-তে ফ্লোটে):
-ফ্ল্টো সহ এমডি 5 পরীক্ষা চালানোর জন্য সময় (সেকেন্ডে)
std::copy memcpy % difference
5.54 5.57 +0.54%
5.50 5.53 +0.54%
5.54 5.58 +0.72%
5.50 5.57 +1.26%
5.54 5.58 +0.72%
5.54 5.57 +0.54%
5.54 5.56 +0.36%
5.54 5.58 +0.72%
5.51 5.58 +1.25%
5.54 5.57 +0.54%
স্টাডির গতিতে মোট গড় বৃদ্ধি: মেমকপির উপর অনুলিপি: 0.72%
সংক্ষেপে, ব্যবহারের জন্য পারফরম্যান্স জরিমানা বলে মনে হয় না std::copy
। আসলে, সেখানে একটি পারফরম্যান্স লাভ বলে মনে হচ্ছে।
ফলাফল ব্যাখ্যা
সুতরাং কেন std::copy
একটি পারফরম্যান্স উত্সাহ দিতে পারে ?
প্রথমত, আমি যতক্ষণ ইনলাইনিংয়ের অপ্টিমাইজেশন চালু না করা হয় এটি কোনও বাস্তবায়নের জন্য ধীর হয়ে যাওয়ার আশা করব না। সমস্ত সংকলক আগ্রাসীভাবে ইনলাইন করুন; এটি সম্ভবত সর্বাধিক গুরুত্বপূর্ণ অপ্টিমাইজেশন কারণ এটি অন্যান্য অনেকগুলি অনুকূলিতকরণ সক্ষম করে। std::copy
(এবং আমি সমস্ত বাস্তব বিশ্বের বাস্তবায়নগুলি সন্দেহ করি) সনাক্ত করতে পারে যে আর্গুমেন্টগুলি তুচ্ছভাবে অনুলিপিযোগ্য এবং সেই মেমরিটি ক্রমান্বয়ে ছড়িয়ে দেওয়া হয়েছে। এর অর্থ হ'ল সবচেয়ে খারাপ ক্ষেত্রে যখন memcpy
আইনী হয় তখন খারাপ আচরণ করা std::copy
উচিত নয়। এই সংলাপগুলির তুচ্ছ বাস্তবায়নটি "গতি বা আকারের জন্য অনুকূলকরণ করার সময় সর্বদা এটির সাথে ইনলাইন করুন" এর std::copy
সংকলনের memcpy
মানদণ্ডটি পূরণ করা উচিত।
তবে এর std::copy
আরও তথ্য রাখে। আপনি যখন কল করবেন তখন std::copy
ফাংশনটি ধরণের অক্ষত রাখে। memcpy
পরিচালিত হয় void *
, যা প্রায় সমস্ত দরকারী তথ্য বাতিল করে দেয়। উদাহরণস্বরূপ, আমি যদি একটি অ্যারে পাস করি std::uint64_t
তবে সংকলক বা লাইব্রেরি প্রয়োগকারী তার সাথে -৪-বিট প্রান্তিককরণের সুবিধা নিতে সক্ষম হতে পারে std::copy
তবে এটি করা আরও কঠিন হতে পারে memcpy
। প্রথমে সীমার শুরুতে স্বাক্ষরবিহীন অংশে, তারপরে প্রান্তিককরণ অংশ, তারপরে শেষে স্বাক্ষরবিহীন অংশটিতে কাজ করে এই কাজের মতো অ্যালগরিদমের অনেকগুলি বাস্তবায়ন। যদি এটি সমস্ত প্রান্তিককরণের গ্যারান্টিযুক্ত হয়, তবে কোডটি আপনার প্রসেসরে থাকা শাখার ভবিষ্যদ্বাণীকের সঠিক হওয়ার পক্ষে কোডটি আরও সহজ এবং দ্রুততর হয়।
অকাল অপটিমাইজেশন?
std::copy
একটি আকর্ষণীয় অবস্থানে আছে। আমি প্রত্যাশা করি যে এটি memcpy
কোনও আধুনিক অপ্টিমাইজ করা সংকলকটির চেয়ে কখনও ধীর এবং কখনও কখনও দ্রুত হবে না । তদুপরি, আপনি যা কিছু করতে পারেন memcpy
, আপনি পারেন std::copy
। memcpy
বাফারগুলিতে কোনও ওভারল্যাপের অনুমতি দেয় না, যেখানে std::copy
একদিকে ওভারল্যাপ সমর্থন করে ( std::copy_backward
ওভারল্যাপের অন্য দিকের সাথে)। memcpy
শুধুমাত্র পয়েন্টার উপর কাজ করে std::copy
কোনো iterators উপর কাজ করে ( std::map
, std::vector
, std::deque
, অথবা আমার নিজস্ব টাইপ)। অন্য কথায়, std::copy
যখন আপনার চারপাশের উপাত্তগুলি অনুলিপি করার প্রয়োজন হয় তখনই আপনার ব্যবহার করা উচিত ।
char
প্রয়োগের উপর নির্ভর করে স্বাক্ষরিত বা স্বাক্ষরযুক্ত হতে পারে। যদি বাইটের সংখ্যা> = 128 হতে পারে তবেunsigned char
আপনার বাইট অ্যারে ব্যবহার করুন । ((int *)
কাস্টটিও এর মতো নিরাপদ হবে(unsigned int *)
))