সর্বদা হিসাবে, এটি পার্শ্ববর্তী কোড প্রসঙ্গে : যেমন আপনি x<<1
একটি অ্যারে সূচক হিসাবে ব্যবহার করছেন ? নাকি এটিকে অন্য কিছুতে যুক্ত করছেন? উভয় ক্ষেত্রেই, ছোট শিফট গণনা (1 বা 2) প্রায়শই আরও বেশি অনুকূলিত করতে পারে যদি সংকলকটি কেবল শিফট শেষ করে দেয় । পুরো থ্রুটপুট বনাম প্রকারের বিলম্বতা বনাম ফ্রন্ট-এন্ড বাধা বিপণনের কথা উল্লেখ না করে। ক্ষুদ্র ক্ষুদ্র অংশের পারফরম্যান্স এক-মাত্রিক নয়।
একটি হার্ডওয়্যার শিফট নির্দেশাবলী সংকলনের একমাত্র সংকলকের বিকল্প x<<1
নয়, তবে অন্যান্য উত্তরগুলি বেশিরভাগই এটি ধরে নিচ্ছে।
x << 1
x+x
স্বাক্ষরবিহীন, এবং 2 এর পরিপূরক স্বাক্ষরিত পূর্ণসংখ্যার জন্য ঠিক সমান । কম্পাইলাররা সর্বদা জানে যে তারা কী হার্ডওয়্যার সংকলন করার সময় তারা লক্ষ্যবস্তু করছে, তাই তারা এই জাতীয় কৌশলগুলির সুবিধা নিতে পারে।
ইনটেল হাসওলে অন , add
প্রতি ক্লক থ্রুপুট 4 থাকে তবে shl
তাত্ক্ষণিক গণনা সহ প্রতি ঘড়ি থ্রুটপুট থাকে 2। ( নির্দেশাবলী সারণী এবং অন্য লিঙ্কগুলির জন্য http://agner.org/optimize/ দেখুনx86ট্যাগ উইকি)। সিমডি ভেক্টর শিফটগুলি প্রতি ঘড়ি প্রতি 1 (স্কাইলেকে 2), তবে সিমডি ভেক্টর সংখ্যার প্রতি ঘড়ি প্রতি 2 হয় (স্কাইলেকে 3)। প্রচ্ছন্নতা একই, যদিও: 1 চক্র।
shl
ওপকোডে গণনা অন্তর্ভুক্ত যেখানে রয়েছে সেখানে একটি বিশেষ শিফট বাই ওয়ান এনকোডিং রয়েছে । 8086 এর তাত্ক্ষণিক-গণনা শিফট নেই, কেবলমাত্র এক-এক করে এবং cl
রেজিস্টার দ্বারা । এটি বেশিরভাগ ক্ষেত্রে ডান-শিফ্টগুলির জন্য প্রাসঙ্গিক, কারণ আপনি যদি কোনও স্মৃতি অপারেণ্ড পরিবর্তন না করেন তবে আপনি কেবল বাম শিফটে যুক্ত করতে পারেন। তবে পরে যদি মানটির প্রয়োজন হয় তবে প্রথমে একটি রেজিস্টারে লোড করা ভাল। তবে যাইহোক, shl eax,1
বা এর add eax,eax
চেয়ে এক বাইট কম shl eax,10
, এবং কোড-আকার সরাসরি (ডিকোড / ফ্রন্ট-এন্ড বাধা) বা অপ্রত্যক্ষভাবে (এল 1 আই কোড ক্যাশে মিস করে) পারফরম্যান্সকে প্রভাবিত করে।
আরও সাধারণভাবে, ছোট শিফট গণনাগুলি কখনও কখনও x86 এর ঠিকানা ঠিকানাটিতে একটি মাপানো সূচকে অনুকূলিত করা যায়। এই দিনগুলিতে প্রচলিত অন্যান্য বেশিরভাগ আর্কিটেকচার হ'ল আরআইএসসি, এবং স্কেল-ইনডেক্সের ঠিকানা ঠিকানাগুলি নেই, তবে এটি উল্লেখ করার মতো x86 একটি সাধারণ যথেষ্ট আর্কিটেকচার। (ডিম্বানু আপনি যদি 4-বাইট উপাদানের একটি অ্যারে সূচক করে থাকেন তবে স্কেল ফ্যাক্টর 1 এর জন্য 1 বাড়ানোর জায়গা রয়েছে int arr[]; arr[x<<1]
)।
অনুলিপি + শিফ্টের প্রয়োজন এমন পরিস্থিতিতে সাধারণ যেখানে x
এখনও এর মূল মূল্য প্রয়োজন। তবে বেশিরভাগ x86 পূর্ণসংখ্যার নির্দেশাবলী স্থানে কাজ করে। (গন্তব্য add
বা এর মতো নির্দেশের জন্য উত্সগুলির মধ্যে একটি shl
)) x86-64 সিস্টেম ভি কলিং কনভেনশন রেজিস্টারে আর্গগুলি পাস করে, প্রথম আরগ ইন edi
এবং রিটার্ন মান সহ eax
, সুতরাং একটি ফাংশন যা x<<10
সংকলককে এমিট কপি + শিফট করে তোলে কোড
LEA
নির্দেশ আপনি নামান-এবং-যোগ করতে দেয় (কারণ এটা অ্যাড্রেসিং-মোড মেশিন-এনকোডিং ব্যবহার করে, 0 থেকে 3 এর একটি স্থানান্তর গণনা সহ)। এটি ফলাফলকে একটি পৃথক রেজিস্টারে রাখে।
জিডিসি এবং ক্ল্যাং উভয়ই এই ফাংশনগুলিকে একইভাবে অনুকূলিত করে, যেমন আপনি গডবোল্ট সংকলক এক্সপ্লোরারটিতে দেখতে পারেন :
int shl1(int x) { return x<<1; }
lea eax, [rdi+rdi] # 1 cycle latency, 1 uop
ret
int shl2(int x) { return x<<2; }
lea eax, [4*rdi] # longer encoding: needs a disp32 of 0 because there's no base register, only scaled-index.
ret
int times5(int x) { return x * 5; }
lea eax, [rdi + 4*rdi]
ret
int shl10(int x) { return x<<10; }
mov eax, edi # 1 uop, 0 or 1 cycle latency
shl eax, 10 # 1 uop, 1 cycle latency
ret
এলইএর 2 টি উপাদান সহ সাম্প্রতিক ইন্টেল এবং এএমডি সিপিইউগুলিতে 1 চক্রের বিলম্ব এবং 2-প্রতি-ক্লক থ্রুটপুট রয়েছে। (স্যান্ডিব্রিজ-পরিবার এবং বুলডোজার / রাইজেন)। ইন্টেলে, এটি প্রতি ঘড়ি থ্রুটপুট প্রতি 3 সি ল্যাটেন্সি সহ কেবল 1 lea eax, [rdi + rsi + 123]
। (সম্পর্কিত: কোলাটজ অনুমানটি পরীক্ষার জন্য আমার হাতের লিখিত সমাবেশের চেয়ে কেন এই সি ++ কোড দ্রুত? বিস্তারিতভাবে এটিতে যায়))
যাইহোক, 10 দ্বারা কপি + শিফ্টের জন্য পৃথক mov
নির্দেশিকা প্রয়োজন। এটি সাম্প্রতিক অনেক সিপিইউতে শূন্যের বিলম্ব হতে পারে তবে এটি এখনও ফ্রন্ট-এন্ড ব্যান্ডউইথ এবং কোড আকার নেয়। ( X86 এর এমওভি আসলেই কী "মুক্ত" হতে পারে? কেন আমি এটিকে কেন মোটেও পুনরুত্পাদন করতে পারি না? )
এছাড়াও সম্পর্কিত: x86 এ কেবলমাত্র 2 টি লল নির্দেশাবলী ব্যবহার করে 37 টি দ্বারা কীভাবে একটি নিবন্ধকে গুণ করবেন? ।
সংকলক আশেপাশের কোডটি রূপান্তর করতেও নিখরচায় যাতে কোনও আসল স্থানান্তর হয় না বা এটি অন্যান্য ক্রিয়াকলাপের সাথে মিলিত হয় ।
উদাহরণস্বরূপ উচ্চ বিট ব্যতীত সমস্ত বিট চেক if(x<<1) { }
করতে একটি ব্যবহার করতে পারে and
। X86-এ, আপনি কোনও test
নির্দেশ ব্যবহার করবেন, তার পরিবর্তে test eax, 0x7fffffff
/ এর jz .false
পরিবর্তে shl eax,1 / jz
। এই অপ্টিমাইজেশনটি যে কোনও শিফ্ট গণনার জন্য কাজ করে এবং এটি এমন মেশিনেও কাজ করে যেখানে বড়-গণনার শিফটগুলি ধীর (পেন্টিয়াম 4 এর মতো), বা অস্তিত্বহীন (কিছু মাইক্রো-কন্ট্রোলার) থাকে।
অনেক আইএসএর কাছে সরিয়ে নেওয়ার বাইরে বিট-ম্যানিপুলেশন নির্দেশনা রয়েছে। উদাহরণস্বরূপ পাওয়ারপিসিতে অনেকগুলি বিট-ফিল্ড এক্সট্রাক্ট / সন্নিবেশ করার নির্দেশাবলী রয়েছে। বা এআরএমের অন্য কোনও নির্দেশের অংশ হিসাবে সোর্স অপারেশনগুলির শিফট রয়েছে। (সুতরাং শিফট / ঘোরানো নির্দেশাবলীর move
স্থানান্তরিত উত্স ব্যবহার করে কেবল একটি বিশেষ ফর্ম )
মনে রাখবেন, সি সমাবেশের ভাষা নয় । আপনি যখন দক্ষতার সাথে সংকলন করতে আপনার উত্স কোডটি টিউন করছেন তখন সর্বদা অনুকূলিত সংকলক আউটপুটটি দেখুন ।