সংকলকটি কিছু মেশিনের জন্য এসেম্বলার (এবং শেষ পর্যন্ত মেশিন কোড) তৈরি করার কথা বলে এবং সাধারণত সি ++ সেই মেশিনের প্রতি সহানুভূতিশীল হওয়ার চেষ্টা করে।
অন্তর্নিহিত মেশিনের প্রতি সহানুভূতিশীল হওয়ার অর্থ মোটামুটি: সি ++ কোড লিখতে সহজ করা যা মেশিনটি দ্রুত কার্যকর করতে পারে এমন ক্রিয়াকলাপগুলিতে দক্ষতার সাথে মানচিত্র তৈরি করবে। সুতরাং, আমরা আমাদের হার্ডওয়্যার প্ল্যাটফর্মে দ্রুত এবং "প্রাকৃতিক" যে ডেটা ধরণের এবং অপারেশনগুলিতে অ্যাক্সেস সরবরাহ করতে চাই।
কংক্রিটলি, একটি নির্দিষ্ট মেশিন আর্কিটেকচার বিবেচনা করুন। চলুন বর্তমান ইন্টেল x86 পরিবারটি নেওয়া যাক।
ইন্টেল ®৪ এবং আইএ -32 আর্কিটেকচার সফটওয়্যার বিকাশকারীর ম্যানুয়াল ভল 1 ( লিঙ্ক ), বিভাগ 3.4.1 এ বলেছে:
নিম্নলিখিত 32 টি বিট সাধারণ উদ্দেশ্য নিবন্ধগুলি EAX, EBX, ECX, EDX, ESI, EDI, EBP, এবং ESP সরবরাহ করে:
Log যৌক্তিক এবং গাণিতিক ক্রিয়াকলাপগুলির জন্য অপারেন্ডস
Address ঠিকানা গণনার জন্য অপারেন্ডস
• স্মৃতি পয়েন্টার
সুতরাং, আমরা চাই যে সংকলকটি সহজ E ++ পূর্ণসংখ্যার গাণিতিকগুলি সঙ্কলন করে এই EAX, EBX ইত্যাদি রেজিস্টারগুলি ব্যবহার করে। এর অর্থ হ'ল আমি যখন একটি ঘোষণা করি তখন intএগুলি এই নিবন্ধগুলির সাথে সামঞ্জস্যপূর্ণ কিছু হওয়া উচিত, যাতে আমি সেগুলি দক্ষতার সাথে ব্যবহার করতে পারি।
নিবন্ধগুলি সর্বদা একই আকারের (এখানে, 32 বিট) থাকে, তাই আমার intভেরিয়েবলগুলি সর্বদা 32 বিটও হবে। আমি একই লেআউটটি ব্যবহার করব (লিটল-এন্ডিয়ান) যাতে প্রতিবারই আমি কোনও রেজিস্টারে ভেরিয়েবলের মান লোড করতে না পারি, বা কোনও ভেরিয়েবলে একটি রেজিস্টার সংরক্ষণ করতে পারি।
গডবোল্ট ব্যবহার করে আমরা দেখতে পাচ্ছি যে সংকলক কিছু তুচ্ছ কোডের জন্য ঠিক কী করে:
int square(int num) {
return num * num;
}
(GCC 8.1 সহ এবং -fomit-frame-pointer -O3সরলতার জন্য) সংকলন করুন :
square(int):
imul edi, edi
mov eax, edi
ret
এর অর্থ:
int numপরামিতি রেজিস্টার ই ডি আই পাস, যার অর্থ এটা ঠিক মাপ এবং Intel একটি নেটিভ রেজিস্টার আশা লে। ফাংশনটি কিছুই রূপান্তর করতে হবে না
- গুণটি একটি একক নির্দেশ (
imul), যা খুব দ্রুত
- ফলাফলটি ফেরত দেওয়া কেবল এটি অন্য রেজিস্টারে অনুলিপি করার বিষয় (কলার আশা করেন যে ফলাফলটি EAX এ দেওয়া হবে)
সম্পাদনা করুন: আমরা কোনও দেশি-বহিরাগত বিন্যাস ব্যবহার করে পার্থক্যটি দেখানোর জন্য একটি প্রাসঙ্গিক তুলনা যুক্ত করতে পারি। সবচেয়ে সহজ ক্ষেত্রে দেশী প্রস্থ ছাড়া অন্য কোনও ক্ষেত্রে মান সংরক্ষণ করা oring
গডবোল্ট আবার ব্যবহার করে আমরা একটি সাধারণ দেশীয় গুণকে তুলনা করতে পারি
unsigned mult (unsigned x, unsigned y)
{
return x*y;
}
mult(unsigned int, unsigned int):
mov eax, edi
imul eax, esi
ret
অ-মানক প্রস্থের সমতুল্য কোড সহ
struct pair {
unsigned x : 31;
unsigned y : 31;
};
unsigned mult (pair p)
{
return p.x*p.y;
}
mult(pair):
mov eax, edi
shr rdi, 32
and eax, 2147483647
and edi, 2147483647
imul eax, edi
ret
সমস্ত অতিরিক্ত নির্দেশাবলী ইনপুট ফর্ম্যাটটি (দুটি 31-বিট স্বাক্ষরবিহীন পূর্ণ সংখ্যা) প্রসেসর স্থানীয়ভাবে পরিচালনা করতে পারে এমন ফর্ম্যাটে রূপান্তর করার সাথে সম্পর্কিত। যদি আমরা ফলাফলটি 31-বিট মানতে আবার সঞ্চয় করতে চাই, তবে এটি করার জন্য আরও একটি বা দুটি নির্দেশ থাকবে।
এই অতিরিক্ত জটিলতার অর্থ হল যখন স্থান সংরক্ষণ খুব গুরুত্বপূর্ণ তখন আপনি এটির জন্য কেবল বিরক্ত হবেন। এই ক্ষেত্রে আমরা দেশীয় unsignedবা uint32_tপ্রকারের তুলনায় কেবল দুটি বিট সংরক্ষণ করছি , যা আরও সহজ কোড তৈরি করতে পারে।
গতিশীল আকারের একটি নোট:
উপরের উদাহরণটি এখনও ভেরিয়েবল-প্রস্থের পরিবর্তে স্থির-প্রস্থের মান, তবে প্রস্থ (এবং প্রান্তিককরণ) আর দেশীয় নিবন্ধগুলির সাথে মেলে না।
এক্স ৮86 প্ল্যাটফর্মটির কয়েকটি স্থানীয় নেটিভ মাপ রয়েছে, এতে মূল 32-বিট ছাড়াও 8-বিট এবং 16-বিট রয়েছে (আমি 64 64-বিট মোডে সরসতার জন্য বিভিন্ন জিনিস আছি)।
এই ধরণের (গৃহস্থালির কাজ, int8_t, uint8_t, int16_t ইত্যাদি) হয় এছাড়াও সরাসরি স্থাপত্য দ্বারা সমর্থিত - আংশিকভাবে সাথে পুরোনো 8086/286/386 / ইত্যাদি পিছন সামঞ্জস্যের জন্য। ইত্যাদি নির্দেশাবলী সেট।
এটি অবশ্যই এটির ক্ষেত্রে উপযুক্ত যে ছোট আকারের প্রাকৃতিক নির্দিষ্ট আকারের পছন্দটি যথেষ্ট হবে, এটি ভাল অনুশীলন হতে পারে - তারা এখনও দ্রুত, একক নির্দেশাবলীর লোড এবং স্টোর, আপনি এখনও পুরো গতির দেশীয় পাটিগণিত পেতে পারেন এবং আপনি এমনকি পারফরম্যান্সকে উন্নত করতে পারেন ক্যাশে মিস মিস।
এটি ভেরিয়েবল-দৈর্ঘ্যের এনকোডিংয়ের থেকে খুব আলাদা - আমি এর কয়েকটি নিয়ে কাজ করেছি এবং সেগুলি ভয়াবহ। প্রতিটি লোড একক নির্দেশের পরিবর্তে লুপ হয়ে যায়। প্রতিটি স্টোরও লুপ। প্রতিটি কাঠামো পরিবর্তনশীল-দৈর্ঘ্যের, তাই আপনি প্রাকৃতিকভাবে অ্যারে ব্যবহার করতে পারবেন না।
দক্ষতার উপর একটি আরও নোট
পরবর্তী মন্তব্যে আপনি "দক্ষ" শব্দটি ব্যবহার করছেন, যতক্ষণ না আমি স্টোরেজ আকারের সাথে সম্মান দিয়ে বলতে পারি। আমরা মাঝে মাঝে স্টোরেজের আকার হ্রাস করতে বেছে নিই - এটি গুরুত্বপূর্ণ হতে পারে যখন আমরা ফাইলগুলিতে খুব বড় সংখ্যক মান সংরক্ষণ করি বা একটি নেটওয়ার্কের মাধ্যমে সেগুলি প্রেরণ করি। বাণিজ্য বন্ধটি হ'ল আমাদের সেই মানগুলি তাদের সাথে কিছু করার জন্য নিবন্ধগুলিতে লোড করতে হবে এবং রূপান্তর সম্পাদন বিনামূল্যে নয়।
যখন আমরা দক্ষতা নিয়ে আলোচনা করি তখন আমাদের জানতে হবে আমরা কী অনুকূল করছি এবং বাণিজ্যগুলি কী। অ-নেটিভ স্টোরেজ প্রকারগুলি ব্যবহার করা স্থানের জন্য প্রক্রিয়াকরণের গতি বাণিজ্য করার এক উপায় এবং কখনও কখনও তা উপলব্ধি করে। পরিবর্তনশীল-দৈর্ঘ্যের স্টোরেজ ব্যবহার করে (কমপক্ষে গাণিতিক ধরণের জন্য), স্থানের প্রায়শই ন্যূনতম আরও সাশ্রয়ের জন্য আরও প্রক্রিয়াকরণ গতি (এবং কোড জটিলতা এবং বিকাশকারী সময়) ট্রেড করে ।
আপনি যে গতির জরিমানার জন্য অর্থ প্রদান করেন তার অর্থ এটি কেবল তখনই সার্থক হয় যখন আপনাকে একেবারে ব্যান্ডউইদথ বা দীর্ঘমেয়াদী স্টোরেজ হ্রাস করতে হবে এবং সেই ক্ষেত্রে সাধারণত একটি সাধারণ এবং প্রাকৃতিক ফর্ম্যাট ব্যবহার করা সহজ and এবং তারপরে কেবল এটি একটি সাধারণ-উদ্দেশ্য সিস্টেমের সাথে সংকুচিত করে ress (যেমন জিপ, জিজিপ, বিজিপ 2, এক্সওয়াই বা যা কিছু)।
TL; ড
প্রতিটি প্ল্যাটফর্মের একটি আর্কিটেকচার থাকে তবে আপনি ডেটা উপস্থাপনের জন্য বিভিন্নভাবে মূলত সীমাহীন সংখ্যক উপায়ে আসতে পারেন। কোনও ভাষার পক্ষে সীমাহীন সংখ্যক বিল্ট-ইন ডেটা প্রকার সরবরাহ করা যুক্তিসঙ্গত নয়। সুতরাং, সি ++ প্ল্যাটফর্মের নেটিভ, ডেটা প্রকারের প্রাকৃতিক সেটকে অন্তর্নিহিত অ্যাক্সেস সরবরাহ করে এবং আপনাকে অন্য কোনও (অ-নেটিভ) প্রতিনিধিত্বের কোড দেওয়ার অনুমতি দেয়।
unsingedমান, যা 1 বাইটের সাথে প্রতিনিধিত্ব করা যায়255। ২) মান পরিবর্তনের সাথে সাথে সর্বোত্তম সঞ্চয়স্থানের আকার গণনা করার এবং ভেরিয়েবলের সঞ্চয় স্থানটি সঙ্কুচিত / প্রসারিত করার বিষয়টি বিবেচনা করুন।