লিনাক্স কার্নেলের সম্ভাব্য / অসম্ভব ম্যাক্রোগুলি কীভাবে কাজ করে এবং তাদের সুবিধা কী?


348

আমি লিনাক্স কার্নেলের কিছু অংশ খনন করেছি, এবং এর মতো কল পেয়েছি:

if (unlikely(fd < 0))
{
    /* Do something */
}

অথবা

if (likely(!err))
{
    /* Do something */
}

আমি তাদের সংজ্ঞা পেয়েছি:

#define likely(x)       __builtin_expect((x),1)
#define unlikely(x)     __builtin_expect((x),0)

আমি জানি যে তারা অপ্টিমাইজেশনের জন্য, তবে তারা কীভাবে কাজ করবে? এবং এগুলি ব্যবহার করে কতটা পারফরম্যান্স / আকার হ্রাস আশা করা যায়? এবং এটি কি ঝামেলা (এবং সম্ভবত বহনযোগ্যতা হারাতে) কমপক্ষে বাধা কোডে (ইউজারস্পেসে, অবশ্যই) মূল্যবান?


7
এটি সত্যই লিনাক্স কার্নেল বা ম্যাক্রোগুলির সাথে নির্দিষ্ট নয়, তবে একটি সংকলক অপ্টিমাইজেশন রয়েছে। এটি প্রতিবিম্বিত করতে কি পুনরায় চালু করা উচিত?
কোডি ব্রোসিওস


2
আরও দেখুনBOOST_LIKELY
রাগ্গেরো তুরা


13
কোনও বহনযোগ্য সমস্যা নেই। আপনি তুচ্ছভাবে প্ল্যাটফর্মগুলিতে #define likely(x) (x)এবং #define unlikely(x) (x)এ জাতীয় ইঙ্গিতটি সমর্থন করেন না এমন প্ল্যাটফর্মগুলিতে এমন কিছু করতে পারেন।
ডেভিড শোয়ার্জ

উত্তর:


328

এগুলি নির্দেশক নির্গত করতে সংকলককে ইঙ্গিতযুক্ত যা শাখার ভবিষ্যদ্বাণীটি লাফের নির্দেশের "সম্ভাব্য" পক্ষের পক্ষে হবে। এটি একটি বড় জয় হতে পারে, যদি ভবিষ্যদ্বাণীটি সঠিক হয় তবে এর অর্থ হ'ল লাফের নির্দেশটি মূলত বিনামূল্যে এবং শূন্য চক্র গ্রহণ করবে। অন্যদিকে যদি ভবিষ্যদ্বাণীটি ভুল হয় তবে এর অর্থ হল প্রসেসরের পাইপলাইনটি ফ্লাশ করা দরকার এবং এটি বেশ কয়েকটি চক্রের জন্য ব্যয় করতে পারে। যতক্ষণ ভবিষ্যদ্বাণী বেশিরভাগ সময় সঠিক হয়, ততক্ষণ পারফরম্যান্সের পক্ষে এটি ভাল হতে পারে।

এই ধরনের সমস্ত পারফরম্যান্স অপটিমাইজেশনের মতো কোডটি সত্যিকার অর্থেই কোনও বাধা আছে এবং সম্ভবত মাইক্রো প্রকৃতি দেওয়া হয়েছে তা নিশ্চিত করার জন্য আপনার কেবলমাত্র এটির বিস্তৃত প্রোফাইল দেওয়ার পরে তা করা উচিত যে এটি একটি শক্ত লুপে চলছে। সাধারণত লিনাক্স বিকাশকারীরা বেশ অভিজ্ঞ তাই আমি কল্পনা করব তারা এটি করত। তারা পোর্টেবিলিটি সম্পর্কে সত্যই খুব বেশি চিন্তা করে না কারণ তারা কেবলমাত্র সিসিসি লক্ষ্য করে এবং তারা যে সমাবেশটি উত্পন্ন করতে চায় তার খুব কাছাকাছি ধারণা রয়েছে।


3
এই ম্যাক্রোগগুলি বেশিরভাগ ত্রুটি পরীক্ষার জন্য ব্যবহৃত হয়েছিল। কারণ ত্রুটি কম পরে সম্ভবত স্বাভাবিক অপারেশন। সর্বাধিক ব্যবহৃত পাতাগুলি নির্ধারণের জন্য কয়েকটি লোকেরা প্রোফাইলিং বা গণনা তৈরি করে ...
gavenkoa

51
খণ্ডটির বিষয়ে "[...]that it is being run in a tight loop", অনেক সিপিইউতে একটি শাখা প্রেডিকটার থাকে , এইভাবে এই ম্যাক্রোগুলি ব্যবহার করে কেবলমাত্র প্রথমবারের কোডটি কার্যকর করা হয় বা যখন ইতিহাস সারণীটি একই সূচী সহ একটি ভিন্ন শাখা দ্বারা শাখা টেবিলে ওভাররাইট করা হয়। একটি কড়া লুপে, এবং একটি শাখা ধরে নিয়ে যায় বেশিরভাগ সময় এক দিক যায়, শাখার ভবিষ্যদ্বাণী সম্ভবত খুব দ্রুত সঠিক শাখাটি অনুমান করা শুরু করবে। - পেডেন্ট্রিতে আপনার বন্ধু
রস রজার্স

8
@ রোসরোজারস: যা ঘটেছিল তা হ'ল সংকলকটি শাখাগুলি সজ্জিত করে তাই সাধারণ ক্ষেত্রে এটি নেওয়া হয় নি। শাখার পূর্বাভাস কাজ করার পরেও এটি দ্রুত। গৃহীত শাখাগুলি নির্দেশ-আনার জন্য সমস্যাযুক্ত এবং ডিকোড করার পরেও যখন তাদের পুরোপুরি পূর্বাভাস দেওয়া হয়। কিছু সিপিইউ স্টাটিকালি এমন শাখাগুলি পূর্বাভাস দেয় যা তাদের ইতিহাসের টেবিলে নেই, সাধারণত ফরোয়ার্ড শাখার জন্য নেওয়া হয়নি বলে ধরে নেওয়া হয়। ইন্টেল সিপিইউগুলি সেভাবে কাজ করে না: তারা ভবিষ্যদ্বাণীকারী টেবিল এন্ট্রি এই শাখার জন্য তা পরীক্ষা করে দেখার চেষ্টা করে না , তারা কেবল এটি যেভাবেই ব্যবহার করে। একটি গরম শাখা এবং একটি শীতল শাখা একই প্রবেশাধিকারীর নাম হতে পারে ...
পিটার কর্ডেস

12
এই উত্তরটি বেশিরভাগই অপ্রচলিত যেহেতু মূল দাবীটি এটি শাখার পূর্বাভাসকে সহায়তা করে এবং @ পিটারকর্ডস উল্লেখ করেছেন যে বেশিরভাগ আধুনিক হার্ডওয়্যারে কোনও অন্তর্নিহিত বা স্পষ্ট স্ট্যাটিক শাখার পূর্বাভাস নেই। প্রকৃতপক্ষে ইঙ্গিতটি কোডটি অপ্টিমাইজ করার জন্য কম্পাইলার দ্বারা ব্যবহৃত হয়, তাতে স্থির শাখার ইঙ্গিত, বা অন্য কোনও ধরণের অপ্টিমাইজেশন অন্তর্ভুক্ত কিনা। আজকের বেশিরভাগ আর্কিটেকচারের জন্য এটি "অন্য কোনও অপ্টিমাইজেশন" যা গুরুত্বপূর্ণ, যেমন,
উত্তোলিত পথগুলিকে সঙ্গতিপূর্ণ করে তোলা

3
ক্যাচ প্রিফেচ এবং শব্দের আকারের কারণে @ বিআনআরওপ, রৈখিকভাবে কোনও প্রোগ্রাম চালানোর এখনও একটি সুবিধা রয়েছে। পরবর্তী মেমরির অবস্থান ইতিমধ্যে সংগ্রহ করা হবে এবং ক্যাশে, শাখার লক্ষ্য হতে পারে বা সম্ভবত নাও। একটি 64 বিট সিপিইউ দিয়ে আপনি একবারে কমপক্ষে b৪ বিট দখল করেন। ডিআআরএএম ইন্টারলিওয়ের উপর নির্ভর করে এটি 2x 3x বা আরও বেশি বিট হতে পারে।
ব্রাইস

88

আসুন জিসিসি 4.8 এটির সাথে কী করে তা দেখতে ডিসমাইল কম্পাইল করি

ছাড়া __builtin_expect

#include "stdio.h"
#include "time.h"

int main() {
    /* Use time to prevent it from being optimized away. */
    int i = !time(NULL);
    if (i)
        printf("%d\n", i);
    puts("a");
    return 0;
}

জিসিসি 4.8.2 x86_64 লিনাক্স দিয়ে কম্পাইল এবং ডিসকোপাইল করুন:

gcc -c -O3 -std=gnu11 main.c
objdump -dr main.o

আউটপুট:

0000000000000000 <main>:
   0:       48 83 ec 08             sub    $0x8,%rsp
   4:       31 ff                   xor    %edi,%edi
   6:       e8 00 00 00 00          callq  b <main+0xb>
                    7: R_X86_64_PC32        time-0x4
   b:       48 85 c0                test   %rax,%rax
   e:       75 14                   jne    24 <main+0x24>
  10:       ba 01 00 00 00          mov    $0x1,%edx
  15:       be 00 00 00 00          mov    $0x0,%esi
                    16: R_X86_64_32 .rodata.str1.1
  1a:       bf 01 00 00 00          mov    $0x1,%edi
  1f:       e8 00 00 00 00          callq  24 <main+0x24>
                    20: R_X86_64_PC32       __printf_chk-0x4
  24:       bf 00 00 00 00          mov    $0x0,%edi
                    25: R_X86_64_32 .rodata.str1.1+0x4
  29:       e8 00 00 00 00          callq  2e <main+0x2e>
                    2a: R_X86_64_PC32       puts-0x4
  2e:       31 c0                   xor    %eax,%eax
  30:       48 83 c4 08             add    $0x8,%rsp
  34:       c3                      retq

মেমরিতে নির্দেশের আদেশটি অপরিবর্তিত ছিল: প্রথমে printfএবং তারপরে putsএবং retqফিরে।

সঙ্গে __builtin_expect

এখন এর সাথে প্রতিস্থাপন করুন if (i):

if (__builtin_expect(i, 0))

এবং আমরা পেতে:

0000000000000000 <main>:
   0:       48 83 ec 08             sub    $0x8,%rsp
   4:       31 ff                   xor    %edi,%edi
   6:       e8 00 00 00 00          callq  b <main+0xb>
                    7: R_X86_64_PC32        time-0x4
   b:       48 85 c0                test   %rax,%rax
   e:       74 11                   je     21 <main+0x21>
  10:       bf 00 00 00 00          mov    $0x0,%edi
                    11: R_X86_64_32 .rodata.str1.1+0x4
  15:       e8 00 00 00 00          callq  1a <main+0x1a>
                    16: R_X86_64_PC32       puts-0x4
  1a:       31 c0                   xor    %eax,%eax
  1c:       48 83 c4 08             add    $0x8,%rsp
  20:       c3                      retq
  21:       ba 01 00 00 00          mov    $0x1,%edx
  26:       be 00 00 00 00          mov    $0x0,%esi
                    27: R_X86_64_32 .rodata.str1.1
  2b:       bf 01 00 00 00          mov    $0x1,%edi
  30:       e8 00 00 00 00          callq  35 <main+0x35>
                    31: R_X86_64_PC32       __printf_chk-0x4
  35:       eb d9                   jmp    10 <main+0x10>

printf(আপনি কম্পাইল __printf_chk), ফাংশন শেষ সরিয়ে নেওয়া হয়েছে পরে putsহিসাবে অন্যান্য উত্তর উল্লেখ এবং বিনিময়ে শাখা ভবিষ্যদ্বাণী উন্নত।

সুতরাং এটি মূলত:

int main() {
    int i = !time(NULL);
    if (i)
        goto printf;
puts:
    puts("a");
    return 0;
printf:
    printf("%d\n", i);
    goto puts;
}

এই অপ্টিমাইজেশন সঙ্গে করা হয়নি -O0

তবে শুভেচ্ছা এমন উদাহরণ লেখার জন্য যা __builtin_expectবাইরে ছাড়াও দ্রুত চলে , সিপিইউগুলি আজকাল সত্যই স্মার্ট । আমার নিষ্পাপ প্রচেষ্টা এখানে

সি ++ 20 [[likely]]এবং[[unlikely]]

সি ++ ২০ এই সি ++ বিল্ট-ইনগুলিকে মানক করেছে: সি -+ 20 এর সম্ভাব্য / অসম্ভব বৈশিষ্ট্যটি যদি অন্য-বিবৃতিতে ব্যবহার করতে হয় তবে তারা সম্ভবত (পাং!) একই কাজ করবে।


71

এটি এমন ম্যাক্রো যা কোনও শাখা যে পথে যেতে পারে সে সম্পর্কে সংকলককে ইঙ্গিত দেয়। ম্যাক্রোগুলি যদি উপলভ্য থাকে তবে তারা জিসিসির নির্দিষ্ট এক্সটেনশনে প্রসারিত করে।

জিসিসি শাখার পূর্বাভাসের জন্য অনুকূলিত করতে এগুলি ব্যবহার করে। উদাহরণস্বরূপ, আপনার যদি নীচের মতো কিছু থাকে

if (unlikely(x)) {
  dosomething();
}

return x;

তারপরে এটি এই কোডটিকে আরও কিছু জাতীয় হতে পুনর্গঠন করতে পারে:

if (!x) {
  return x;
}

dosomething();
return x;

এর সুবিধাটি হ'ল প্রসেসরটি যখন প্রথমবার একটি শাখা নেয়, ততক্ষণে উল্লেখযোগ্য ওভারহেড থাকে, কারণ এটি সম্ভবত পূর্বে কোডটি লোডিং এবং চালানো কোডটি হতে পারে। যখন এটি নির্ধারণ করে যে এটি শাখাটি নেবে, তারপরে এটি অকার্যকর করতে হবে এবং শাখার লক্ষ্য থেকে শুরু করতে হবে।

বেশিরভাগ আধুনিক প্রসেসরের এখন কিছু ধরণের শাখা পূর্বাভাস রয়েছে, তবে এটি কেবল তখনই সহায়তা করে যখন আপনি আগে শাখার মধ্য দিয়ে এসেছিলেন, এবং শাখাটি তখনও শাখার পূর্বাভাস ক্যাশে থাকবে।

সংকলক এবং প্রসেসর এই পরিস্থিতিতে ব্যবহার করতে পারে এমন আরও অনেক কৌশল রয়েছে। উইকিপিডিয়ায় আপনি কিভাবে শাখা ভবিষ্যতবক্তা কাজের উপর আরো বিস্তারিত জানতে পারেন: http://en.wikipedia.org/wiki/Branch_predictor


3
এছাড়াও, এটি আইচাছের পদচিহ্নগুলিকে প্রভাবিত করে - কোডের সম্ভাব্য স্নিপেটগুলি গরম পথ থেকে দূরে রেখে।
fche

2
আরো সঠিকভাবে, এটা দিয়ে কি করতে পারেন gotoগুলি পুনরায় ছাড়া return x: stackoverflow.com/a/31133787/895245
সিরো Santilli郝海东冠状病六四事件法轮功

7

তারা কম্পাইলারটি যথাযথ শাখার ইঙ্গিতগুলি নির্গত করে যেখানে হার্ডওয়্যার তাদের সমর্থন করে। এর অর্থ হ'ল নির্দেশ অপকোডে কয়েকটি বিট গুটিয়ে ফেলা হয়, সুতরাং কোডের আকার পরিবর্তন হবে না। সিপিইউ পূর্বাভাসিত স্থান থেকে নির্দেশনা আনতে শুরু করবে, এবং পাইপলাইনটি ফ্লাশ করবে এবং শাখাটি পৌঁছে যাওয়ার পরে যদি এটি ভুল হয়ে যায় তবে এটি শুরু হবে; ক্ষেত্রে যেখানে ইঙ্গিতটি সঠিক, এটি শাখাকে আরও দ্রুত করে তুলবে - ঠিক কতটা দ্রুত হার্ডওয়্যারের উপর নির্ভর করবে; এবং কোডের কার্যকারিতাটিকে এটি কতটা প্রভাবিত করে তা নির্ভর করবে সময়ের ইঙ্গিতটির সঠিক অনুপাতের উপর।

উদাহরণস্বরূপ, পাওয়ারপিসি সিপিইউতে একটি অযাচিত শাখা 16 টি চক্র গ্রহণ করতে পারে, সঠিকভাবে ইঙ্গিতযুক্ত একটি 8 এবং একটি ভুলভাবে ইঙ্গিতযুক্ত একটি 24. আন্তঃতম লুপগুলিতে ভাল ইঙ্গিতটি একটি বিশাল পার্থক্য করতে পারে।

বহনযোগ্যতা আসলেই কোনও সমস্যা নয় - সম্ভবত সংজ্ঞাটি প্রতি প্ল্যাটফর্মের শিরোনামে রয়েছে; স্ট্যাটিক শাখার ইঙ্গিতগুলিকে সমর্থন করে না এমন প্ল্যাটফর্মগুলির জন্য আপনি কেবল "সম্ভাব্য" এবং "সম্ভাব্য" সংজ্ঞায়িত করতে পারেন।


3
রেকর্ডের জন্য, x86 শাখার ইঙ্গিতগুলির জন্য অতিরিক্ত স্থান নেয়। উপযুক্ত ইঙ্গিতটি নির্দিষ্ট করতে আপনার শাখাগুলিতে একটি বাইট উপসর্গ থাকতে হবে। সম্মত হয়েছে যে ইঙ্গিত দেওয়া একটি ভাল জিনিস (টিএম), যদিও।
কোডি ব্রোসিওস

2
ডাং সিআইএসসি সিপিইউ এবং তাদের পরিবর্তনশীল দৈর্ঘ্যের নির্দেশাবলী;)
চাঁদ

3
ডাং আরআইএসসি সিপিইউ - আমার 15 বাইট নির্দেশাবলী থেকে দূরে থাকুন;)
কোডি ব্রোসিওস

7
@ কোডি ব্রোকিয়াস: ব্রাঞ্চ ইঙ্গিতটি পি 4 দিয়ে প্রবর্তিত হয়েছিল, তবে পি 4 সহ তিনি পরিত্যক্ত হয়েছিলেন। অন্যান্য সমস্ত x86 সিপিইউ কেবল সেই উপসর্গগুলিকে উপেক্ষা করে (কারণ উপসর্গগুলি যেখানে অর্থহীন তা প্রসঙ্গে সবসময় উপেক্ষা করা হয়)। এই ম্যাক্রো না এক্স 86 উপর আসলে নির্গত শাখা-ইঙ্গিতটি উপসর্গ থেকে জিসিসি কারণ। তারা আপনাকে দ্রুত গতিতে কম নেওয়া শাখাগুলি দিয়ে আপনার ফাংশনটি সজ্জিত করতে জিসিসি পেতে সহায়তা করে।
পিটার কর্ডেস

5
long __builtin_expect(long EXP, long C);

এই কনস্ট্রাক্টরটি সংকলককে বলে যে এক্সপ্রেস এক্সপ্রেসনের সম্ভবত সম্ভবত মান সি হবে The __builtin_expect বলতে শর্তযুক্ত অভিব্যক্তিটি ব্যবহার করা হয়। প্রায় সকল ক্ষেত্রে এটি বুলিয়ান অভিব্যক্তিগুলির প্রসঙ্গে ব্যবহৃত হবে যা ক্ষেত্রে দুটি সহায়ক ম্যাক্রো সংজ্ঞায়িত করা আরও বেশি সুবিধাজনক:

#define unlikely(expr) __builtin_expect(!!(expr), 0)
#define likely(expr) __builtin_expect(!!(expr), 1)

এই ম্যাক্রোগুলি তখন হিসাবে ব্যবহার করা যেতে পারে

if (likely(a > 1))

তথ্যসূত্র: https://www.akkadia.org/drepper/cpumemory.pdf


1
যেমনটি অন্য উত্তরে একটি মন্তব্যে জিজ্ঞাসা করা হয়েছিল - ম্যাক্রোগুলিতে ডাবল বিপর্যয়ের কারণ কী (যেমন ন্যায়বিচারের __builtin_expect(!!(expr),0)পরিবর্তে কেন ব্যবহার করবেন __builtin_expect((expr),0)?
মাইকেল

1
@ মিশেলফ্রিথ "ডাবল বিপর্যয়" এটিতে !!কিছু ফেলে দেওয়ার সমতুল্য bool। কিছু লোক এটি এইভাবে লিখতে পছন্দ করেন।
বেন এক্সও

2

(সাধারণ মন্তব্য - অন্যান্য উত্তর বিশদগুলি কভার করে)

এগুলি ব্যবহার করে আপনার বহনযোগ্যতা হারাতে হবে এমন কোনও কারণ নেই।

আপনার কাছে সর্বদা একটি সহজ শূন্য-প্রভাব "ইনলাইন" বা ম্যাক্রো তৈরির বিকল্প রয়েছে যা আপনাকে অন্য প্ল্যাটফর্মগুলিতে অন্যান্য সংকলকগুলির সাথে সংকলন করতে দেয়।

আপনি যদি অন্য প্ল্যাটফর্মে থাকেন তবে আপনি অপ্টিমাইজেশনের সুবিধা পাবেন না।


1
আপনি বহনযোগ্যতা ব্যবহার করবেন না - প্ল্যাটফর্মগুলি যা তাদের সমর্থন করে না খালি স্ট্রিংগুলিতে প্রসারিত করার জন্য কেবল তাদের সংজ্ঞা দেয়।
sharptooth

2
আমি মনে করি আপনি দুজন একে অপরের সাথে একমত হচ্ছেন - এটি কেবল বিভ্রান্তিকরভাবে বর্ণিত। (এর চেহারা থেকে, অ্যান্ড্রুয়ের মন্তব্যটি বলছে "আপনি বহনযোগ্যতা হারায়ে এগুলি ব্যবহার করতে পারেন" তবে তীক্ষ্ণ ধারণা করেছিলেন যে তিনি বলেছিলেন যে তারা "পোর্টেবল নয় বলে তাদের ব্যবহার করবেন না" এবং আপত্তি জানিয়েছিল।)
মিরাল

2

কোডির মন্তব্য অনুসারে , এটির লিনাক্সের সাথে কোনও সম্পর্ক নেই, তবে এটি সংকলকটির জন্য একটি ইঙ্গিত। যা ঘটে তা আর্কিটেকচার এবং সংকলক সংস্করণের উপর নির্ভর করবে।

লিনাক্সের এই বিশেষ বৈশিষ্ট্যটি ড্রাইভারগুলিতে কিছুটা ভুল ব্যবহার করা হয়। যেমন ওসজিএক্স হট অ্যাট্রিবিউটের শব্দার্থবিজ্ঞানগুলিতে ইঙ্গিত করে , কোনও ব্লকের সাথে ডাকা যে কোনও hotবা coldফাংশন স্বয়ংক্রিয়ভাবে ইঙ্গিত দিতে পারে যে শর্তটি সম্ভবত রয়েছে কি না। উদাহরণস্বরূপ, dump_stack()চিহ্নিত করা হয়েছে coldযাতে এটি অপ্রয়োজনীয়,

 if(unlikely(err)) {
     printk("Driver error found. %d\n", err);
     dump_stack();
 }

ভবিষ্যতের সংস্করণগুলি gccএই ইঙ্গিতগুলির ভিত্তিতে কোনও ফাংশন নির্বাচন করে ইনলাইন করতে পারে। এছাড়াও এটির মতামত রয়েছে যে এটি নয় boolean, তবে সম্ভবত একটি স্কোর ইত্যাদি General সাধারণভাবে, কিছু বিকল্প পদ্ধতি যেমন পছন্দ করতে পছন্দ করা উচিত cold। এটি কোনও জায়গায় ব্যবহার করার কোনও কারণ নেই তবে গরম পথগুলি। একটি আর্কিটেকচারে একটি সংকলক কী করবে তা অন্যটিতে সম্পূর্ণ আলাদা হতে পারে।


2

অনেকগুলি লিনাক্স রিলিজে, আপনি / usr / linux / এ কমপ্লায়ার h খুঁজে পেতে পারেন, আপনি কেবল এটি ব্যবহারের জন্য অন্তর্ভুক্ত করতে পারেন। এবং অন্য একটি মতামত, সম্ভাব্য () পরিবর্তে সম্ভাব্য () বেশি কার্যকর, কারণ

if ( likely( ... ) ) {
     doSomething();
}

এটি অনেক সংকলক পাশাপাশি অপ্টিমাইজ করা যেতে পারে।

এবং যাইহোক, আপনি যদি কোডটির বিশদ আচরণ পর্যবেক্ষণ করতে চান তবে আপনি কেবল অনুসরণ হিসাবে করতে পারেন:

gcc -c test.c objdump -d test.o> obj.s

তারপরে, আপত্তি.ইন খুলুন, আপনি উত্তরটি খুঁজে পেতে পারেন।


1

শাখায় ইঙ্গিতের উপসর্গগুলি তৈরি করতে তারা সংকলককে ইঙ্গিত দিচ্ছে। X86 / x64 এ, তারা একটি বাইট নেয়, যাতে আপনি প্রতিটি শাখার জন্য সর্বাধিক এক বাইট বৃদ্ধি পাবেন। কর্মক্ষমতা হিসাবে, এটি পুরোপুরি আবেদনের উপর নির্ভর করে - বেশিরভাগ ক্ষেত্রে, প্রসেসরের শাখার ভবিষ্যদ্বাণী আজকাল তাদের উপেক্ষা করবে।

সম্পাদনা করুন: তারা সত্যিকার অর্থে সহায়তা করতে পারে এমন এক জায়গার কথা ভুলে গেছেন। এটি 'সম্ভাব্য' পাথের জন্য নেওয়া শাখাগুলির সংখ্যা হ্রাস করতে কন্ট্রোলারটিকে নিয়ন্ত্রণ-প্রবাহ গ্রাফটিকে পুনরায় সাজানোর অনুমতি দিতে পারে। আপনি একাধিক প্রস্থান কেস পরীক্ষা করছেন যেখানে লুপগুলিতে এটির একটি উল্লেখযোগ্য উন্নতি হতে পারে।


10
gcc কখনই x86 শাখার ইঙ্গিত জেনারেট করে না - কমপক্ষে সমস্ত ইন্টেল সিপিইউ সেগুলি এড়িয়ে চলবে ignore এটি ইনলাইনিং এবং লুপ আন্রোলিং এড়িয়ে সম্ভাব্য অঞ্চলে কোডের আকার সীমাবদ্ধ করার চেষ্টা করবে though
অ্যালেক্স অদ্ভুত

1

প্রোগ্রামারটির জন্য जीসিসির কাজগুলি হ'ল প্রদত্ত অভিব্যক্তিতে সবচেয়ে সম্ভবত শাখার অবস্থা কী হবে সে সম্পর্কে কম্পাইলারকে একটি ইঙ্গিত দেয়। এটি সংযোগকারীটিকে শাখার নির্দেশাবলী তৈরি করতে সহায়তা করে যাতে সর্বাধিক সাধারণ কেসটি সম্পাদন করতে খুব কম সংখ্যক নির্দেশনা নেয়।

শাখার নির্দেশাবলী কীভাবে তৈরি করা হয় তা প্রসেসরের আর্কিটেকচারের উপর নির্ভর করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.