c# - অপরিশোধিত তুলনা এবং নিয়োগের আগে "যদি"




.net if-statement (5)

এখানে উদাহরণ:

if(value != ageValue) {
  ageValue = value;
}

আমি বলতে চাচ্ছি, যদি আমরা অন্য একটিতে একটি পরিবর্তনশীলের মান বরাদ্দ করি, তবে তাদের কেন একই মূল্য আছে কিনা তা যাচাই করতে হবে?

যে আমাকে confuses। এখানে বিস্তৃত প্রসঙ্গ:

private double ageValue;
public double Age {
  get {
    return ageValue;
  }

  set {
    if(value != ageValue) {
      ageValue = value;
    }
  }
}

আমি আসলে বিভিন্ন কারণের জন্য এই কয়েকবার মত কোড কোড করেছি। তারা ব্যাখ্যা করা কঠিন, তাই আমার সাথে সহ্য করুন।

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

আমি এই ধরনের ব্যবহার ক্ষেত্রে বিভক্ত করার চেষ্টা করব:

  1. মান একটি বিমূর্ত তথ্য টাইপ, যেখানে আপনি একই লজিক্যাল মান প্রতিনিধিত্ব করে বিভিন্ন নির্মিত উদাহরণ থাকতে পারে।

    • এটি গণিতের প্রোগ্রামগুলির মধ্যে অনেক কিছু, যেমন গণিত, যেখানে আপনি আদিম সংখ্যাসূচক ব্যবহার করতে পারবেন না, যা আপনাকে প্রতিনিধিত্ব করার জন্য বিভিন্ন বস্তুর সাথে শেষ করার অনুমতি দেয়।
  2. value রেফারেন্স একটি ক্যাশিং যুক্তি জন্য দরকারী।

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

    • ঠিক কিভাবে এবং কেন এই বিষয় প্রসঙ্গে উপর নির্ভর করে পরিবর্তিত হয়।

বড় ধারণাগত বিন্দুটি হল, কিছু ক্ষেত্রে, আপনি বিভিন্ন রেফারেন্সগুলিতে একই লজিক্যাল মান সংরক্ষণ করতে পারেন তবে আপনি দুটি বড় কারণগুলির জন্য অধঃপতন রেফারেন্সগুলির সংখ্যা কমানোর চেষ্টা করতে চান:

  1. একাধিক বার সংরক্ষিত একই লজিক্যাল মান হচ্ছে আরো মেমরি hogs।

  2. অনেক রান-টাইম শর্টকাট হিসাবে রেফারেন্স-চেকিং ব্যবহার করতে পারে, উদাহরণস্বরূপ ক্যাশিংয়ের মাধ্যমে, যদি আপনি অপ্রয়োজনীয় রেফারেন্সগুলিকে প্রচার করতে একই লজিক্যাল মানের অনুমতি দেয় তা আরো কার্যকরী হতে পারে।

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

আরেকটি ব্যবহার কেস, আবার বিমূর্ত তথ্য ধরনের সঙ্গে, যেখানে আপনি তাদের সাথে সংযুক্ত Lazly- মূল্যায়ন বৈশিষ্ট্য থাকতে পারে। উদাহরণস্বরূপ, বলুন আপনার কাছে একটি abstract class Number যার মধ্যে বৈশিষ্ট্য রয়েছে। .IsEven , ইত্যাদি। ইত্যাদি, তারপরে, আপনি তা অবিলম্বে গণনা করতে পারবেন না, বরং ফলাফলগুলি ক্যাশে করে অন-ডিমান্ড করুন। এইরকম একটি দৃশ্যকল্পতে, আপনি পুরানো সংখ্যক একই লজিক্যাল মান বজায় রাখতে পছন্দ করতে পারেন কারণ তাদের কাছে আরো বেশি জিনিস সংযুক্ত থাকতে পারে, তবে একটি নতুন value সাথে সম্পর্কিত কম তথ্য থাকতে পারে, এমনকি যদি এটি যৌক্তিকভাবে হয় ==

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


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

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

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

নিম্নোক্ত নমুনা অ্যাপ্লিকেশন এই প্রভাবটি দেখায় যা লিখার আগে চেক রয়েছে:

 if (tmp1 != checkValue)  // set only if not equal to checkvalue
 {
    values[i] = checkValue;
 }

এখানে সম্পূর্ণ কোড:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        const int N = 500_000_000;
        int[] values = new int[N]; // 2 GB
        for (int nThreads = 1; nThreads < Environment.ProcessorCount; nThreads++)
        {
            SetArray(values, checkValue: 1, nTimes: 10, nThreads: nThreads);
            SetArray(values, checkValue: 2, nTimes: 10, nThreads: nThreads);
            SetArrayNoCheck(values, checkValue: 2, nTimes: 10, nThreads: nThreads);
        }
    }

    private static void SetArray(int[] values, int checkValue, int nTimes, int nThreads)
    {
        List<double> ms = new List<double>();

        for (int k = 0; k < nTimes; k++)  // set array values to 1
        {
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = 1;
            }

            var sw = Stopwatch.StartNew();
            Action acc = () =>
            {
                int tmp1 = 0;
                for (int i = 0; i < values.Length; i++)
                {
                    tmp1 = values[i];
                    if (tmp1 != checkValue)  // set only if not equal to checkvalue
                    {
                        values[i] = checkValue;
                    }
                }
            };

            Parallel.Invoke(Enumerable.Repeat(acc, nThreads).ToArray());  // Let this run on 3 cores

            sw.Stop();
            ms.Add(sw.Elapsed.TotalMilliseconds);
            //  Console.WriteLine($"Set {values.Length * 4 / (1_000_000_000.0f):F1} GB of Memory in {sw.Elapsed.TotalMilliseconds:F0} ms. Initial Value 1. Set Value {checkValue}");
        }
        string descr = checkValue == 1 ? "Conditional Not Set" : "Conditional Set";
        Console.WriteLine($"{descr}, {ms.Average():F0}, ms, nThreads, {nThreads}");

    }

    private static void SetArrayNoCheck(int[] values, int checkValue, int nTimes, int nThreads)
    {
        List<double> ms = new List<double>();
        for (int k = 0; k < nTimes; k++)  // set array values to 1
        {
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = 1;
            }

            var sw = Stopwatch.StartNew();
            Action acc = () =>
            {
                for (int i = 0; i < values.Length; i++)
                {
                        values[i] = checkValue;
                }
            };

            Parallel.Invoke(Enumerable.Repeat(acc, nThreads).ToArray());  // Let this run on 3 cores

            sw.Stop();
            ms.Add(sw.Elapsed.TotalMilliseconds);
            //Console.WriteLine($"Unconditional Set {values.Length * 4 / (1_000_000_000.0f):F1} GB of Memory in {sw.Elapsed.TotalMilliseconds:F0} ms. Initial Value 1. Set Value {checkValue}");
        }
        Console.WriteLine($"Unconditional Set, {ms.Average():F0}, ms, nThreads, {nThreads}");
    }
}

আপনি যদি সেই রানটি চালান তবে আপনার মত মানগুলি পান:

// Value not set
Set 2.0 GB of Memory in 439 ms. Initial Value 1. Set Value 1
Set 2.0 GB of Memory in 420 ms. Initial Value 1. Set Value 1
Set 2.0 GB of Memory in 429 ms. Initial Value 1. Set Value 1
Set 2.0 GB of Memory in 393 ms. Initial Value 1. Set Value 1
Set 2.0 GB of Memory in 404 ms. Initial Value 1. Set Value 1
Set 2.0 GB of Memory in 395 ms. Initial Value 1. Set Value 1
Set 2.0 GB of Memory in 419 ms. Initial Value 1. Set Value 1
Set 2.0 GB of Memory in 421 ms. Initial Value 1. Set Value 1
Set 2.0 GB of Memory in 442 ms. Initial Value 1. Set Value 1
Set 2.0 GB of Memory in 422 ms. Initial Value 1. Set Value 1
// Value written
Set 2.0 GB of Memory in 519 ms. Initial Value 1. Set Value 2
Set 2.0 GB of Memory in 582 ms. Initial Value 1. Set Value 2
Set 2.0 GB of Memory in 543 ms. Initial Value 1. Set Value 2
Set 2.0 GB of Memory in 484 ms. Initial Value 1. Set Value 2
Set 2.0 GB of Memory in 523 ms. Initial Value 1. Set Value 2
Set 2.0 GB of Memory in 540 ms. Initial Value 1. Set Value 2
Set 2.0 GB of Memory in 552 ms. Initial Value 1. Set Value 2
Set 2.0 GB of Memory in 527 ms. Initial Value 1. Set Value 2
Set 2.0 GB of Memory in 535 ms. Initial Value 1. Set Value 2
Set 2.0 GB of Memory in 581 ms. Initial Value 1. Set Value 2

যে একটি 22% দ্রুত কর্মক্ষমতা যা উচ্চ কর্মক্ষমতা নম্বর crunching পরিস্থিতিতে উল্লেখযোগ্য হতে পারে।

প্রশ্নটি উত্তর দেওয়ার জন্য:

মেমরি অ্যাক্সেস যদি শুধুমাত্র একক থ্রেডেড আপনি যদি বিবৃতি মুছে ফেলতে পারেন। যদি একাধিক থ্রেড একই বা নিকটবর্তী ডেটাতে কাজ করছে তবে মিথ্যা ভাগ করা হতে পারে যা আপনাকে CA পর্যন্ত খরচ করতে পারে। মেমরি অ্যাক্সেস কর্মক্ষমতা 20%।

আপডেট 1 আমি আরো পরীক্ষা দৌড়াচ্ছি এবং ক্রস কোর চিট চ্যাট দেখানোর জন্য একটি চার্ট তৈরি করেছি। এটি একটি সাধারণ সেট ( অকার্যকর সেট ) দেখায় কারণ এটি মন্তব্যকারী ফ্র্যাঙ্ক হপকিন্স দ্বারা উল্লেখ করা হয়েছিল। শর্তসাপেক্ষ সেট সেট থাকে না যা মান সেট করে না। এবং শেষ কিন্তু কমপক্ষে শর্তসাপেক্ষ সেট যদি শর্তের মান সেট করবে।


কর্মক্ষমতা একটি বড় চুক্তি নয়, শুধু আপনার যুক্তি প্রয়োজন উপর নির্ভর করে।


চেকটি বেশ কার্যকর হলে এখানে একটি কোড নমুনা রয়েছে:

 public class MyClass {
    ...
    int ageValue = 0;

    public int AgeValue {
      get {
        return ageValue
      }
      protected set {
        ... // value validation here

        // your code starts
        if (value != ageValue) { 
          ageValue = value; 
        }
        // your code ends
        else
          return; // do nothing since value == ageValue

        // ageValue has been changed
        // Time (or / and memory) consuming process
        SaveToRDBMS();
        InvalidateCache(); 
        ...
      } 
    } 

 ... 

তবে আরো প্রাকৃতিক বাস্তবায়ন, অপ্রয়োজনীয় গণনা এড়ানোর জন্য খুব শুরুতে চেক করা।

    protected set {
      if (ageValue == value)
        return;

      ... // value validation here
      ageValue = value; 

      // ageValue has been changed
      // Time (or / and memory) consuming process
      SaveToRDBMS();
      InvalidateCache();  
      ...
    }

if হয়, পরিদর্শন উপর, অকার্যকর না । এটা অবশিষ্ট বাস্তবায়ন উপর নির্ভর করে। উল্লেখ্য যে সি # != ওভারলোড করা যেতে পারে, যার অর্থ হল মূল্যায়নের পার্শ্ব প্রতিক্রিয়া থাকতে পারে। Futhermore, চেক ভেরিয়েবল বৈশিষ্ট্য হিসাবে প্রয়োগ করা যেতে পারে, যা মূল্যায়নের উপর পার্শ্ব প্রতিক্রিয়া হতে পারে।





if-statement