'যদি' এর চেয়ে 'সুইচ' দ্রুত হয়?


242

একটি switchবিবৃতি আসলে একটি বিবৃতি চেয়ে দ্রুত if?

আমি /Oxপতাকাটির সাথে ভিজুয়াল স্টুডিও 2010 এর x64 সি ++ সংকলকটিতে নীচে কোডটি চালিয়েছি :

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define MAX_COUNT (1 << 29)
size_t counter = 0;

size_t testSwitch()
{
    clock_t start = clock();
    size_t i;
    for (i = 0; i < MAX_COUNT; i++)
    {
        switch (counter % 4 + 1)
        {
            case 1: counter += 4; break;
            case 2: counter += 3; break;
            case 3: counter += 2; break;
            case 4: counter += 1; break;
        }
    }
    return 1000 * (clock() - start) / CLOCKS_PER_SEC;
}

size_t testIf()
{
    clock_t start = clock();
    size_t i;
    for (i = 0; i < MAX_COUNT; i++)
    {
        const size_t c = counter % 4 + 1;
        if (c == 1) { counter += 4; }
        else if (c == 2) { counter += 3; }
        else if (c == 3) { counter += 2; }
        else if (c == 4) { counter += 1; }
    }
    return 1000 * (clock() - start) / CLOCKS_PER_SEC;
}

int main()
{
    printf("Starting...\n");
    printf("Switch statement: %u ms\n", testSwitch());
    printf("If     statement: %u ms\n", testIf());
}

এবং এই ফলাফলগুলি পেয়েছে:

বিবৃতি পরিবর্তন করুন: 5261 এমএস
যদি বিবৃতি হয়: 5196 এমএস

আমি যা শিখেছি তা থেকে, switchবিবৃতিগুলি ব্রাঞ্চিংকে অনুকূলিত করার জন্য দৃশ্যত জাম্প টেবিল ব্যবহার করে।

প্রশ্নাবলী:

  1. X86 বা x64 এ কোনও বেসিক জাম্প টেবিলটি কেমন হবে?

  2. এই কোডটি কি জাম্প টেবিল ব্যবহার করছে?

  3. এই উদাহরণে কোনও পারফরম্যান্সের পার্থক্য নেই কেন? সেখানে কোনো পরিস্থিতি যা আছে কি নেই একটি উল্লেখযোগ্য কর্মক্ষমতা পার্থক্য কি?


কোডটি বিযুক্ত করা:

testIf:

13FE81B10 sub  rsp,48h 
13FE81B14 call qword ptr [__imp_clock (13FE81128h)] 
13FE81B1A mov  dword ptr [start],eax 
13FE81B1E mov  qword ptr [i],0 
13FE81B27 jmp  testIf+26h (13FE81B36h) 
13FE81B29 mov  rax,qword ptr [i] 
13FE81B2E inc  rax  
13FE81B31 mov  qword ptr [i],rax 
13FE81B36 cmp  qword ptr [i],20000000h 
13FE81B3F jae  testIf+0C3h (13FE81BD3h) 
13FE81B45 xor  edx,edx 
13FE81B47 mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81B4E mov  ecx,4 
13FE81B53 div  rax,rcx 
13FE81B56 mov  rax,rdx 
13FE81B59 inc  rax  
13FE81B5C mov  qword ptr [c],rax 
13FE81B61 cmp  qword ptr [c],1 
13FE81B67 jne  testIf+6Dh (13FE81B7Dh) 
13FE81B69 mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81B70 add  rax,4 
13FE81B74 mov  qword ptr [counter (13FE835D0h)],rax 
13FE81B7B jmp  testIf+0BEh (13FE81BCEh) 
13FE81B7D cmp  qword ptr [c],2 
13FE81B83 jne  testIf+89h (13FE81B99h) 
13FE81B85 mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81B8C add  rax,3 
13FE81B90 mov  qword ptr [counter (13FE835D0h)],rax 
13FE81B97 jmp  testIf+0BEh (13FE81BCEh) 
13FE81B99 cmp  qword ptr [c],3 
13FE81B9F jne  testIf+0A5h (13FE81BB5h) 
13FE81BA1 mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81BA8 add  rax,2 
13FE81BAC mov  qword ptr [counter (13FE835D0h)],rax 
13FE81BB3 jmp  testIf+0BEh (13FE81BCEh) 
13FE81BB5 cmp  qword ptr [c],4 
13FE81BBB jne  testIf+0BEh (13FE81BCEh) 
13FE81BBD mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81BC4 inc  rax  
13FE81BC7 mov  qword ptr [counter (13FE835D0h)],rax 
13FE81BCE jmp  testIf+19h (13FE81B29h) 
13FE81BD3 call qword ptr [__imp_clock (13FE81128h)] 
13FE81BD9 sub  eax,dword ptr [start] 
13FE81BDD imul eax,eax,3E8h 
13FE81BE3 cdq       
13FE81BE4 mov  ecx,3E8h 
13FE81BE9 idiv eax,ecx 
13FE81BEB cdqe      
13FE81BED add  rsp,48h 
13FE81BF1 ret       

testSwitch:

13FE81C00 sub  rsp,48h 
13FE81C04 call qword ptr [__imp_clock (13FE81128h)] 
13FE81C0A mov  dword ptr [start],eax 
13FE81C0E mov  qword ptr [i],0 
13FE81C17 jmp  testSwitch+26h (13FE81C26h) 
13FE81C19 mov  rax,qword ptr [i] 
13FE81C1E inc  rax  
13FE81C21 mov  qword ptr [i],rax 
13FE81C26 cmp  qword ptr [i],20000000h 
13FE81C2F jae  testSwitch+0C5h (13FE81CC5h) 
13FE81C35 xor  edx,edx 
13FE81C37 mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81C3E mov  ecx,4 
13FE81C43 div  rax,rcx 
13FE81C46 mov  rax,rdx 
13FE81C49 inc  rax  
13FE81C4C mov  qword ptr [rsp+30h],rax 
13FE81C51 cmp  qword ptr [rsp+30h],1 
13FE81C57 je   testSwitch+73h (13FE81C73h) 
13FE81C59 cmp  qword ptr [rsp+30h],2 
13FE81C5F je   testSwitch+87h (13FE81C87h) 
13FE81C61 cmp  qword ptr [rsp+30h],3 
13FE81C67 je   testSwitch+9Bh (13FE81C9Bh) 
13FE81C69 cmp  qword ptr [rsp+30h],4 
13FE81C6F je   testSwitch+0AFh (13FE81CAFh) 
13FE81C71 jmp  testSwitch+0C0h (13FE81CC0h) 
13FE81C73 mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81C7A add  rax,4 
13FE81C7E mov  qword ptr [counter (13FE835D0h)],rax 
13FE81C85 jmp  testSwitch+0C0h (13FE81CC0h) 
13FE81C87 mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81C8E add  rax,3 
13FE81C92 mov  qword ptr [counter (13FE835D0h)],rax 
13FE81C99 jmp  testSwitch+0C0h (13FE81CC0h) 
13FE81C9B mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81CA2 add  rax,2 
13FE81CA6 mov  qword ptr [counter (13FE835D0h)],rax 
13FE81CAD jmp  testSwitch+0C0h (13FE81CC0h) 
13FE81CAF mov  rax,qword ptr [counter (13FE835D0h)] 
13FE81CB6 inc  rax  
13FE81CB9 mov  qword ptr [counter (13FE835D0h)],rax 
13FE81CC0 jmp  testSwitch+19h (13FE81C19h) 
13FE81CC5 call qword ptr [__imp_clock (13FE81128h)] 
13FE81CCB sub  eax,dword ptr [start] 
13FE81CCF imul eax,eax,3E8h 
13FE81CD5 cdq       
13FE81CD6 mov  ecx,3E8h 
13FE81CDB idiv eax,ecx 
13FE81CDD cdqe      
13FE81CDF add  rsp,48h 
13FE81CE3 ret       

হালনাগাদ:

আকর্ষণীয় ফলাফল এখানে । তবে কেন একটি দ্রুত এবং একজন ধীরে ধীরে তা নিশ্চিত নয়।


47
জনগণ এই চিন্তাভাবনাটি বন্ধ করতে ভোট দিচ্ছে? তারা কি পুরোপুরি অনুকূলকরণকারী সংকলকের ধারণাতে বিশ্বাসী যে আদর্শ কোডের তুলনায় এর উত্পন্ন করার কোনও চিন্তাও ধর্মবিরোধী? কোনও অপ্টিমাইজেশনের খুব ধারণা তাদের কোথাও আপত্তি করে?
ক্রাশ ওয়ার্কস

6
এই প্রশ্নে ঠিক কী ভুল?
Tugrul Ates

25
এই প্রশ্নের কী ভুল তা ভাবছেন যে কেউ : শুরুর জন্য, এটি একটি প্রশ্ন নয়, এটি 3 টি প্রশ্ন, যার অর্থ এখন উত্তর অনেকেরই বিভিন্ন সমস্যা রয়েছে। এর অর্থ হ'ল যে কোনও উত্তর যা সমস্ত কিছুর উত্তর দেয় তা গ্রহণ করা কঠিন হবে । তদ্ব্যতীত, উপরের প্রশ্নের সাধারণ হাঁটু-ঝাঁকুনির প্রতিক্রিয়া হ'ল এটি "সত্যই আকর্ষণীয় নয়" হিসাবে প্রায়শই বন্ধুত্বের কারণে এটি বেশিরভাগই অপ্টিমাইজেশনের এই স্তরে, আপনি প্রায় সবসময় অকালে অপ্টিমাইজ করছেন । শেষ অবধি, 5196 বনাম 5261 আসলে যত্ন নেওয়ার পক্ষে পর্যাপ্ত হওয়া উচিত নয়। যৌক্তিক কোডটি লিখুন যা বোঝা যায়।
লাসে ভি কার্লসেন

40
@ লাস: আপনি কি সত্যিই আমাকে পরিবর্তে এসওতে তিনটি প্রশ্ন পোস্ট করতে পছন্দ করেছেন ? এছাড়াও: 5196 vs. 5261 shouldn't be enough to actually care-> আপনি যদি প্রশ্নটি ভুল বুঝে থাকেন বা আমি আপনার মন্তব্যে ভুল বোঝে তবে আমি নিশ্চিত নই, তবে কেন আমার পার্থক্য নেই তা জিজ্ঞাসা করার পুরো বিষয়টি আমার কাছে নয় ? (আমি কি কখনও দাবি করেছিলাম যে যত্ন নেওয়ার ক্ষেত্রে এটি একটি তাত্পর্যপূর্ণ পার্থক্য?)
ব্যবহারকারী 541686

5
@ রবার্ট: আচ্ছা এটিতে 20 টিরও বেশি মন্তব্য রয়েছে কারণ তারা মেটা-মন্তব্য're এখানে প্রশ্নের সাথে সম্পর্কিত মাত্র 7 টি মন্তব্য রয়েছে। মতামত: আমি এখানে "মতামত" আছে তা দেখতে পাচ্ছি না। একটি কারণ আছে যে আমি কোনও পারফরম্যান্সের পার্থক্য দেখছি না, না? এটা কি শুধু স্বাদ? বিতর্ক: সম্ভবত, তবে এটি আমার কাছে স্বাস্থ্যকর ধরণের বিতর্কের মতো দেখাচ্ছে, যেমন আমি এসও-র অন্যান্য জায়গাগুলিতে দেখেছি (এর বিপরীতে কিছু আছে কিনা তা আমাকে জানান)। যুক্তি: আমি এখানে বিতর্কিত কিছু দেখছি না (যদি না আপনি এটিকে 'বিতর্ক' এর প্রতিশব্দ হিসাবে গ্রহণ করেন?) বর্ধিত আলোচনা: আপনি যদি এই মেটা-মন্তব্যগুলি অন্তর্ভুক্ত করেন।
ব্যবহারকারী541686

উত্তর:


122

একটি সংকলক একটি স্যুইচ করতে পারে এমন কয়েকটি অপ্টিমাইজেশন রয়েছে । আমি মনে করি না যে উপরে উল্লিখিত "জাম্প-টেবিল" একটি খুব দরকারী, যদিও এটি কেবল তখনই কাজ করে যখন ইনপুটটি কোনওভাবে আবদ্ধ করা যায়।

একটি "লাফ টেবিল" জন্য সি Pseudocode ভালো কিছু হবে এই মনে রাখবেন যে বাস্তবে কম্পাইলার যদি টেবিলের চারপাশে পরীক্ষা নিশ্চিত করার যে ইনপুট টেবিলের বৈধ ছিল কিছু ফর্ম সন্নিবেশ করতে হবে -। এটি নোট করুন যে এটি কেবলমাত্র নির্দিষ্ট ক্ষেত্রে কাজ করে যে ইনপুটটি ধারাবাহিক সংখ্যার রান।

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

আপনার নির্দিষ্ট প্রশ্নের উত্তর দিতে:

  1. ঝনঝন উত্পন্ন এক যে মত দেখাচ্ছে এই :

    test_switch(char):                       # @test_switch(char)
            movl    %edi, %eax
            cmpl    $19, %edi
            jbe     .LBB0_1
            retq
    .LBB0_1:
            jmpq    *.LJTI0_0(,%rax,8)
            jmp     void call<0u>()         # TAILCALL
            jmp     void call<1u>()         # TAILCALL
            jmp     void call<2u>()         # TAILCALL
            jmp     void call<3u>()         # TAILCALL
            jmp     void call<4u>()         # TAILCALL
            jmp     void call<5u>()         # TAILCALL
            jmp     void call<6u>()         # TAILCALL
            jmp     void call<7u>()         # TAILCALL
            jmp     void call<8u>()         # TAILCALL
            jmp     void call<9u>()         # TAILCALL
            jmp     void call<10u>()        # TAILCALL
            jmp     void call<11u>()        # TAILCALL
            jmp     void call<12u>()        # TAILCALL
            jmp     void call<13u>()        # TAILCALL
            jmp     void call<14u>()        # TAILCALL
            jmp     void call<15u>()        # TAILCALL
            jmp     void call<16u>()        # TAILCALL
            jmp     void call<17u>()        # TAILCALL
            jmp     void call<18u>()        # TAILCALL
            jmp     void call<19u>()        # TAILCALL
    .LJTI0_0:
            .quad   .LBB0_2
            .quad   .LBB0_3
            .quad   .LBB0_4
            .quad   .LBB0_5
            .quad   .LBB0_6
            .quad   .LBB0_7
            .quad   .LBB0_8
            .quad   .LBB0_9
            .quad   .LBB0_10
            .quad   .LBB0_11
            .quad   .LBB0_12
            .quad   .LBB0_13
            .quad   .LBB0_14
            .quad   .LBB0_15
            .quad   .LBB0_16
            .quad   .LBB0_17
            .quad   .LBB0_18
            .quad   .LBB0_19
            .quad   .LBB0_20
            .quad   .LBB0_21
  2. আমি বলতে পারি যে এটি কোনও জাম্প টেবিল ব্যবহার করছে না - 4 তুলনা নির্দেশাবলী স্পষ্টভাবে দৃশ্যমান:

    13FE81C51 cmp  qword ptr [rsp+30h],1 
    13FE81C57 je   testSwitch+73h (13FE81C73h) 
    13FE81C59 cmp  qword ptr [rsp+30h],2 
    13FE81C5F je   testSwitch+87h (13FE81C87h) 
    13FE81C61 cmp  qword ptr [rsp+30h],3 
    13FE81C67 je   testSwitch+9Bh (13FE81C9Bh) 
    13FE81C69 cmp  qword ptr [rsp+30h],4 
    13FE81C6F je   testSwitch+0AFh (13FE81CAFh) 

    একটি জাম্প টেবিল ভিত্তিক সমাধানটি তুলনা মোটেই ব্যবহার করে না।

  3. হয় সংখ্যক সংযোগকারী একটি লাফ টেবিল তৈরির কারণ হিসাবে পর্যাপ্ত শাখা নয়, বা আপনার সংকলক কেবল সেগুলি তৈরি করে না। আমি নিশ্চিত না কোনটি।

সম্পাদনা 2014 : এলএলভিএম অপটিমাইজারের সাথে পরিচিত ব্যক্তিদের কাছ থেকে অন্য কোথাও কিছু আলোচনা হয়েছে যে বলে যে লাফ টেবিল অপটিমাইজেশন অনেক পরিস্থিতিতে গুরুত্বপূর্ণ হতে পারে; উদাহরণস্বরূপ যেখানে উল্লেখযোগ্য গণনার ক্ষেত্রে অনেক মান সহ একটি গণনা রয়েছে এবং মানগুলির বিরুদ্ধে অনেকগুলি ক্ষেত্রে। এটি বলেছিল, ২০১১ সালে আমি উপরে যা বলেছি তার সাথে আমি দাঁড়িয়ে আছি - প্রায়শই আমি লোকদের ভাবতে দেখি "আমি যদি এটি স্যুইচ করে রাখি তবে একই সময়ে আমার পক্ষে যত মামলা আসবে না কেন" - এবং এটি সম্পূর্ণ মিথ্যা। এমনকি একটি জাম্প টেবিলের সাথেও আপনি পরোক্ষ লাফের দাম পান এবং আপনি প্রতিটি ক্ষেত্রে টেবিলের প্রবেশের জন্য অর্থ প্রদান করেন; এবং মেমোরি ব্যান্ডউইথ আধুনিক হার্ডওয়্যার উপর একটি বড় চুক্তি।

পাঠযোগ্যতার জন্য কোড লিখুন। এর লবণের মূল্যের যে কোনও সংকলক যদি মই দেখতে পায় এবং অন্য কোনও সিঁড়ি এবং এটি সমতুল্য স্যুইচ বা এর বিপরীতে রূপান্তরিত হয় তবে তা করা আরও দ্রুত হবে be


3
প্রকৃতপক্ষে প্রশ্নের উত্তর দেওয়ার জন্য এবং দরকারী তথ্যের জন্য +1। :-) তবে, একটি প্রশ্ন: আমি যা বুঝতে পারি তা থেকে একটি জাম্প টেবিল অপ্রত্যক্ষ জাম্প ব্যবহার করে ; এটা কি ঠিক? যদি তা হয়, তবে আরও বেশি প্রিফেচিং / পাইপলাইনিংয়ের কারণে এটি সাধারণত ধীর হয় না?
ব্যবহারকারী541686

1
@ মেহরদাদ: হ্যাঁ, এটি পরোক্ষ লাফ ব্যবহার করে। তবে একটি পরোক্ষ লাফ (পাইপলাইন স্টল সহ এটি আসে) শত শত সরাসরি জাম্পের চেয়ে কম হতে পারে। :)
বিলি ওনিল

1
@ মেহরদাদ: না, দুর্ভাগ্যক্রমে। :( আমি খুশি যে আমি এমন লোকদের শিবিরে রয়েছি যারা সবসময় ভাবেন যে IF আরও বেশি পাঠযোগ্য! :)
বিলি ওনিল

1
কয়েকটি কুইপস - "[স্যুইচগুলি] কেবল তখনই কাজ করে যখন ইনপুটটি কোনও উপায়ে আবদ্ধ করা যায়" "টেবিলে টেপটি বৈধ ছিল কিনা তা পরীক্ষা করার জন্য টেস্টের কিছু ফর্ম সন্নিবেশ করা দরকার। এছাড়াও নোট করুন যে এটি কেবলমাত্র নির্দিষ্ট ক্ষেত্রে কাজ করে যদি ইনপুটটি ধারাবাহিক সংখ্যার একটি রান "": এটি একটি বিচ্ছিন্ন জনবহুল টেবিল পাওয়া সম্পূর্ণভাবে সম্ভব, যেখানে সম্ভাব্য পয়েন্টারটি পড়া হয় এবং কেবল যদি অ-এনইউএলএল একটি লাফ সঞ্চালিত হয়, অন্যথায় যদি কোনওটিতে লাফানো হয় তবে ডিফল্ট কেস, তারপর switchপ্রস্থান। সোরেন এই উত্তরটি পড়ার পরে আরও কিছু কথা বলতে চেয়েছিলেন।
টনি ডেলরয়

2
"এর নুনের মূল্য নির্ধারণকারী কোনও সংকলক যদি একটি সিঁড়ি দেখতে পায় তবে মই এবং এটিকে সমতুল্য স্যুইচ বা তদ্বিপরীত রূপান্তরিত করে" - এই দৃ ?়তার জন্য কোনও সমর্থন? একটি সংকলক অনুমান করতে পারে যে আপনার ifধারাগুলির ক্রমটি ইতিমধ্যে ফ্রিকোয়েন্সি এবং আপেক্ষিক কার্য সম্পাদনের প্রয়োজনগুলির সাথে মেলে যাবার জন্য হ্যান্ড টিউন হয়েছে, যেখানে switchপ্রথাগতভাবে সংকলকটি চয়ন করলেও এটি অপ্টিমাইজ করার জন্য একটি উন্মুক্ত আমন্ত্রণ হিসাবে দেখা যায়। ভাল পয়েন্ট পুনরায় অতীত switch:-)। কোডের আকার কেস / রেঞ্জের উপর নির্ভর করে - এটি আরও ভাল হতে পারে। অবশেষে কিছু এনাম, বিট ফিল্ড এবং দৃশ্যগুলি charসহজাতভাবে বৈধ / সীমাবদ্ধ এবং ওভারহেড মুক্ত।
টনি ডেলরয়

47

আপনার প্রশ্নের উত্তর:

1. x86 বা x64 এ কোনও বেসিক জাম্প টেবিলটি কেমন হবে?

জাম্প টেবিলটি এমন মেমরি ঠিকানা যা অ্যারের কাঠামোর মতো লেবেলে পয়েন্টার ধারণ করে। নীচের উদাহরণটি আপনাকে বুঝতে সহায়তা করবে কীভাবে জাম্প টেবিলগুলি আউট রাখা হয়েছে

00B14538  D8 09 AB 00 D8 09 AB 00 D8 09 AB 00 D8 09 AB 00  Ø.«.Ø.«.Ø.«.Ø.«.
00B14548  D8 09 AB 00 D8 09 AB 00 D8 09 AB 00 00 00 00 00  Ø.«.Ø.«.Ø.«.....
00B14558  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00B14568  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

এখানে চিত্র বর্ণনা লিখুন

যেখানে 00B14538 জাম্প টেবিলের পয়েন্টার এবং D8 09 AB 00 এর মতো মান লেবেল পয়েন্টার উপস্থাপন করে।

২.এ কোডটি কী লাফ টেবিল ব্যবহার করছে? এই ক্ষেত্রে না।

৩. এই উদাহরণে পারফরম্যান্সের পার্থক্য নেই কেন?

পারফরম্যান্সের কোনও পার্থক্য নেই কারণ উভয় ক্ষেত্রেই নির্দেশ একই, কোনও জাম্প টেবিল।

৪.সামান্য পারফরম্যান্সের পার্থক্য রয়েছে এমন কোন পরিস্থিতি কি আছে?

যদি আপনার চেক থাকে কিনা খুব দীর্ঘ ক্রম থাকে, সেক্ষেত্রে জাম্প টেবিল ব্যবহার করে কর্মক্ষমতা উন্নত হয় (ব্রাঞ্চিং / জেএমপি নির্দেশাবলী যদি তারা নিখুঁতভাবে পূর্বাভাস না দেয় তবে ব্যয়বহুল ) তবে মেমরির দাম সহ আসে।

সমস্ত তুলনামূলক নির্দেশাবলীর কোডেরও কিছু আকার রয়েছে, তাই বিশেষত 32-বিট পয়েন্টার বা অফসেটের সাথে, একটি একক জাম্প টেবিল লুঠনের ফলে এক্সিকিউটেবলের জন্য অনেক বেশি আকারের ব্যয় করতে হবে না।

উপসংহার: সংকলক যথেষ্ট পরিমাণে স্মার্ট এবং উপযুক্ত নির্দেশাবলী জেনারেট করে :)


(সম্পাদনা: এনভিএম, বিলির উত্তরটিতে ইতিমধ্যে যা আমি পরামর্শ দিচ্ছিলাম তা রয়েছে I আমি অনুমান করি এটি একটি দুর্দান্ত সমৃদ্ধি)) gcc -Sআউটপুট অন্তর্ভুক্ত করা ভাল হবে : .long L1/ .long L2টেবিলের প্রবেশের অনুক্রমটি হেক্সডাম্পের চেয়ে বেশি অর্থবহ এবং কারও কাছে আরও কার্যকর সংকলক তাকান কিভাবে শিখতে চায়। (যদিও আমি অনুমান করেছি যে আপনি কেবল স্যুইচ কোডটি দেখুন এটি অপ্রত্যক্ষ জেএমপি বা জিসিসির একটি গুচ্ছ ছিল কিনা তা দেখতে)।
পিটার কর্ডেস

31

সংকলকটি সুইচ স্টেটমেন্টটিকে কোড হিসাবে সংকলন করতে ইফ-স্টেটমেন্টের সমতুল্য বা জাম্প টেবিল তৈরি করতে মুক্ত is এটি সম্ভবত সবচেয়ে দ্রুত কার্যকর করতে পারে বা আপনার সংকলক বিকল্পগুলির মধ্যে নির্দিষ্ট করে দেওয়া কিছুটা ক্ষুদ্রতম কোড উত্পন্ন করবে তার উপর ভিত্তি করে অন্যটির একটি বেছে নেবে - তাই সবচেয়ে খারাপ ক্ষেত্রে এটি একই গতি হবে যদি বিবৃতিগুলির মতো হয়

আমি সর্বোত্তম পছন্দটি করতে সংস্থাপককে বিশ্বাস করব এবং কোডটি কী সর্বাধিক পাঠযোগ্য।

যদি মামলার সংখ্যা খুব বড় হয়ে যায় তবে একটি জাম্প টেবিল যদি এর সিরিজের চেয়ে অনেক দ্রুত হবে। তবে মানগুলির মধ্যে ধাপগুলি যদি খুব বড় হয় তবে জাম্প টেবিলটি বড় হতে পারে এবং সংকলকটি এটি তৈরি না করাকে বেছে নিতে পারে।


13
আমি মনে করি না এটি ওপি-র প্রশ্নের উত্তর দেয়। মোটেই
বিলি ওনিল

5
@ সোরেন: যদি এটি "প্রাথমিক প্রশ্ন" হত তবে আমি প্রশ্নটির অন্যান্য 179 লাইন নিয়ে বিরক্ত করতাম না, এটি সবেমাত্র 1 লাইন হত been :-)
user541686

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

2
একটি জাম্প টেবিল কী এবং আপনার সংজ্ঞার উপর নির্ভর করে কোনটির মধ্যে একটি অস্পষ্ট রেখা রয়েছে। আমি সাব-প্রশ্ন অংশ 3 সম্পর্কিত তথ্য সরবরাহ করেছি
সোরেন

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

13

আপনি কীভাবে জানবেন যে আপনার কম্পিউটার স্যুইচ টেস্ট লুপ চলাকালীন পরীক্ষার সাথে সম্পর্কিত কিছু কাজ করছে না এবং পরীক্ষার লুপের সময় কম কাজ সম্পাদন করছে? আপনার পরীক্ষার ফলাফলগুলি এর মতো কিছু দেখায় না:

  1. পার্থক্য খুব সামান্য
  2. কেবলমাত্র একটি ফলাফল রয়েছে, ফলাফলের সিরিজ নয়
  3. খুব কম কেস আছে

আমার ফলাফল:

আমি যুক্ত:

printf("counter: %u\n", counter);

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

আপনার কোড সহ অন্যান্য সমস্যাটি হ'ল:

switch (counter % 4 + 1)

আপনার সুইচ লুপ, বনাম

const size_t c = counter % 4 + 1; 

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

ওহ এবং আমি মনে করি আপনারও পরীক্ষার মধ্যে পাল্টা পুনরায় সেট করা উচিত। প্রকৃতপক্ষে, আপনি সম্ভবত +1, +2, +3 ইত্যাদির পরিবর্তে কিছু ধরণের এলোমেলো নম্বর ব্যবহার করা উচিত কারণ এটি সম্ভবত সেখানে কিছুটা অনুকূল করে দেবে। এলোমেলো সংখ্যার দ্বারা, আমি বর্তমান সময়ের উপর নির্ভর করে একটি সংখ্যা বোঝাচ্ছি, উদাহরণস্বরূপ। অন্যথায়, সংকলক আপনার উভয় ফাংশনকে একটি দীর্ঘ গণিত ক্রিয়ায় রূপান্তর করতে পারে এবং এমনকি কোনও লুপ নিয়ে বিরক্তও করতে পারে না।

আমি রায়ের কোডটি যথেষ্ট পরিমাণে সংশোধন করেছি যে কোডটি চালুর আগে সংকলক জিনিসগুলি বের করতে পারে না তা নিশ্চিত করার জন্য:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define MAX_COUNT (1 << 26)
size_t counter = 0;

long long testSwitch()
{
    clock_t start = clock();
    size_t i;
    for (i = 0; i < MAX_COUNT; i++)
    {
        const size_t c = rand() % 20 + 1;

        switch (c)
        {
                case 1: counter += 20; break;
                case 2: counter += 33; break;
                case 3: counter += 62; break;
                case 4: counter += 15; break;
                case 5: counter += 416; break;
                case 6: counter += 3545; break;
                case 7: counter += 23; break;
                case 8: counter += 81; break;
                case 9: counter += 256; break;
                case 10: counter += 15865; break;
                case 11: counter += 3234; break;
                case 12: counter += 22345; break;
                case 13: counter += 1242; break;
                case 14: counter += 12341; break;
                case 15: counter += 41; break;
                case 16: counter += 34321; break;
                case 17: counter += 232; break;
                case 18: counter += 144231; break;
                case 19: counter += 32; break;
                case 20: counter += 1231; break;
        }
    }
    return 1000 * (long long)(clock() - start) / CLOCKS_PER_SEC;
}

long long testIf()
{
    clock_t start = clock();
    size_t i;
    for (i = 0; i < MAX_COUNT; i++)
    {
        const size_t c = rand() % 20 + 1;
        if (c == 1) { counter += 20; }
        else if (c == 2) { counter += 33; }
        else if (c == 3) { counter += 62; }
        else if (c == 4) { counter += 15; }
        else if (c == 5) { counter += 416; }
        else if (c == 6) { counter += 3545; }
        else if (c == 7) { counter += 23; }
        else if (c == 8) { counter += 81; }
        else if (c == 9) { counter += 256; }
        else if (c == 10) { counter += 15865; }
        else if (c == 11) { counter += 3234; }
        else if (c == 12) { counter += 22345; }
        else if (c == 13) { counter += 1242; }
        else if (c == 14) { counter += 12341; }
        else if (c == 15) { counter += 41; }
        else if (c == 16) { counter += 34321; }
        else if (c == 17) { counter += 232; }
        else if (c == 18) { counter += 144231; }
        else if (c == 19) { counter += 32; }
        else if (c == 20) { counter += 1231; }
    }
    return 1000 * (long long)(clock() - start) / CLOCKS_PER_SEC;
}

int main()
{
    srand(time(NULL));
    printf("Starting...\n");
    printf("Switch statement: %lld ms\n", testSwitch()); fflush(stdout);
    printf("counter: %d\n", counter);
    counter = 0;
    srand(time(NULL));
    printf("If     statement: %lld ms\n", testIf()); fflush(stdout);
    printf("counter: %d\n", counter);
} 

স্যুইচ করুন: 3740
যদি: 3980

(একাধিক প্রচেষ্টা উপর একই ফলাফল)

আমি কেস / আইএফএসের সংখ্যাও হ্রাস করে 5 করেছি এবং স্যুইচ ফাংশনটি এখনও জিতেছে।


ইড্ক, আমি এটি প্রমাণ করতে পারি না; আপনি কি আলাদা ফলাফল পাবেন?
ব্যবহারকারী541686

+1: বেঞ্চমার্কিং কঠিন, আপনি সাধারণ কম্পিউটারে একক রান করার ক্ষেত্রে অল্প সময়ের পার্থক্য থেকে সত্যই কোনও সিদ্ধান্ত আঁকতে পারবেন না। আপনি প্রচুর পরীক্ষা চালানোর চেষ্টা করতে পারেন এবং ফলাফলগুলি সম্পর্কে কিছু পরিসংখ্যান করতে পারেন। অথবা একটি এমুলেটরে নিয়ন্ত্রিত প্রয়োগের উপর প্রসেসরের চক্র গণনা করা হচ্ছে।
টমাস প্যাড্রন-ম্যাকার্থি

Er, ঠিক যেখানে আপনি যোগ হয়নি printবক্তব্য? আমি পুরো প্রোগ্রামটির শেষে এটি যুক্ত করেছিলাম এবং কোনও পার্থক্য দেখিনি। আমি বুঝতে পারছি না যে অন্যটির সাথে "সমস্যা" কি ... ... "খুব বড় পার্থক্য" কী তা বোঝানোর মন করুন?
ব্যবহারকারী541686

1
@ BobTurbo: 45983493 12 ঘন্টা পেরিয়ে গেছে। এটা কি টাইপো ছিল?
Gus

1
দুর্দান্ত, এখন আমাকে আবার এটি করতে হবে :)
বব টার্বো

7

এমএসভিসির মতো একটি ভাল অনুকূলকরণ সংকলক উত্পন্ন করতে পারে:

  1. কেসগুলি দীর্ঘ দীর্ঘ পরিসরে সাজানো থাকলে একটি সহজ জাম্প টেবিল
  2. যদি অনেক ফাঁক থাকে তবে একটি স্পারস (দ্বি-স্তরের) জাম্প টেবিল
  3. আইফিসের একটি সিরিজ যদি কেসের সংখ্যা কম হয় বা মানগুলি একসাথে না থাকে
  4. যদি কেসগুলি ঘনিষ্ঠভাবে ব্যবধানযুক্ত রেঞ্জের বিভিন্ন গ্রুপের প্রতিনিধিত্ব করে তবে উপরের সংমিশ্রণটি।

সংক্ষেপে, যদি সুইচটি ifs এর একটি ধারাবাহিকের চেয়ে ধীর বলে মনে হয়, সংকলকটি কেবল এটি একটিতে রূপান্তর করতে পারে। এবং এটি সম্ভবত প্রতিটি ক্ষেত্রে তুলনাগুলির ক্রম নয়, তবে একটি বাইনারি অনুসন্ধান ট্রি হবে। একটি উদাহরণের জন্য এখানে দেখুন ।


প্রকৃতপক্ষে, একটি সংকলক এটি একটি হ্যাশ এবং জাম্পের সাথে প্রতিস্থাপন করতেও সক্ষম, যা আপনার প্রস্তাবিত স্পার দ্বি-স্তরের সমাধানের চেয়ে আরও ভাল সম্পাদন করে।
এলিস

5

আমি 2 টি উত্তর দেব) এবং কিছু সাধারণ মন্তব্য করব। 2) না, আপনার পোস্ট করা সমাবেশ কোডটিতে কোনও জাম্প টেবিল নেই। একটি জাম্প টেবিল হ'ল জাম্প গন্তব্যের একটি টেবিল এবং টেবিল থেকে সরাসরি কোনও সূচী স্থানে লাফানোর জন্য এক বা দুটি নির্দেশ। যখন সম্ভাব্য অনেকগুলি স্যুইচ গন্তব্য থাকে তখন একটি জাম্প টেবিল আরও বোধগম্য হয়। হয়তো অপটিমাইজারটি সহজ জানেন যদি অন্য যুক্তি দ্রুত না হয় তবে গন্তব্যগুলির সংখ্যা কিছু প্রান্তিকের চেয়ে বেশি না হয়। 4 এর পরিবর্তে 20 সম্ভাবনা বলার সাথে আবার আপনার উদাহরণ ব্যবহার করে দেখুন।


# 2 এর উত্তরের জন্য ধন্যবাদ! :) (বিটিডব্লিউ, আরও সম্ভাবনা সহ ফলাফল এখানে রয়েছে))
ব্যবহারকারীর 41১6868686

4

আমি কৌতূহল ছিলাম, এবং সুইচ স্টেটমেন্টটি দ্রুত চালিত করার জন্য আপনার উদাহরণ সম্পর্কে আমি কী পরিবর্তন করতে পারি তা একবার দেখেছি।

যদি আপনি 40 টিতে স্টেটমেন্ট পেয়ে থাকেন এবং একটি 0 কেস যোগ করেন তবে ইফ ব্লকটি সমতুল্য সুইচ স্টেটমেন্টের চেয়ে ধীর হয়ে চলবে। আমি এখানে ফলাফল আছে: https://www.ideone.com/KZeCz

0 কেস অপসারণের প্রভাবটি এখানে দেখা যাবে: https://www.ideone.com/LFnrX


1
আপনার লিঙ্কগুলি ভেঙে গেছে।
টিএস

4

পুরানো (এখন খুঁজে পাওয়া শক্ত) বেঞ্চের ++ বেঞ্চমার্কের কিছু ফলাফল এখানে রয়েছে:

Test Name:   F000003                         Class Name:  Style
CPU Time:       0.781  nanoseconds           plus or minus     0.0715
Wall/CPU:        1.00  ratio.                Iteration Count:  1677721600
Test Description:
 Time to test a global using a 2-way if/else if statement
 compare this test with F000004

Test Name:   F000004                         Class Name:  Style
CPU Time:        1.53  nanoseconds           plus or minus     0.0767
Wall/CPU:        1.00  ratio.                Iteration Count:  1677721600
Test Description:
 Time to test a global using a 2-way switch statement
 compare this test with F000003

Test Name:   F000005                         Class Name:  Style
CPU Time:        7.70  nanoseconds           plus or minus      0.385
Wall/CPU:        1.00  ratio.                Iteration Count:  1677721600
Test Description:
 Time to test a global using a 10-way if/else if statement
 compare this test with F000006

Test Name:   F000006                         Class Name:  Style
CPU Time:        2.00  nanoseconds           plus or minus     0.0999
Wall/CPU:        1.00  ratio.                Iteration Count:  1677721600
Test Description:
 Time to test a global using a 10-way switch statement
 compare this test with F000005

Test Name:   F000007                         Class Name:  Style
CPU Time:        3.41  nanoseconds           plus or minus      0.171
Wall/CPU:        1.00  ratio.                Iteration Count:  1677721600
Test Description:
 Time to test a global using a 10-way sparse switch statement
 compare this test with F000005 and F000006

আমরা এটি থেকে যা দেখতে পাচ্ছি তা হ'ল (এই মেশিনে, এই সংকলক সহ - ভিসি ++ 9.0 এক্স 64), প্রতিটি ifপরীক্ষায় প্রায় 0.7 ন্যানোসেকেন্ড লাগে। পরীক্ষার সংখ্যা বাড়ার সাথে সাথে সময়টি প্রায় পুরোপুরি রৈখিকভাবে স্কেল করে।

স্যুইচ বিবৃতি দিয়ে, মানগুলি যতক্ষণ ঘন হয় ততক্ষণ 2-উপায় এবং 10-ওয়ে পরীক্ষার মধ্যে গতির প্রায় কোনও পার্থক্য নেই। স্পারস মান সহ 10-উপায়ের পরীক্ষাটি ঘন মানগুলির সাথে 10-উপায় পরীক্ষার মতো প্রায় 1.6x সময় নেয় - তবে এমনকি বিরল মানের সাথে, 10-ওয়ে if/ এর গতির দ্বিগুণ চেয়েও ভালelse if

নীচের লাইন: কেবল একটি 4-ওয়ে পরীক্ষা ব্যবহার করে আপনাকে বনাম / এর পারফরম্যান্স সম্পর্কে সত্যিই বেশি কিছু দেখাবে না । আপনি যদি এই কোডটি থেকে নম্বরগুলি দেখেন তবে 4-টি পরীক্ষার জন্য, আমরা উভয়টি বেশ একইরকম ফলাফল ( / ২.৮ এর জন্য ন্যানোসেকেন্ডের জন্য / / ~ ২.০ ) আশা করি interswitchifelseifelseswitch


1
এটি কী করে তৈরি করা যায় তা জানা খুব কঠিন তবে যদি পরীক্ষাটি ইচ্ছাকৃতভাবে if/ elseচেইন বনামের শেষে বা তার সাথে ছড়িয়ে পড়া ইত্যাদির শেষে মেলে না এমন একটি মান সন্ধান করে কিনা তা আমরা জানি না। bench++10 পরে উত্সগুলি খুঁজে পাই না মিনিট গুগলিং।
টনি ডেলরয়

3

মনে রাখবেন যে যখন কোনও স্যুইচটি কোনও জাম্প টেবিলটিতে সংকলিত হয় না, আপনি সুইচের চেয়ে দক্ষতার সাথে থাকলে প্রায়শই লিখতে পারেন ...

(1) যদি সমস্ত এন এর জন্য সবচেয়ে খারাপ কেস টেস্টিংয়ের পরিবর্তে কেসগুলির অর্ডার থাকে তবে আপনি যদি লিখতে পারেন তবে উপরের বা নীচের অর্ধে যদি পরীক্ষা করতে হয় তবে তার প্রতিটি অর্ধে, বাইনারি অনুসন্ধান স্টাইল ... ফলস্বরূপ সবচেয়ে খারাপ ক্ষেত্রে এন এর চেয়ে লগএন হচ্ছে

(২) যদি নির্দিষ্ট কেস / গোষ্ঠী অন্যান্য মামলার তুলনায় অনেক বেশি ঘন ঘন হয় তবে আপনার ক্ষেত্রে যদি প্রথমে সেই কেসগুলিকে আলাদা করতে হয় তার মাধ্যমে ডিজাইনের মাধ্যমে গড় সময়ের গতি বাড়ানো যায়


এটি স্পষ্টত অসত্য; সংকলকগণ এই অপটিমাইজেশনের দুটি তৈরির তুলনায় সক্ষম।
এলিস

1
অ্যালিস, কোনও সংকলক কীভাবে আপনার প্রত্যাশিত কাজের চাপের ক্ষেত্রে অন্যান্য মামলার চেয়ে বেশি ঘটবে তা জানতে হবে? (এ: এটি সম্ভবত জানতে পারে না, সুতরাং এটি সম্ভবত
ব্রায়ান কেনেডি

(1) সহজেই করা যায়, এবং কিছু সংকলকগুলিতে কেবল বাইনারি অনুসন্ধান করে। (২) বিভিন্ন উপায়ে পূর্বাভাস দেওয়া যায়, বা সংকলককে নির্দেশ করা যায়। আপনি কি কখনও জিসিসির "সম্ভাব্য" বা "সম্ভাবনা" ব্যবহার করেন নি?
অ্যালিস

এবং কিছু সংকলক প্রোগ্রামটি এমন একটি মোডে চালানোর অনুমতি দেয় যা পরিসংখ্যান সংগ্রহ করে এবং তারপরে সেই তথ্য থেকে অনুকূলিত হয়।
ফিল 1970

2

এইগুলি যদি না হয় তবে অন্যটি লাফিয়ে যদি অন্য লাফ দেয় ... একটি জাম্প টেবিলের ঠিকানাগুলির একটি টেবিল থাকে বা একটি হ্যাশ বা এর মতো কিছু ব্যবহার করা হত।

ত্বরান্বিত বা ধীরতর বিষয়গত। আপনি উদাহরণস্বরূপ কেস 1 প্রথমটির পরিবর্তে শেষ জিনিস হতে পারেন এবং যদি আপনার পরীক্ষার প্রোগ্রাম বা বাস্তব বিশ্ব প্রোগ্রামটি কেস 1 ব্যবহার করে তবে বেশিরভাগ সময় কোডটি এই প্রয়োগের সাথে ধীর হবে। সুতরাং কেবল প্রয়োগের উপর নির্ভর করে কেস তালিকাটি পুনরায় সাজানো একটি বড় পার্থক্য আনতে পারে।

আপনি যদি 1-4 এর পরিবর্তে 0-3 কেস ব্যবহার করেন তবে সংকলকটি একটি জাম্প টেবিল ব্যবহার করতে পারে, সংকলকটি যাইহোক আপনার +1 অপসারণ করা উচিত। সম্ভবত এটি আইটেমের সংখ্যা কম ছিল। উদাহরণস্বরূপ আপনি যদি এটি 0 - 15 বা 0 - 31 তৈরি করে থাকেন তবে এটি এটি কোনও টেবিলের সাহায্যে প্রয়োগ করেছে বা অন্য কোনও শর্টকাট ব্যবহার করেছে। সংস্থাপকটি উত্স কোডটির কার্যকারিতাটি পূরণ করার সাথে সাথে কীভাবে এটি এতক্ষণ জিনিস প্রয়োগ করে তা চয়ন করতে নিখরচায়। এবং এটি সংকলক পার্থক্য এবং সংস্করণ পার্থক্য এবং অপ্টিমাইজেশনের পার্থক্যগুলির মধ্যে যায়। আপনি যদি একটি জাম্প টেবিল চান তবে একটি ঝাঁপ টেবিল তৈরি করুন, যদি আপনি চান তবে অন্য গাছ যদি একটি অন্যথায় গাছ তৈরি করে। আপনি যদি সংকলকটি সিদ্ধান্ত নিতে চান তবে একটি স্যুইচ / কেস স্টেটমেন্ট ব্যবহার করুন।


2

তবে কেন একটি দ্রুত এবং একজন ধীরে ধীরে তা নিশ্চিত নয়।

এটি ব্যাখ্যা করা আসলে খুব কঠিন নয় ... আপনার যদি মনে থাকে যে সঠিকভাবে পূর্বাভাসিত শাখাগুলির চেয়ে ভুল অনুমানিত শাখাগুলি দশ থেকে কয়েক গুণ বেশি ব্যয়বহুল।

মধ্যে % 20 সংস্করণ, প্রথম ক্ষেত্রে / যদি সবসময় যে হিট অন্যতম। আধুনিক সিপিইউগুলি "শিখুন" কোন শাখা সাধারণত নেওয়া হয় এবং কোনটি নয়, তাই তারা সহজেই অনুমান করতে পারে যে এই শাখাটি লুপের প্রায় প্রতিটি পুনরাবৃত্তিতে কী আচরণ করবে। এটি ব্যাখ্যা করে যে "যদি" সংস্করণটি উড়ে যায়; এটি প্রথম পরীক্ষার আগে কখনও কার্যকর করতে হবে না এবং এটি (সঠিকভাবে) বেশিরভাগ পুনরাবৃত্তির জন্য সেই পরীক্ষার ফলাফলের পূর্বাভাস দেয়। স্পষ্টতই "স্যুইচ" কিছুটা ভিন্নভাবে প্রয়োগ করা হয় - সম্ভবত একটি জাম্প টেবিলও, যা গণিত শাখার জন্য ধীরে ধীরে ধন্যবাদ হতে পারে।

মধ্যে % 21 সংস্করণ, শাখা মূলত র্যান্ডম হয়। সুতরাং কেবল তাদের মধ্যে অনেকেই প্রতিটি পুনরুক্তি সম্পাদন করে না, সিপিইউ তারা কোন পথে যাবে তা অনুমান করতে পারে না। এটি এমন একটি পরিস্থিতি যেখানে কোনও জাম্প টেবিল (বা অন্যান্য "স্যুইচ" অপ্টিমাইজেশন) সাহায্য করবে।

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

এর সবকটি বলতে গেলে আমার উপরোক্ত ব্যাখ্যাটি মূলত অনুমান is :-)


2
শতগুণ ধীরগতি কোথা থেকে আসতে পারে তা আমি দেখছি না। একটি ভুল অনুমানিত শাখার সবচেয়ে খারাপ পরিস্থিতি হ'ল একটি পাইপলাইন স্টল, যা বেশিরভাগ আধুনিক সিপিইউতে 20 ডলার ধীর হবে। শতবার নয়। (ঠিক আছে, আপনি যদি কোনও পুরাতন নেটবার্স্ট চিপ ব্যবহার করেন তবে এটি 35x ধীর হতে পারে ...)
বিলি ওনিল

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

1
সত্য না. পি 4 (নেটবার্স্ট) এর 31 টি পাইপলাইন পর্যায় ছিল; স্যান্ডি ব্রিজের উল্লেখযোগ্যভাবে কম স্টেজ রয়েছে। আমি মনে করি "100 বা তত্সহ নির্দেশাবলীর কাজ হারাতে" এই অনুমানের অধীনে রয়েছে যে নির্দেশের ক্যাশেটি অবৈধ হয়ে যায়। বাস্তবে ঘটে এমন একটি সাধারণ পরোক্ষ লাফের জন্য, তবে একটি জাম্প টেবিলের মতো কোনও কিছুর জন্য সম্ভবত পরোক্ষ লাফের লক্ষ্য নির্দেশের ক্যাশে কোথাও থাকে।
বিলি ওনিল

@ বিলি: আমি মনে করি না যে আমরা একমত নই। আমার বক্তব্যটি ছিল: "ভুল পূর্বাভাসিত শাখাগুলি সঠিকভাবে পূর্বাভাসিত শাখাগুলির চেয়ে দশ থেকে কয়েক গুণ ব্যয়বহুল"। সামান্য অতিরঞ্জিত, সম্ভবত ... তবে আই-ক্যাশে এবং এক্সিকিউশন পাইপলাইন গভীরতায় কেবল আঘাতের চেয়ে আরও বেশি কিছু চলছে; আমি যা পড়েছি তা থেকে, একা ডিকোডের জন্য সারি হ'ল 20 ডলার।
নিমো

যদি শাখার পূর্বাভাস হার্ডওয়্যার কার্যকর করার পথটিকে ভুলভাবে অনুমান করে তবে ভুল পাইপ থেকে নির্দেশগুলি যে পাইপলাইনে রয়েছে সেগুলি কার্যকর করা স্থবির না করে কেবল যেখানে সরিয়ে দেওয়া হবে। এটি কীভাবে সম্ভব (বা আমি এটির ভুল ব্যাখ্যা করছি কিনা) আমারকোনও ধারণা নেই, তবে দৃশ্যতনেহালেমেভুলঅনুমান করা শাখা সহ কোনও পাইপলাইন স্টল নেই ? (তারপরে আবার, আমার কাছে আই 7 নেই; আমার আই 5 রয়েছে, সুতরাং এটি আমার ক্ষেত্রে প্রযোজ্য নয়))
ব্যবহারকারীর 415686

1

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

counter += (4 - counter % 4);

আপনি ব্যবহার করা উচিত সঠিক বর্ধিত অভিব্যক্তি হিসাবে আমার কাছে মনে হচ্ছে।

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