সাধারণ বৈশিষ্ট্যগুলিতে আগ্রাসী ইনলাইনিং ব্যবহার করার কোনও প্রতিকূলতা আছে কি?


16

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

আমার কাছে এর মতো সহজ কোড রয়েছে:

    private SqlMetaData[] meta;

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private SqlMetaData[] Meta
    {
        get
        {
            return this.meta;
        }
    }

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

এই জাতীয় জিনিসটি সম্পাদন / স্থিতিশীলতা / কোনও কিছুতে আঘাত করতে পারে?


2
1) আমার অভিজ্ঞতায় এ জাতীয় আধ্যাত্মিক বৈশিষ্ট্যগুলি বৈশিষ্ট্য ছাড়াই ইনলাইন করা হবে। আমি মূলত নগণ্য পদ্ধতিগুলির সাথে দরকারী বৈশিষ্ট্যটি খুঁজে পেয়েছি যা এখনও ইনলাইন করা উচিত। 2) কোনও গ্যারান্টি নেই যে গুণাবলী দিয়ে সজ্জিত কোনও পদ্ধতি অন্তর্ভুক্ত হবে। এটি জিটটারের কাছে কেবল একটি ইঙ্গিত।
কোডসইনচওস

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

14
3) খুব বেশি lোকানো মানে কোডটি আরও বড় হয়ে যায় এবং এটি আর ক্যাশে মাপসই করা যায় না। ক্যাশে মিস করা একটি উল্লেখযোগ্য পারফরম্যান্স হিট হতে পারে। 4) আমি কোনও মানদণ্ড না দেখানো পর্যন্ত এটি বৈশিষ্ট্যটি ব্যবহার না করার প্রস্তাব দিই যা এটির কার্যকারিতা উন্নত করে।
কোডসইনচওস

4
উদ্বেগ ছাড়ুন। আপনি যত বেশি সংকলককে আউটস্মার্ট করার চেষ্টা করবেন ততই আপনাকে আউটসামার করার উপায়গুলি খুঁজে পাবেন। উদ্বেগের জন্য আরও কিছু সন্ধান করুন।
david.pfx

1
আমার দুটি সেন্টের জন্য, আমি রিলিজ মোডে দুর্দান্ত লাভ দেখেছি, বিশেষত যখন একটি শক্ত লুপে কোনও বৃহত ফাংশনটি কল করার সময়।
jjxtra

উত্তর:


22

সংকলকগণ হ'ল স্মার্ট জন্তু। সাধারণত, তারা যে কোনও জায়গা থেকে নিজেরাই যতটা পারফরম্যান্স সেগুলি স্বয়ংক্রিয়ভাবে নিচে নেবে।

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

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


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

1
সংকলকগণ যদি এত স্মার্ট হয় তবে কেন কম্পাইলার ব্যাকফায়ার আউটসামার্ট করার চেষ্টা করবে?
ছোট এন্ডিয়ান

11
সংকলকগণ স্মার্ট নয় । সংকলকগণ "সঠিক জিনিস" করেন না। বুদ্ধি যেখানে নেই সেখানে বৈশিষ্ট্যযুক্ত করবেন না। আসলে, সি # সংকলক / জেআইটি অতিরিক্ত বোবা। উদাহরণস্বরূপ, এটি 32 বাইট আইএল বা structপ্যারামিটার হিসাবে জড়িত কেসগুলির পূর্ববর্তী কোনও কিছুকে ইনলাইন করবে না - যেখানে বেশিরভাগ ক্ষেত্রে এটি হওয়া উচিত এবং হতে পারে। অন্যান্য বিষয়গুলির মধ্যে অপ্রয়োজনীয় গণ্ডি চেক এবং বরাদ্দ এড়ানো সহ - তবে সীমাবদ্ধ নয় - শত শত সুস্পষ্ট অপ্টিমাইজেশানগুলি হারিয়ে যাওয়া ছাড়াও ।
জেবারার

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

3
সংকলকগুলি "স্মার্ট বিস্ট" নয়। সংকলক লেখকদের দ্বারা প্রত্যাশিত বেশিরভাগ দৃশ্যের জন্য ভারসাম্য রক্ষার চেষ্টা করার জন্য তারা কেবল একগুচ্ছ তাত্ত্বিক প্রয়োগ করে এবং বাণিজ্য বন্ধ করে দেয়। আমি পড়ার পরামর্শ দিচ্ছি: ডকস.মাইক্রোসফট
us

8

আপনি ঠিক বলেছেন - পদ্ধতিটি ইনলাইনড হবে তার গ্যারান্টি দেওয়ার কোনও উপায় নেই - এমএসডিএন মেথডিম্পলঅ্যাপশনস এনুমুরেশন , এসও মেথডিম্পলপশনস gঅগ্রগ্রিভ ইনলাইনিং বনাম টার্গেটডপ্যাচিংঅপটআউট

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

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


8

সম্পাদনা: আমি বুঝতে পারি যে আমার উত্তরটি প্রশ্নের ঠিক উত্তর দেয়নি, যদিও কোনও সত্যিকারের নেপথ্যতা নেই, আমার সময়সীমার ফলাফল থেকে সত্যিকারের উল্টোটাও নেই। একটি ইনলাইন সম্পত্তি প্রাপ্তির মধ্যে পার্থক্য 500 মিলিয়ন পুনরাবৃত্তির চেয়ে 0.002 সেকেন্ড। আমার পরীক্ষার কেসটি স্ট্রাক ব্যবহারের পরেও 100% নির্ভুল হতে পারে না কারণ জিটটারে কিছু সতর্কতা রয়েছে এবং স্ট্রাক্টগুলির সাথে অন্তর্নিহিত রয়েছে।

সর্বদা হিসাবে, সত্যই জানার একমাত্র উপায় হ'ল একটি পরীক্ষা লিখতে এবং এটি নির্ধারণ করা। নিম্নলিখিত কনফিগারেশন সহ আমার ফলাফল এখানে:

Windows 7 Home  
8GB ram  
64bit os  
i5-2300 2.8ghz  

নিম্নলিখিত সেটিংস সহ খালি প্রকল্প:

.NET 4.5  
Release mode  
Start without debugger attached - CRUCIAL  
Unchecked "Prefer 32-bit" under project build settings  

ফলাফল

struct get property                               : 0.3097832 seconds
struct inline get property                        : 0.3079076 seconds
struct method call with params                    : 1.0925033 seconds
struct inline method call with params             : 1.0930666 seconds
struct method call without params                 : 1.5211852 seconds
struct intline method call without params         : 1.2235001 seconds

এই কোড দিয়ে পরীক্ষিত:

class Program
{
    const int SAMPLES = 5;
    const int ITERATIONS = 100000;
    const int DATASIZE = 1000;

    static Random random = new Random();
    static Stopwatch timer = new Stopwatch();
    static Dictionary<string, TimeSpan> timings = new Dictionary<string, TimeSpan>();

    class SimpleTimer : IDisposable
    {
        private string name;
        public SimpleTimer(string name)
        {
            this.name = name;
            timer.Restart();
        }

        public void Dispose()
        {
            timer.Stop();
            TimeSpan ts = TimeSpan.Zero;
            if (timings.ContainsKey(name))
                ts = timings[name];

            ts += timer.Elapsed;
            timings[name] = ts;
        }
    }

    [StructLayout(LayoutKind.Sequential, Size = 4)]
    struct TestStruct
    {
        private int x;
        public int X { get { return x; } set { x = value; } }
    }


    [StructLayout(LayoutKind.Sequential, Size = 4)]
    struct TestStruct2
    {
        private int x;

        public int X
        {
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get { return x; }
            set { x = value; }
        }
    }

    [StructLayout(LayoutKind.Sequential, Size = 8)]
    struct TestStruct3
    {
        private int x;
        private int y;

        public void Update(int _x, int _y)
        {
            x += _x;
            y += _y;
        }
    }

    [StructLayout(LayoutKind.Sequential, Size = 8)]
    struct TestStruct4
    {
        private int x;
        private int y;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Update(int _x, int _y)
        {
            x += _x;
            y += _y;
        }
    }

    [StructLayout(LayoutKind.Sequential, Size = 8)]
    struct TestStruct5
    {
        private int x;
        private int y;

        public void Update()
        {
            x *= x;
            y *= y;
        }
    }

    [StructLayout(LayoutKind.Sequential, Size = 8)]
    struct TestStruct6
    {
        private int x;
        private int y;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Update()
        {
            x *= x;
            y *= y;
        }
    }

    static void RunTests()
    {
        for (var i = 0; i < SAMPLES; ++i)
        {
            Console.Write("Sample {0} ... ", i);
            RunTest1();
            RunTest2();
            RunTest3();
            RunTest4();
            RunTest5();
            RunTest6();
            Console.WriteLine(" complate");
        }
    }

    static int RunTest1()
    {
        var data = new TestStruct[DATASIZE];
        var temp = 0;
        unchecked
        {
            //init the data, just so jitter can't make assumptions
            for (var j = 0; j < DATASIZE; ++j)
                data[j].X = random.Next();

            using (new SimpleTimer("struct get property"))
            {
                for (var j = 0; j < DATASIZE; ++j)
                {
                    for (var i = 0; i < ITERATIONS; ++i)
                    {
                        //use some math to make sure its not optimized out (aka don't use an incrementor)
                        temp += data[j].X;
                    }
                }
            }
        }
        //again need variables to cross scopes to make sure the jitter doesn't do crazy optimizations
        return temp;
    }

    static int RunTest2()
    {
        var data = new TestStruct2[DATASIZE];
        var temp = 0;
        unchecked
        {
            //init the data, just so jitter can't make assumptions
            for (var j = 0; j < DATASIZE; ++j)
                data[j].X = random.Next();

            using (new SimpleTimer("struct inline get property"))
            {
                for (var j = 0; j < DATASIZE; ++j)
                {
                    for (var i = 0; i < ITERATIONS; ++i)
                    {
                        //use some math to make sure its not optimized out (aka don't use an incrementor)
                        temp += data[j].X;
                    }
                }
            }
        }
        //again need variables to cross scopes to make sure the jitter doesn't do crazy optimizations
        return temp;
    }

    static void RunTest3()
    {
        var data = new TestStruct3[DATASIZE];
        unchecked
        {
            using (new SimpleTimer("struct method call with params"))
            {
                for (var j = 0; j < DATASIZE; ++j)
                {
                    for (var i = 0; i < ITERATIONS; ++i)
                    {
                        //use some math to make sure its not optimized out (aka don't use an incrementor)
                        data[j].Update(j, i);
                    }
                }
            }
        }
    }

    static void RunTest4()
    {
        var data = new TestStruct4[DATASIZE];
        unchecked
        {
            using (new SimpleTimer("struct inline method call with params"))
            {
                for (var j = 0; j < DATASIZE; ++j)
                {
                    for (var i = 0; i < ITERATIONS; ++i)
                    {
                        //use some math to make sure its not optimized out (aka don't use an incrementor)
                        data[j].Update(j, i);
                    }
                }
            }
        }
    }

    static void RunTest5()
    {
        var data = new TestStruct5[DATASIZE];
        unchecked
        {
            using (new SimpleTimer("struct method call without params"))
            {
                for (var j = 0; j < DATASIZE; ++j)
                {
                    for (var i = 0; i < ITERATIONS; ++i)
                    {
                        //use some math to make sure its not optimized out (aka don't use an incrementor)
                        data[j].Update();
                    }
                }
            }
        }
    }

    static void RunTest6()
    {
        var data = new TestStruct6[DATASIZE];
        unchecked
        {
            using (new SimpleTimer("struct intline method call without params"))
            {
                for (var j = 0; j < DATASIZE; ++j)
                {
                    for (var i = 0; i < ITERATIONS; ++i)
                    {
                        //use some math to make sure its not optimized out (aka don't use an incrementor)
                        data[j].Update();
                    }
                }
            }
        }
    }

    static void Main(string[] args)
    {
        RunTests();
        DumpResults();
        Console.Read();
    }

    static void DumpResults()
    {
        foreach (var kvp in timings)
        {
            Console.WriteLine("{0,-50}: {1} seconds", kvp.Key, kvp.Value.TotalSeconds);
        }
    }
}

5

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

অন্যান্য অনেকগুলি অপ্টিমাইজেশন বিশেষত বিল্ড অপশনগুলি থেকে সক্ষম করা হলে বা "রিলিজ" মোড এটি করবে। তবে এই অপ্টিমাইজেশানগুলি হ'ল "আপনার জন্য কাজ করেছে, দুর্দান্ত! কাজ হয়নি, ছেড়ে দিন" অপটিমাইজেশন এবং সাধারণত আরও ভাল পারফরম্যান্স দেয়।

[MethodImpl(MethodImplOptions.AggressiveInlining)]

সংকলকটির জন্য কেবল এটি একটি পতাকা যা এখানে একটি অন্তর্নিহিত অপারেশনটি সত্যই চাইছিল। এখানে এবং এখানে আরও তথ্য

আপনার প্রশ্নের উত্তর দিতে;

জেআইটি অন্যথায় এটি ইনলাইন করবে এমন কোনও গ্যারান্টি নেই। আমি কি ভূল?

সত্য। গ্যারান্টি নেই; সি # এর কোনওটিতেই "ফোর্স ইনলাইনিং" বিকল্প নেই।

এই জাতীয় জিনিসটি সম্পাদন / স্থিতিশীলতা / কোনও কিছুতে আঘাত করতে পারে?

এই ক্ষেত্রে না, যেমন হাই-পারফরম্যান্স ম্যানেজড অ্যাপ্লিকেশনগুলি লেখার ক্ষেত্রে বলা হয়েছে : একজন প্রাইমার

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


1
আশা করা যায় যে উত্তরগুলি প্রশ্নের সম্পূর্ণ উত্তর দেয় answer যদিও এটি কোনও উত্তরের সূচনা, সত্যই এটি উত্তরের প্রত্যাশার গভীরতায় যায় না।

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