সি / সি ++ এ অন্য কোনও শিকল যদি শৃঙ্খলিত হয় সেভাবে কেন একটি সুইচ অনুকূলিত হয় না?


39

স্কয়ারের নিম্নলিখিত বাস্তবায়নটি সিএমপি / জে স্টেটমেন্টগুলির একটি সিরিজ তৈরি করে যেমন আমি যদি শৃঙ্খলাবদ্ধ হওয়ার কথা আশা করি তবে:

int square(int num) {
    if (num == 0){
        return 0;
    } else if (num == 1){
        return 1;
    } else if (num == 2){
        return 4;
    } else if (num == 3){
        return 9;
    } else if (num == 4){
        return 16;
    } else if (num == 5){
        return 25;
    } else if (num == 6){
        return 36;
    } else if (num == 7){
        return 49;
    } else {
        return num * num;
    }
}

এবং নিম্নলিখিতটি ফেরতের জন্য একটি ডেটা টেবিল তৈরি করে:

int square_2(int num) {
    switch (num){
        case 0: return 0;
        case 1: return 1;
        case 2: return 4;
        case 3: return 9;
        case 4: return 16;
        case 5: return 25;
        case 6: return 36;
        case 7: return 49;
        default: return num * num;
    }
}

জিসিসি শীর্ষেরটিকে নীচের অংশে অনুকূলিত করতে কেন অক্ষম?

রেফারেন্সের জন্য বিযুক্তি: https://godbolt.org/z/UP_igi

সম্পাদনা: মজার বিষয় হল, এমএসভিসি স্যুইচ কেসের জন্য ডেটা টেবিলের পরিবর্তে একটি জাম্প টেবিল তৈরি করে। এবং আশ্চর্যজনকভাবে, ঝনঝন তাদের একই ফলাফলের জন্য অনুকূল করে তোলে।


3
"অপরিজ্ঞাত আচরণ" বলতে কী বোঝ? যতক্ষণ পর্যবেক্ষণযোগ্য আচরণ একই হয়, সংকলক যেকোন সমাবেশ / মেশিন কোড চায় তা তৈরি করতে পারে
bolov

2
@ ব্যবহারকারী 207421 returnগুলি অগ্রাহ্য করছেন ; কেসগুলির কোনও হ'ল না breaks, সুতরাং স্যুইচটিরও একটি কার্যকর আদেশ কার্যকর হয়। প্রতিটি শাখায় যদি / অন্য চেইনের রিটার্ন থাকে তবে এই ক্ষেত্রে শব্দার্থবিজ্ঞানের সমতুল্য। অপ্টিমাইজেশন অসম্ভব নয় । একটি কাউন্টারে নমুনা আইসিসি হিসাবে কোনও ক্রিয়াকে অনুকূলিত করে না।
ব্যবহারকারী 1810087

9
সম্ভবত সবচেয়ে সহজ উত্তর ... জিসিসি কেবল এই কাঠামোটি দেখতে এবং এটি অনুকূলকরণ করতে সক্ষম নয় (এখনও)।
ব্যবহারকারী 1810087

3
আমি @ ব্যবহারকারী 1810087 এর সাথে একমত। আপনি কেবল সংকলক সংশোধন প্রক্রিয়াটির বর্তমান সীমানাটি পেয়ে গেছেন। একটি উপ-সাব-কেস যা বর্তমানে অপটিমাইজযোগ্য (কিছু সংকলক দ্বারা) হিসাবে স্বীকৃত নয়। প্রকৃতপক্ষে, অন্য প্রত্যেকটি-যদি চেইনটিকে সেভাবে অনুকূল করা যায় তবে কেবলমাত্র সেই উপসেট যেখানে ধ্রুবক মানের তুলনায় একই ভেরিয়েবল পরীক্ষা করা হয়।
রবার্তো ক্যাবনি

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

উত্তর:


29

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

এখন আসা if-else, এটি ঠিক বিপরীত। যদিও switch-caseধ্রুব সময়, executes শাখা সংখ্যা নির্বিশেষে if-elseশাখা একটি ছোট সংখ্যার জন্য অপ্টিমাইজ করা হয়। এখানে, আপনি আশা করতে পারেন যে সংকলকটি মূলত আপনি সেগুলি লিখেছেন সেভাবে একটি ধারাবাহিক তুলনা তৈরি করে।

সুতরাং যদি আমি ব্যবহার if-elseকরতাম কারণ আমি আশা করি যে বেশিরভাগ কলগুলি অন্যান্য মানের square()জন্য 0বা 1খুব কমই হবে, তবে টেবিল-অনুসন্ধানে এটি 'অনুকূলিতকরণ' আসলে আমার কোডটিকে আমার প্রত্যাশার চেয়ে ধীর করে দিতে পারে, ifপরিবর্তে ব্যবহারের জন্য আমার উদ্দেশ্যকে পরাস্ত করে could of a switch। সুতরাং এটি বিতর্কযোগ্য হলেও, আমি মনে করি যে জিসিসি সঠিক জিনিসটি করছে এবং ঝাঁকুনি তার অপ্টিমাইজেশনে অত্যধিক আগ্রাসী হচ্ছে।

কেউ মন্তব্য করে, একটি লিঙ্ক ভাগ করে নিয়েছিল যেখানে ঝাঁকুনি এই অপ্টিমাইজেশানটি করে এবং if-elseপাশাপাশি লুক -টেবিল ভিত্তিক কোডও জেনারেট করে । যখন আমরা ঝাঁকুনির সাহায্যে কেবলমাত্র সংখ্যা (এবং একটি ডিফল্ট) কমিয়ে দেই তখন কিছু উল্লেখযোগ্য ঘটে Some এটি আবার যদি ও স্যুইচ উভয়ের জন্য অভিন্ন কোড উত্পন্ন করে তবে এবার উভয়ের জন্য লক -টেবিল পদ্ধতির পরিবর্তে তুলনা করতে এবং চলতে চলেছে। এর অর্থ হ'ল এমনকি স্যুইচ-ফেভারিং বিড়ম্বনাও জানে যে মামলার সংখ্যা কম হলে 'যদি' প্যাটার্নটি আরও অনুকূল হয়!

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


2
হ্যাঁ, অপ্টিমাইজেশন হ'ল বহুতল তরোয়াল: তারা কী লিখবে, তারা কী চায়, কী পায় এবং আমরা এর জন্য কাকে অভিশাপ দিই।
উত্সাহক

1
"... তারপরে টেবিল-অনুসন্ধানে এটি 'অনুকূলিতকরণ' আসলে আমার কোডটি আমার প্রত্যাশার চেয়ে ধীর করে দেবে ..." আপনি কি এর পক্ষে যুক্তি প্রমাণ করতে পারেন? কেন একটি জাম্প টেবিল দুটি সম্ভাব্য শর্তসাপেক্ষ শাখার চেয়ে ধীর হবে (ইনপুটগুলির বিরুদ্ধে 0এবং এটি পরীক্ষা করতে 1)?
কোডি গ্রে

@ কোডি গ্রে আমাকে স্বীকার করতে হবে যে আমি গণনা চক্রের স্তরে পৌঁছতে পারি নি - আমি কেবল এক আক্ষেপের অনুভূতিতে গিয়েছিলাম যে একটি পয়েন্টারের মাধ্যমে স্মৃতি থেকে লোড তুলনা এবং লাফানোর চেয়ে বেশি চক্র গ্রহণ করতে পারে তবে আমি ভুল হতে পারি। তবে, আমি আশা করি আপনি আমার সাথে একমত হয়েছিলেন যে এমনকি এই ক্ষেত্রেও কমপক্ষে '0' এর জন্য, ifসম্ভবত স্পষ্টতই দ্রুত? এখন, এখানে এমন একটি প্ল্যাটফর্মের উদাহরণ রয়েছে যেখানে ifস্যুইচটি ব্যবহার করার সময় 0 এবং 1 উভয়ই দ্রুত হবে : Godbolt.org/z/wcJhvS (নোট এখানেও একাধিক অন্যান্য অপ্টিমাইজেশান রয়েছে মনে রাখবেন)
th33lf

1
ঠিক আছে, গণনা চক্র আধুনিক সুপারক্যালার ওইও আর্কিটেকচারগুলিতে যাইহোক কাজ করে না। :-) মেমোরি থেকে লোডগুলি ভুল পূর্বাভাসিত শাখাগুলির চেয়ে ধীর হতে যাচ্ছে না, সুতরাং প্রশ্নটি ঠিক কীভাবে শাখাটির পূর্বাভাস দেওয়া সম্ভব? এই প্রশ্নটি শর্তসাপেক্ষ শাখাগুলির সমস্ত ধরণের ক্ষেত্রে প্রযোজ্য, স্পষ্ট ifবক্তব্য দ্বারা উত্পন্ন বা সংকলক দ্বারা স্বয়ংক্রিয়ভাবে হোক whether আমি কোনও এআরএম বিশেষজ্ঞ নই, তাই আপনার switchচেয়ে দ্রুত হওয়ার বিষয়ে যে দাবিটি করা হচ্ছে ifসত্য তা সত্য কিনা নিশ্চিত I'm এটি অনুমানিত শাখাগুলির দণ্ডের উপর নির্ভর করবে এবং এটি আসলে কোন এআরএমের উপর নির্ভর করবে ।
কোডি গ্রে

0

একটি সম্ভাব্য যুক্তি হ'ল যদি নিম্ন মানগুলি বেশি numহয় তবে উদাহরণস্বরূপ সর্বদা 0, প্রথমটির জন্য উত্পন্ন কোডটি দ্রুত হতে পারে। স্যুইচের জন্য উত্পন্ন কোডটি সমস্ত মানের জন্য সমান সময় নেয়।

এই টেবিল অনুসারে সেরা কেসের তুলনা করা । সারণির ব্যাখ্যার জন্য এই উত্তরটি দেখুন ।

যদি num == 0"if" এর জন্য আপনার কাছে xor, পরীক্ষা, je (জাম্প সহ) থাকে তবে ret। লেটেন্সি: 1 + 1 + জাম্প। তবে, জোর এবং টেস্ট স্বাধীন তাই প্রকৃত মৃত্যুর গতি 1 + 1 চক্রের চেয়ে দ্রুত হবে।

যদি num < 7, "স্যুইচ" এর জন্য আপনার মুভি, সিএমপি, জা (ঝাঁপ ছাড়াই), মুভি, রেট থাকে। দেরি: 2 + 1 + কোন লাফ না + 2।

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


1
হুঁ, আকর্ষণীয় তত্ত্ব, তবে আইএফএস বনাম সুইচ আপনার কাছে রয়েছে: এক্সওর, পরীক্ষা, জেএমপি বনাম মুভি, সিএমপি জেএমপি। সর্বশেষ তিনটি নির্দেশ হ'ল সর্বশেষে লাফানো। সেরা ক্ষেত্রে সমান বলে মনে হচ্ছে, না?
চামচাম

3
"একটি লাফের নির্দেশ যা লাফানোর ফলাফল দেয় না তার থেকে দ্রুত লাফানো ফলাফল" " এটি শাখার পূর্বাভাস যা গুরুত্বপূর্ণ।
গেজা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.