কার্নেলের সম্ভাব্য এবং সম্ভাব্য কলগুলির মধ্যে পার্থক্য কী?


11

কার্নেলের মধ্যে সম্ভাব্য এবং সম্ভাব্য কলগুলির মধ্যে কী রয়েছে। কার্নেল উত্স অনুসন্ধান করার সময় আমি এই বিবৃতি পেয়েছি।

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

কেউ কি এর মধ্যে কিছু আলোকপাত করতে পারে?


এটি সত্যিই একটি প্রোগ্রামিং প্রশ্ন, স্ট্যাক ওভিফর্ফ্লোয়ের পক্ষে আরও উপযুক্ত ।
গিলস 'এ-দুষ্ট হওয়া বন্ধ করুন'

উত্তর:


14

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

এগুলি এ জাতীয়ভাবে ব্যবহৃত হয়:

if (likely(some_condition)) {
  // the compiler will try and make the code layout optimal for the case
  // where some_condition is true, i.e. where this block is run
  most_likely_action();
} else {
  // this block is less frequently used
  corner_case();
}

এটি দুর্দান্ত যত্ন সহ ব্যবহার করা উচিত (যেমন প্রকৃত শাখা প্রোফাইলিংয়ের ফলাফলের ভিত্তিতে)। একটি ভুল ইঙ্গিত কর্মক্ষমতা হ্রাস করতে পারে (স্পষ্টতই)।

কোডটি কীভাবে অনুকূলিত করা যায় তার কয়েকটি উদাহরণ অনুসন্ধান করে সহজেই পাওয়া যায় GCC __builtin_expect। এই ব্লগ পোস্ট জিসিসি অপ্টিমাইজেশন: __builtin_expect উদাহরণস্বরূপ এটির সাথে একটি বিচ্ছিন্নতার বিবরণ দেয়।

যে ধরণের অপ্টিমাইজেশন করা যায় তা অত্যন্ত প্রসেসর-নির্দিষ্ট। সাধারণ ধারণাটি হ'ল প্রায়শই, প্রসেসরগুলি কোডটি দ্রুত চালাবে যদি এটি পুরো জায়গা জুড়ে শাখা / ঝাঁপ না দেয়। এটি যত বেশি লিনিয়ার হয়, এবং শাখাগুলি যত বেশি অনুমানযোগ্য হয় তত দ্রুত চালিত হবে। (উদাহরণস্বরূপ গভীর পাইপলাইন সহ প্রসেসরের ক্ষেত্রে এটি সত্য true

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


ইউনিকর্ন বলতে কী বোঝায় ? এটি কোনও প্রযুক্তিগত শব্দ বা কেবল একটি ফিলার?
সেন

আমি বিভ্রান্তি এড়াতে ইউনিকর্নগুলি সরিয়েছি।
মাদুর

আপনি কি দয়া করে সংকলকটিতে বিস্তারিতভাবে চেষ্টা করুন এবং কেসটির জন্য কোড বিন্যাসটিকে সর্বোত্তম করে তুলবেন ? আমি এটি কীভাবে তা জানতে চাই।
সেন

সে সম্পর্কে কিছুটা তথ্য যুক্ত করেছে। কোডটি অপ্টিমাইজ করার কোনও সাধারণ উপায় নেই, এটি সবই খুব প্রসেসর নির্ভর।
মাদুর

2

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

প্রত্যাশা ছাড়াই

#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ফিরে।

প্রত্যাশার সাথে

এখন এর সাথে প্রতিস্থাপন করুন 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 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 এই সি ++ বিল্ট-ইনগুলি মানক করেছে: /programming/51797959/how-to-use-c20s- Likely-unlikely-attribute-in-if-else-statement তারা সম্ভবত (একটি পাং!) একই জিনিস।

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