আমার অ্যাপ্লিকেশন কেন তার জীবনের 24% নাল চেক করতে ব্যয় করে?


104

আমি একটি পারফরম্যান্স সমালোচনামূলক বাইনারি সিদ্ধান্ত গাছ পেয়েছি, এবং আমি এই প্রশ্নটি কোডের একক লাইনে ফোকাস করতে চাই। বাইনারি ট্রি আইট্রেটারের কোডটি এর বিপরীতে কার্য সম্পাদন বিশ্লেষণের ফলাফল সহ নীচে রয়েছে।

        public ScTreeNode GetNodeForState(int rootIndex, float[] inputs)
        {
0.2%        ScTreeNode node = RootNodes[rootIndex].TreeNode;

24.6%       while (node.BranchData != null)
            {
0.2%            BranchNodeData b = node.BranchData;
0.5%            node = b.Child2;
12.8%           if (inputs[b.SplitInputIndex] <= b.SplitValue)
0.8%                node = b.Child1;
            }

0.4%        return node;
        }

ব্রাঞ্চডেটা একটি ক্ষেত্র, সম্পত্তি নয়। এর ঝুঁকি যাতে অন্তর্ভুক্ত না হয় সে জন্য আমি এটি করেছি।

ব্রাঞ্চনোডেটা ক্লাসটি নিম্নরূপ:

public sealed class BranchNodeData
{
    /// <summary>
    /// The index of the data item in the input array on which we need to split
    /// </summary>
    internal int SplitInputIndex = 0;

    /// <summary>
    /// The value that we should split on
    /// </summary>
    internal float SplitValue = 0;

    /// <summary>
    /// The nodes children
    /// </summary>
    internal ScTreeNode Child1;
    internal ScTreeNode Child2;
}

যেমন আপনি দেখতে পাচ্ছেন, সেই সময় লুপ / ​​নাল চেকটি পারফরম্যান্সে একটি বিশাল হিট। গাছটি বিশাল, তাই আমি একটি পাতা সন্ধান করার জন্য কিছু সময় নেওয়ার আশা করব, তবে আমি সেই এক লাইনে ব্যয়বহুল পরিমাণ ব্যয় করতে চাই।

আমি চেষ্টা করেছিলাম:

  • নল চেকটি কিছুক্ষণ থেকে আলাদা করা - এটি হ'ল নল চেক।
  • বস্তুটিতে একটি বুলিয়ান ক্ষেত্র যুক্ত করা এবং এর বিপরীতে পরীক্ষা করা, এতে কোনও তফাত হয়নি। কী তুলনা করা হচ্ছে তা বিবেচ্য নয়, এটি তুলনা এটিই।

এটি কি শাখার পূর্বাভাসের বিষয়? যদি তা হয় তবে আমি এটি সম্পর্কে কী করতে পারি? কিছু হলে?

আমি সিআইএল বোঝার ভান করব না তবে আমি এটি কারও জন্য পোস্ট করব যাতে তারা এ থেকে কিছু তথ্য নষ্ট করার চেষ্টা করতে পারে।

.method public hidebysig
instance class OptimalTreeSearch.ScTreeNode GetNodeForState (
    int32 rootIndex,
    float32[] inputs
) cil managed
{
    // Method begins at RVA 0x2dc8
    // Code size 67 (0x43)
    .maxstack 2
    .locals init (
        [0] class OptimalTreeSearch.ScTreeNode node,
        [1] class OptimalTreeSearch.BranchNodeData b
    )

    IL_0000: ldarg.0
    IL_0001: ldfld class [mscorlib]System.Collections.Generic.List`1<class OptimalTreeSearch.ScRootNode> OptimalTreeSearch.ScSearchTree::RootNodes
    IL_0006: ldarg.1
    IL_0007: callvirt instance !0 class [mscorlib]System.Collections.Generic.List`1<class OptimalTreeSearch.ScRootNode>::get_Item(int32)
    IL_000c: ldfld class OptimalTreeSearch.ScTreeNode OptimalTreeSearch.ScRootNode::TreeNode
    IL_0011: stloc.0
    IL_0012: br.s IL_0039
    // loop start (head: IL_0039)
        IL_0014: ldloc.0
        IL_0015: ldfld class OptimalTreeSearch.BranchNodeData OptimalTreeSearch.ScTreeNode::BranchData
        IL_001a: stloc.1
        IL_001b: ldloc.1
        IL_001c: ldfld class OptimalTreeSearch.ScTreeNode OptimalTreeSearch.BranchNodeData::Child2
        IL_0021: stloc.0
        IL_0022: ldarg.2
        IL_0023: ldloc.1
        IL_0024: ldfld int32 OptimalTreeSearch.BranchNodeData::SplitInputIndex
        IL_0029: ldelem.r4
        IL_002a: ldloc.1
        IL_002b: ldfld float32 OptimalTreeSearch.BranchNodeData::SplitValue
        IL_0030: bgt.un.s IL_0039

        IL_0032: ldloc.1
        IL_0033: ldfld class OptimalTreeSearch.ScTreeNode OptimalTreeSearch.BranchNodeData::Child1
        IL_0038: stloc.0

        IL_0039: ldloc.0
        IL_003a: ldfld class OptimalTreeSearch.BranchNodeData OptimalTreeSearch.ScTreeNode::BranchData
        IL_003f: brtrue.s IL_0014
    // end loop

    IL_0041: ldloc.0
    IL_0042: ret
} // end of method ScSearchTree::GetNodeForState

সম্পাদনা: আমি একটি শাখার পূর্বাভাস পরীক্ষা করার সিদ্ধান্ত নিয়েছি, কিছুক্ষণের মধ্যে যদি আমি একটি অভিন্ন যোগ করেছি, তাই আমাদের রয়েছে

while (node.BranchData != null)

এবং

if (node.BranchData != null)

যে ভিতরে। আমি তারপরে পারফরম্যান্স বিশ্লেষণ চালিয়েছিলাম এবং প্রথম তুলনাটি কার্যকর করতে এটি ছয় গুণ বেশি সময় নিয়েছিল কারণ এটি সর্বদা সত্য প্রত্যাবর্তনকারী দ্বিতীয় তুলনাটি কার্যকর করতে হয়েছিল। সুতরাং দেখে মনে হচ্ছে এটি সত্যিই একটি শাখার পূর্বাভাসের বিষয় - এবং আমি অনুমান করছি যে এটি সম্পর্কে আমি কিছুই করতে পারি না !?

অন্য সম্পাদনা

উপরের ফলাফলটিও ঘটতে পারে যদি নোড.ব্রেঞ্চডাটা কিছুক্ষণ চেক করার জন্য র‍্যাম থেকে লোড করতে হয় - তবে এটি যদি বিবৃতিতে ক্যাশে হয়।


এটি একটি অনুরূপ বিষয়ে আমার তৃতীয় প্রশ্ন। এবার আমি কোডের একক লাইনে ফোকাস করছি। এই বিষয়ে আমার অন্যান্য প্রশ্নগুলি হ'ল:


3
BranchNodeসম্পত্তি বাস্তবায়ন দেখান । প্রতিস্থাপন করার চেষ্টা করুন node.BranchData != null ReferenceEquals(node.BranchData, null)। এটা কি কোনো পার্থক্য তৈরি করে?
ড্যানিয়েল হিলগারথ

4
আপনি কি নিশ্চিত যে 24% ততক্ষণের বিবৃতিতে নয় এবং শর্তটি প্রকাশের
সময়টির

2
আরেকটি পরীক্ষা: চেষ্টা পুনরায় লিখতে এই মত আপনার যখন লুপ: while(true) { /* current body */ if(node.BranchData == null) return node; }। এটি কিছু পরিবর্তন করে?
ড্যানিয়েল হিলগারথ

2
সামান্য অপ্টিমাইজেশন নিম্নলিখিত হবে: while(true) { BranchNodeData b = node.BranchData; if(ReferenceEquals(b, null)) return node; node = b.Child2; if (inputs[b.SplitInputIndex] <= b.SplitValue) node = b.Child1; }এটি node. BranchDataকেবল একবারে পুনরুদ্ধার হবে ।
ড্যানিয়েল হিলগারথ

2
মোট সময় কার্যকরভাবে সবচেয়ে বেশি সময় ব্যয় করা দুটি লাইনের সংখ্যাটি দয়া করে যুক্ত করুন।
ড্যানিয়েল হিলগার্থ

উত্তর:


180

গাছটি বিশাল

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

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

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

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

যা এখন পর্যন্ত সবচেয়ে দক্ষ ডেটা কাঠামোয় একটি অ্যারে তৈরি করে। .NET তালিকা <> শ্রেণি মোটেও একটি তালিকা নয় বলেও এটি সঞ্চয়স্থানের জন্য একটি অ্যারে ব্যবহার করে। অভিধানের মতো অন্যান্য সংগ্রহের ধরণের ক্ষেত্রেও একই রকম, কাঠামোগতভাবে অ্যারের সাথে দূরবর্তীভাবে অনুরূপ নয়, তবে অভ্যন্তরীণভাবে অ্যারে দ্বারা প্রয়োগ করা হয়।

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

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


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

11
থ্রেডগুলি এই সমস্যার সমাধান করে না। আপনাকে আরও কোর দেয়, আপনার কাছে এখনও একটি মাত্র মেমোরি বাস রয়েছে।
হান্স প্যাস্যান্ট

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

4
যথারীতি সম্পর্কিত বিস্তৃত বিস্তৃত বিবরণ সহ গভীর ব্যাখ্যামূলক। +1
21:51

1
আপনি যদি গাছের অ্যাক্সেসের ধরণটি জানেন এবং এটি 80/20 (অ্যাক্সেসের 80% সর্বদা নোডের একই 20% তে থাকে) নিয়ম অনুসরণ করে তবে একটি স্প্লে গাছের মতো একটি স্ব সমন্বয়কারী গাছও দ্রুত প্রমাণ করতে পারে। en.wikedia.org/wiki/Splay_tree
জেনস টিমারম্যান

10

মেমরি ক্যাশে প্রভাবগুলি সম্পর্কে হান্সের দুর্দান্ত উত্তরের পরিপূরক করতে, আমি শারীরিক মেমরির অনুবাদ এবং NUMA প্রভাবগুলিতে ভার্চুয়াল মেমরির একটি আলোচনা যুক্ত করি।

ভার্চুয়াল মেমরি কম্পিউটারের সাথে (সমস্ত বর্তমান কম্পিউটার) মেমরি অ্যাক্সেস করার সময় প্রতিটি ভার্চুয়াল মেমরি ঠিকানা অবশ্যই একটি শারীরিক মেমরি ঠিকানায় অনুবাদ করা উচিত। এটি অনুবাদ সারণী ব্যবহার করে মেমরি পরিচালনা হার্ডওয়্যার দ্বারা করা হয়। এই টেবিলটি প্রতিটি প্রক্রিয়াটির জন্য অপারেটিং সিস্টেম দ্বারা পরিচালিত হয় এবং এটি নিজেই র‌্যামে সঞ্চিত থাকে। ভার্চুয়াল মেমরির প্রতিটি পৃষ্ঠার জন্য, এই অনুবাদ টেবিলটিতে একটি ভৌত ​​পৃষ্ঠায় ভার্চুয়াল ম্যাপিংয়ের একটি সারণি রয়েছে। মনে রাখবেন হ্যান্সের মেমরি অ্যাক্সেসগুলি সম্পর্কে আলোচনাগুলি ব্যয়বহুল: যদি প্রতিটি ভার্চুয়ালকে ভিজ্যুয়াল অনুবাদে মেমরির অনুসন্ধানের প্রয়োজন হয় তবে সমস্ত মেমরির অ্যাক্সেস দ্বিগুণ হবে। সমাধানটি হ'ল অনুবাদ টেবিলের জন্য একটি ক্যাশে রাখা যাকে অনুবাদ লুকাসাইড বাফার বলে(সংক্ষেপে টিএলবি)। টিএলবি বৃহত্তর নয় (12 থেকে 4096 এন্ট্রি), এবং x86-64 আর্কিটেকচারের নির্দিষ্ট পৃষ্ঠার আকারটি কেবল 4 কেবি, যার অর্থ টিএলবি হিটের সাথে সর্বাধিক 16 এমবি সরাসরি অ্যাক্সেসযোগ্য রয়েছে (এটি সম্ভবত এর চেয়ে কমও কম, স্যান্ডি 512 আইটেমের টিএলবি আকারযুক্ত সেতু )। টিএলবি মিসের সংখ্যা হ্রাস করতে, আপনার অপারেটিং সিস্টেম এবং অ্যাপ্লিকেশন একসাথে 2 এমবি এর মতো বৃহত্তর পৃষ্ঠার আকার ব্যবহার করতে পারে, যার ফলে টিএলবি হিটের সাহায্যে অনেক বড় মেমরি স্পেস পাওয়া যায়। এই পৃষ্ঠাটি কিভাবে ব্যাখ্যা জাভা দিয়ে বড় পৃষ্ঠাগুলি ব্যবহার করতে যা যা করতে পারেন ব্যাপকভাবে speedup মেমরির ব্যবহারের

আপনার কম্পিউটারে যদি অনেকগুলি সকেট থাকে তবে এটি সম্ভবত একটি NUMA আর্কিটেকচার। NUMA অর্থ অ-ইউনিফর্ম মেমরি অ্যাক্সেস। এই আর্কিটেকচারগুলিতে কিছু স্মৃতি অ্যাক্সেসের জন্য অন্যের চেয়ে বেশি ব্যয় হয়। উদাহরণস্বরূপ, 32 গিগাবাইট র‌্যাম সহ 2 সকেটের কম্পিউটার সহ প্রতিটি সকেটে সম্ভবত 16 গিগাবাইট র‌্যাম রয়েছে। এই উদাহরণস্বরূপ কম্পিউটারে, স্থানীয় মেমরি অ্যাক্সেসগুলি অন্য সকেটের মেমরির অ্যাক্সেসের চেয়ে সস্তা (দূরবর্তী অ্যাক্সেস 20 থেকে 100% ধীর, সম্ভবত আরও বেশি)। যদি এই জাতীয় কম্পিউটারে আপনার গাছটি 20 গিগাবাইট র‌্যাম ব্যবহার করে, আপনার ডেটা কমপক্ষে 4 গিগাবাইট অন্য NUMA নোডে রয়েছে এবং যদি দূরবর্তী মেমরির জন্য অ্যাক্সেসগুলি 50% ধীর হয়, NUMA অ্যাক্সেসগুলি আপনার মেমরির অ্যাক্সেসগুলি 10% কমিয়ে দেয়। তদতিরিক্ত, যদি আপনার কেবল একটি একক NUMA নোডে ফ্রি মেমরি থাকে তবে অনাহারে নোডে মেমরির প্রয়োজন সমস্ত প্রক্রিয়া অন্য নোড থেকে মেমরি বরাদ্দ করা হবে যা অ্যাক্সেস বেশি ব্যয়বহুল। সবচেয়ে খারাপ, অপারেটিং সিস্টেমটি অনাহারে থাকা নোডের মেমরির কিছু অংশ বদলানো ভাল ধারণা বলে মনে করতে পারে,যা আরও বেশি ব্যয়বহুল স্মৃতি অ্যাক্সেসের কারণ হতে পারে । এটি মাইএসকিউএল "অদলবদলতা" সমস্যা এবং NUMA আর্কিটেকচারের প্রভাবগুলিতে যেখানে লিনাক্সের জন্য কিছু সমাধান দেওয়া হয় সে সম্পর্কে আরও বিস্তারিতভাবে ব্যাখ্যা করা হয়েছে (অদলবদল এড়ানোর জন্য দূরবর্তী NUMA অ্যাক্সেসগুলিতে বুলেটটি কামড়ানো) আমি কোনও সকেটে আরও র‌্যাম বরাদ্দ করার কথা ভাবতে পারি (১ 16 এবং ১ instead গিগাবাইটের পরিবর্তে ২৪ এবং ৮ গিগাবাইট) এবং আপনার প্রোগ্রামটি বৃহত্তর NUMA নোডের সময়সূচী রয়েছে কিনা তা নিশ্চিত করার জন্য, তবে এটির জন্য কম্পিউটার এবং স্ক্রু ড্রাইভারের শারীরিক অ্যাক্সেস প্রয়োজন ;-) ।


4

এটি প্রতি সেটের কোনও উত্তর নয়, বরং হ্যান্স প্যাস্যান্ট মেমোরি সিস্টেমে বিলম্বের বিষয়ে কী লিখেছেন তার উপরে জোর দেওয়া।

সত্যিই উচ্চ পারফরম্যান্স সফ্টওয়্যার - যেমন কম্পিউটার গেমস - কেবল গেমটি প্রয়োগ করার জন্যই এটি রচিত হয় না, এমন কোড এবং ডেটা স্ট্রাকচারগুলি বেশিরভাগ ক্যাশে এবং মেমরি সিস্টেমগুলিকে তৈরি করে অর্থাৎ তাদের সীমিত সংস্থান হিসাবে বিবেচনা করে। আমি যখন ক্যাশের সমস্যাগুলি মোকাবিলা করি তখন আমি সাধারণত ধরে নিয়েছি যে ডেটা উপস্থিত থাকলে L1 3 টি চক্র সরবরাহ করবে। যদি এটি না হয় এবং আমাকে এল 2 এ যেতে হয় তবে আমি 10 চক্র গ্রহণ করি। L3 30 চক্রের জন্য এবং র‌্যাম মেমরি 100 এর জন্য।

মেমোরি সম্পর্কিত একটি অতিরিক্ত ক্রিয়া রয়েছে যা - আপনার যদি এটির প্রয়োজন হয় - এটি আরও বেশি জরিমানা আরোপ করে এবং এটি একটি বাস লক। আপনি যদি উইন্ডোজ এনটি কার্যকারিতা ব্যবহার করেন তবে বাস লকগুলিকে সমালোচনামূলক বিভাগ বলা হয়। আপনি যদি একটি বাড়ির মধ্যে প্রচুর জাত ব্যবহার করেন তবে আপনি এটিকে একটি স্পিনলক বলবেন। নামটি যাই হোক না কেন এটি লকটি স্থাপনের আগে সিস্টেমের সবচেয়ে ধীরতম বাস-মাস্টারিং ডিভাইসে সিঙ্ক্রোনাইজ করে। ধীরতম বাস-মাস্টারিং ডিভাইসটি হতে পারে একটি ক্লাসিক 32-বিট পিসিআই কার্ড সংযুক্ত @ 33MHz। 33MHz একটি সাধারণ x86 সিপিইউ (@ 3.3 গিগাহার্টজ) এর ফ্রিকোয়েন্সিটির এক শততম। আমি বাসের লকটি সম্পূর্ণ করতে 300 চক্রেরও কম নয় ধরে নিলাম তবে আমি জানি তারা 3 গুণ বেশি সময় নিতে পারে যদি আমি 3000 চক্র দেখি তবে আমি অবাক হব না।

নতুন ধরণের মাল্টি-থ্রেডিং সফটওয়্যার বিকাশকারীরা পুরো জায়গা জুড়ে বাসের লক ব্যবহার করবে এবং তারপরে কেন তাদের কোডটি ধীর হচ্ছে তা অবাক করে দেবে। কৌতুক - মেমরির সাথে যা কিছু করা দরকার তা হল - অ্যাক্সেসগুলিতে অর্থায়ন।

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