একটি পুনরাবৃত্ত ফাংশন ইনলাইন হতে পারে?


134
inline int factorial(int n)
{
    if(!n) return 1;
    else return n*factorial(n-1);
}

আমি পড়া ছিল এই পাওয়া যে উপরোক্ত কোড "অসীম সংকলন" হতে তাহলে সঠিকভাবে কম্পাইলার দ্বারা পরিচালিত নয়।

কম্পাইলার কীভাবে কোনও ফাংশনটি ইনলাইন করবে কিনা তা সিদ্ধান্ত নিতে পারে?

উত্তর:


137

প্রথমত, inlineকোনও ফাংশনের স্পেসিফিকেশনটি কেবল একটি ইঙ্গিত। সংকলক কোনও যোগ্যতার উপস্থিতি বা অনুপস্থিতিকে সম্পূর্ণ উপেক্ষা করতে পারে (এবং প্রায়শই তা করে) inline। যা বলেছিল, একটি সংকলক একটি পুনরাবৃত্ত ফাংশনটি ইনলাইন করতে পারে, যতটা এটি অসীম লুপটিকে আনরোল করতে পারে। এটি কেবল যে স্তরে এটি ফাংশনটি "তালিকাভুক্ত" করবে তাতে একটি সীমা রাখতে হবে।

একটি অনুকূলকরণ সংকলক এই কোডটি চালু করতে পারে:

inline int factorial(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    else
    {
        return n * factorial(n - 1);
    }
}

int f(int x)
{
    return factorial(x);
}

এই কোডে:

int factorial(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    else
    {
        return n * factorial(n - 1);
    }
}

int f(int x)
{
    if (x <= 1)
    {
        return 1;
    }
    else
    {
        int x2 = x - 1;
        if (x2 <= 1)
        {
            return x * 1;
        }
        else
        {
            int x3 = x2 - 1;
            if (x3 <= 1)
            {
                return x * x2 * 1;
            }
            else
            {
                return x * x2 * x3 * factorial(x3 - 1);
            }
        }
    }
}

এই ক্ষেত্রে, আমরা মূলত ফাংশনটি 3 বার linedুকেছি। কিছু কম্পাইলার কি এই অপ্টিমাইজেশান সঞ্চালন। আমি এমএসভিসি ++ এর পুনরাবৃত্ত ফাংশনগুলিতে সঞ্চালিত হবে এমন ইনলাইনিং স্তরের টিউন করার জন্য একটি সেটিং থাকার কথা মনে করি (20 টি পর্যন্ত, আমি বিশ্বাস করি)।


20
এটি # প্রগমা ইনলাইন_রেচার্শন (চালু)। সর্বাধিক গভীরতা সম্পর্কে ডকুমেন্টেশন সামঞ্জস্যপূর্ণ বা বেমানান নয়। 8, 16, বা #pragma ইনলাইন_পথের মানগুলি সম্ভব।
পিটারচেন

@ পেটারচেন যদি ফাংশনটি ইনলাইন করা হয় তবে এর মধ্যে যে কোনও একটি যুক্তির মান পরিবর্তন হয় তবে আমি মনে করি মূলটির পরিবর্তে ফাংশনটির ভিতরে lineোকানো ভাল। আমার ইংরাজির জন্য দুঃখিত
ob_dev

1
@ ওবোনাইম: আপনি হয়ত এটি ভাবতে পারেন। এমএসভিসি না।
সিকিউরিটিম্যাট

23

প্রকৃতপক্ষে, যদি আপনার সংকলক বুদ্ধিমানের সাথে কাজ না করে, এটি আপনার inlineডি ফাংশনের অনুলিপি পুনরাবৃত্তভাবে ser োকানোর চেষ্টা করতে পারে , অসীম-বৃহত কোড তৈরি করতে পারে। তবে বেশিরভাগ আধুনিক সংকলকগণ এটি স্বীকৃতি দেবে। তারা হয়:

  1. ফাংশনটি একেবারেই ইনলাইন করবেন না
  2. এটিকে একটি নির্দিষ্ট গভীরতা পর্যন্ত ইনলাইন করুন এবং যদি এটি ততক্ষণে অবসান না হয় তবে স্ট্যান্ডার্ড ফাংশন কলিং কনভেনশনটি ব্যবহার করে আপনার ফাংশনের পৃথক উদাহরণটি কল করুন। এটি একটি বৃহত্তর কলতার গভীরতার সাথে বিরল ক্ষেত্রে ফ্যালব্যাক রেখে উচ্চ-পারফরম্যান্স পদ্ধতিতে অনেকগুলি সাধারণ কেসের যত্ন নিতে পারে। এর অর্থ হ'ল আপনি সেই ফাংশনের কোডের উভয় অন্তর্নিহিত এবং পৃথক সংস্করণ রাখবেন।

কেস 2 এর জন্য, অনেক সংকলক আপনার #pragmaসর্বাধিক গভীরতা নির্দিষ্ট করতে সেট করতে পারেন যা এটি করা উচিত। ইন জিসিসি , সেই জন্যই এই মধ্যে কম্যান্ড-লাইন থেকে পাস দিয়ে করতে পারেন --max-inline-insns-recursive(আরো তথ্য দেখতে এখানে )।


7

আফাইক জিসিসি সম্ভব হলে পুনরাবৃত্তির কাজগুলিতে টেল কল নির্মূল করবে। আপনার ফাংশন তবে লেজ পুনরাবৃত্ত হয় না।


6

সংকলক একটি কল গ্রাফ তৈরি করে; যখন একটি চক্র নিজেকে কল করে সনাক্ত করা হয়, তখন নির্দিষ্ট গভীরতার পরে ক্রিয়াকলাপটি আর প্রবেশ করা হয় না (এন = 1, 10, 100, সংকলকটি যাই হোক না কেন)।


3

কিছু পুনরাবৃত্ত ক্রিয়াকলাপগুলি লুপগুলিতে রূপান্তরিত হতে পারে, যা কার্যকরভাবে অসীমভাবে তাদের ইনলাইন করে। আমি বিশ্বাস করি জিসিসি এটি করতে পারে তবে আমি অন্যান্য সংকলকগুলি সম্পর্কে জানি না।


2

কেন এটি সাধারণত কাজ করবে না এর জন্য ইতিমধ্যে দেওয়া উত্তরগুলি দেখুন।

"পাদটীকা" হিসাবে, আপনি যে প্রভাবটি সন্ধান করছেন তা অর্জন করতে পারেন (কমপক্ষে আপনি যেমন উদাহরণ হিসাবে ব্যবহার করছেন তার জন্য) টেমপ্লেট বিপণন ব্যবহার করে । উইকিপিডিয়া থেকে আটকানো:

template <int N>
struct Factorial 
{
    enum { value = N * Factorial<N - 1>::value };
};

template <>
struct Factorial<0> 
{
    enum { value = 1 };
};

1
এটি খুব সুন্দর, তবে দয়া করে লক্ষ্য করুন যে মূল পোস্টিংটিতে একটি পরিবর্তনশীল আর্গুমেন্ট ছিল "int n"।
উইন্ডোজ প্রোগ্রামার

1
সত্য, তবে এন সংকলনের সময় জানা না গেলে "পুনরাবৃত্ত ইনলাইনিং" চাওয়ার খুব কম ব্যপারও আছে ... সংকলক কীভাবে এটি অর্জন করতে পারে? সুতরাং প্রশ্নের প্রসঙ্গে আমি মনে করি এটি একটি প্রাসঙ্গিক বিকল্প।
yungchin

1
কীভাবে এটি করবেন ডেরেক পার্কের উদাহরণ দেখুন: দু'বার ইনলাইন করে আপনি এন >> 2 বার পুনরাবৃত্তি করেন এবং ফলাফল কোড থেকে আপনার কাছে 2 + 2 রিটার্ন থাকে।
এমএসএলটাররা

1

সংকলক এই ধরণের জিনিস সনাক্ত করতে এবং তাদের প্রতিরোধের জন্য একটি কল গ্রাফ তৈরি করবে। সুতরাং এটি দেখতে পাবে যে ফাংশনটি নিজেরাই কল করে এবং ইনলাইন নয়।

তবে মূলত এটি ইনলাইন কীওয়ার্ড এবং সংকলক সুইচগুলি দ্বারা নিয়ন্ত্রিত হয় (উদাহরণস্বরূপ, আপনি কীওয়ার্ড ছাড়াই এটি স্বয়ংক্রিয়ভাবে ছোট ফাংশনগুলিও ইনলাইন করতে পারেন)) ডিবাগ সংকলনগুলি কখনই ইনলাইন হওয়া উচিত নয় কারণ কলস্ট্যাকটি আয়নাতে সংরক্ষণ করা হবে না note কোডগুলিতে আপনি তৈরি কলগুলি।


1

"কম্পাইলার কীভাবে কোনও ফাংশনটি ইনলাইন করবে কিনা তা সিদ্ধান্ত নেবে?"

এটি সংকলক, নির্দিষ্ট করা বিকল্পগুলি, সংকলকটির সংস্করণ নম্বর, কত স্মৃতি উপলব্ধ রয়েছে ইত্যাদি নির্ভর করে etc.

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

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


0

কিছু সংকলক (আই বোরল্যান্ড সি ++) শর্তযুক্ত বিবৃতি (যদি, ক্ষেত্রে, ইত্যাদি ইত্যাদি) অন্তর্নিহিত কোড দেয় না যাতে আপনার উদাহরণে পুনরাবৃত্ত ফাংশনটি অন্তর্ভুক্ত করা যায় না।

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