জেনেরিক অপটিমাইজেশন
এখানে আমার প্রিয় কয়েকটি অপ্টিমাইজেশন হিসাবে রয়েছে। আমি এগুলি ব্যবহার করে বাস্তবায়নের সময়গুলি এবং প্রোগ্রামের আকার হ্রাস করেছি।
ছোট ক্রিয়াকলাপগুলি inline
ম্যাক্রো হিসাবে ঘোষণা করুন
কোনও ফাংশনে (বা পদ্ধতি) প্রতিটি কল ওভারহেডকে অন্তর্ভুক্ত করে, যেমন স্ট্যাকের উপরে ভেরিয়েবলগুলি ঠেলাঠেলি। কিছু ফাংশন ফিরতে ওভারহেডও দিতে পারে। একটি অদক্ষ ফাংশন বা পদ্ধতিতে এর সামগ্রীতে সম্মিলিত ওভারহেডের চেয়ে কম বিবৃতি রয়েছে। এগুলি ইনলাইনিংয়ের জন্য ভাল প্রার্থী, এটি #define
ম্যাক্রো বা inline
ফাংশন হিসাবেই হোক । (হ্যাঁ, আমি জানি inline
কেবল একটি পরামর্শ, তবে এই ক্ষেত্রে আমি এটিকে সংকলকটির অনুস্মারক হিসাবে বিবেচনা করি ))
মৃত এবং অপ্রয়োজনীয় কোড সরান
যদি কোডটি ব্যবহার না করা হয় বা প্রোগ্রামের ফলাফলে অবদান না দেয় তবে এ থেকে মুক্তি পান।
অ্যালগরিদমের নকশা সরল করুন
আমি একবার গণনা করা বীজগণিত সমীকরণটি লিখে একটি প্রোগ্রাম থেকে প্রচুর সমাবেশ কোড এবং প্রয়োগের সময় সরিয়ে দিয়েছিলাম এবং তারপরে বীজগণিতিক ভাবটি সরল করে দিয়েছিলাম। সরল বীজগণিত প্রকাশের বাস্তবায়নে আসল ফাংশনটির চেয়ে কম জায়গা এবং সময় নিয়েছে।
লুপ আনরোলিং
প্রতিটি লুপের ইনক্রিমেন্টিং এবং টার্মিনেশন চেকিংয়ের ওভারহেড থাকে। পারফরম্যান্স ফ্যাক্টরের একটি অনুমান পেতে, ওভারহেডে নির্দেশিকাগুলির সংখ্যা গণনা করুন (ন্যূনতম 3: বর্ধন, চেক, লুপের সূচনা) এবং লুপের ভিতরে বিবৃতি সংখ্যার দ্বারা ভাগ করুন divide ভাল নম্বর কম।
সম্পাদনা করুন: এর আগে লুপ আন্রোলিংয়ের একটি উদাহরণ সরবরাহ করুন:
unsigned int sum = 0;
for (size_t i; i < BYTES_TO_CHECKSUM; ++i)
{
sum += *buffer++;
}
তালিকাভুক্তির পরে:
unsigned int sum = 0;
size_t i = 0;
**const size_t STATEMENTS_PER_LOOP = 8;**
for (i = 0; i < BYTES_TO_CHECKSUM; **i = i / STATEMENTS_PER_LOOP**)
{
sum += *buffer++; // 1
sum += *buffer++; // 2
sum += *buffer++; // 3
sum += *buffer++; // 4
sum += *buffer++; // 5
sum += *buffer++; // 6
sum += *buffer++; // 7
sum += *buffer++; // 8
}
// Handle the remainder:
for (; i < BYTES_TO_CHECKSUM; ++i)
{
sum += *buffer++;
}
এই সুবিধাটিতে, একটি গৌণ সুবিধা পাওয়া যায়: প্রসেসরের নির্দেশের ক্যাশে পুনরায় লোড করার আগে আরও বিবৃতি কার্যকর করা হয়।
আমি 32 টি স্টেটমেন্টে একটি লুপ আনরোলড করেছিলাম তখন আমি বিস্ময়কর ফলাফল পেয়েছি। প্রোগ্রামটি একটি 2 জিবি ফাইলের জন্য একটি চেকসাম গণনা করার পরে এটি একটি অন্তরায়। এই অপ্টিমাইজেশনটি 1 ঘন্টা থেকে 5 মিনিটের মধ্যে ব্লক রিডিং উন্নত পারফরম্যান্সের সাথে মিলিত হয়। লুপ আনরোলিং সমাবেশের ভাষায়ও দুর্দান্ত পারফরম্যান্স সরবরাহ করেছিল, আমার সংকলকটির থেকে memcpy
অনেক দ্রুত ছিল memcpy
। - টিএম
if
বিবৃতি হ্রাস
প্রসেসরগুলি শাখাগুলি ঘৃণা করে, বা লাফ দেয়, যেহেতু এটি প্রসেসরকে তার নির্দেশাবলীর সারিটি পুনরায় লোড করতে বাধ্য করে।
বুলিয়ান পাটিগণিত ( সম্পাদিত: কোড টুকরাটিতে কোড বিন্যাস প্রয়োগ, উদাহরণ যুক্ত)
if
বুলিয়ান অ্যাসাইনমেন্টগুলিতে বিবৃতি রূপান্তর করুন । কিছু প্রসেসর শর্তযুক্তভাবে শাখা ছাড়াই নির্দেশাবলী কার্যকর করতে পারে:
bool status = true;
status = status && /* first test */;
status = status && /* second test */;
সংক্ষিপ্ত circuiting এর লজিক্যাল এবং অপারেটর ( &&
) পরীক্ষা মৃত্যুদন্ড যদি বাধা দেয় status
হয় false
।
উদাহরণ:
struct Reader_Interface
{
virtual bool write(unsigned int value) = 0;
};
struct Rectangle
{
unsigned int origin_x;
unsigned int origin_y;
unsigned int height;
unsigned int width;
bool write(Reader_Interface * p_reader)
{
bool status = false;
if (p_reader)
{
status = p_reader->write(origin_x);
status = status && p_reader->write(origin_y);
status = status && p_reader->write(height);
status = status && p_reader->write(width);
}
return status;
};
লুপগুলির বাইরে ফ্যাক্টর ভেরিয়েবল বরাদ্দ
যদি লুপের অভ্যন্তরে ফ্লাইতে কোনও পরিবর্তনশীল তৈরি করা হয় তবে তৈরি / বরাদ্দটি লুপের আগে নিয়ে যান। বেশিরভাগ ক্ষেত্রে, প্রতিটি পুনরাবৃত্তির সময় চলকটি বরাদ্দ করার প্রয়োজন হয় না।
লুপগুলির বাইরে ফ্যাক্টর ধ্রুবক প্রকাশ
যদি কোনও গণনা বা পরিবর্তনশীল মান লুপ সূচকের উপর নির্ভর করে না, এটি লুপের বাইরে (আগে) সরিয়ে ফেলুন।
ব্লকগুলিতে I / O
বড় অংশগুলিতে (ব্লক) ডেটা পড়ুন এবং লিখুন। বৃহত্তর আরও ভাল। উদাহরণস্বরূপ, একবারে একটি অক্টেক্ট পড়া একটি পড়ার সাথে 1024 অক্টেট পড়ার চেয়ে কম দক্ষ।
উদাহরণ:
static const char Menu_Text[] = "\n"
"1) Print\n"
"2) Insert new customer\n"
"3) Destroy\n"
"4) Launch Nasal Demons\n"
"Enter selection: ";
static const size_t Menu_Text_Length = sizeof(Menu_Text) - sizeof('\0');
//...
std::cout.write(Menu_Text, Menu_Text_Length);
এই কৌশলটির দক্ষতা চাক্ষুষভাবে প্রদর্শিত হতে পারে। :-)
ধ্রুবক ডেটার জন্য printf
পরিবার ব্যবহার করবেন না
ধ্রুব তথ্য ব্লক রাইট ব্যবহার করে আউটপুট হতে পারে। ফর্ম্যাট লেখনী অক্ষর বিন্যাসকরণ বা ফর্ম্যাটিং কমান্ডগুলি প্রক্রিয়াকরণের জন্য পাঠ্য স্ক্যান করতে ব্যয় করবে উপরের কোড উদাহরণ দেখুন।
স্মৃতিতে ফর্ম্যাট করুন, তারপরে লিখুন
char
একাধিক ব্যবহার করে একটি অ্যারে ফর্ম্যাট করুন sprintf
, তারপরে ব্যবহার করুন fwrite
। এটি ডেটা বিন্যাসকে "ধ্রুবক বিভাগ" এবং পরিবর্তনশীল বিভাগগুলিতে বিভক্ত করতে দেয়। চিন্তা করুন মেইল মার্জ ।
ধ্রুবক পাঠ্য (স্ট্রিং লিটারাল) হিসাবে ঘোষণা করুন static const
যখন ভেরিয়েবলগুলি ছাড়াই ঘোষণা করা হয় static
, কিছু সংকলক স্ট্যাকের জন্য স্থান বরাদ্দ করতে পারে এবং রম থেকে ডেটা অনুলিপি করতে পারে। এগুলি দুটি অপ্রয়োজনীয় অপারেশন। static
উপসর্গ ব্যবহার করে এটি স্থির করা যেতে পারে ।
শেষ অবধি, সংকলকের মতো কোডটি হবে
কখনও কখনও, সংকলকটি একটি জটিল সংস্করণের চেয়ে বেশ কয়েকটি ছোট বিবরণকে সর্বোত্তম করতে পারে। এছাড়াও, সংকলকটি অনুকূল করতে সহায়তা করার জন্য কোড লিখনটিও সহায়তা করে। যদি আমি কম্পাইলারটি বিশেষ ব্লক স্থানান্তর নির্দেশাবলী ব্যবহার করতে চাই তবে আমি এমন কোড লিখব যা দেখে মনে হচ্ছে এটি বিশেষ নির্দেশাবলী ব্যবহার করবে।