অ্যারে.কপি বনাম বাফার.ব্লককপি


124

অ্যারে.কপি এবং বাফার.ব্লককপি উভয়ই একই কাজ করে তবে BlockCopyদ্রুত বাইট-স্তরের আদিম অ্যারে অনুলিপি করা হয়, যেখানে Copyসাধারণ উদ্দেশ্য বাস্তবায়ন হয়। আমার প্রশ্নটি - কোন পরিস্থিতিতে আপনার ব্যবহার করা উচিত BlockCopy? আপনি যখন আদিম ধরণের অ্যারেগুলি অনুলিপি করছেন তখন যে কোনও সময় এটি ব্যবহার করা উচিত, বা আপনি যদি পারফরম্যান্সের জন্য কোডিং করছেন তবেই এটি ব্যবহার করা উচিত? Buffer.BlockCopyওভার ব্যবহার সম্পর্কে সহজাতভাবে বিপজ্জনক কিছু আছে কি Array.Copy?


3
ভুলে যাবেন না Marshal.Copy:-)। ভাল, Array.Copyরেফারেন্স ধরণের জন্য, জটিল মান ধরণের এবং যদি প্রকারটি পরিবর্তন না Buffer.BlockCopyহয় তবে মান ধরণের, বাইট অ্যারে এবং বাইট যাদুতে "রূপান্তর" করার জন্য ব্যবহার করুন। F.ex. StructLayoutআপনি কী করছেন তা যদি জানেন তবে এর সাথে সম্মিলনটি বেশ শক্তিশালী। পারফরম্যান্সের ক্ষেত্রে, এটি মনে হয় যে এটির জন্য একটি নিয়ন্ত্রণহীন কল memcpy/ cpblkএটি সবচেয়ে দ্রুত - কোড4 k.blogspot.nl/2010/10/… দেখুন
অ্যাটলাস্ট

1
আমি কিছু বেনমার্ক পরীক্ষা দিয়েছিলাম byte[]। রিলিজ সংস্করণে কোনও পার্থক্য ছিল না। কখনও কখনও Array.Copy, কখনও কখনও Buffer.BlockCopy(সামান্য) দ্রুত।
বিটারব্লু

স্রেফ নীচে পোস্ট করা নতুন ব্যাপক উত্তর। মনে রাখবেন যে ছোট বাফার আকারগুলির ক্ষেত্রে, স্পষ্টত লুপ অনুলিপিটি সবচেয়ে ভাল।
বিশেষ সস

আমি মনে করি না যে তারা সবসময় একই কাজ করে - আপনি অ্যারে ব্যবহার করতে পারবেন না instance ইনটসের অ্যারেটি বাইটের অ্যারে অনুলিপি করতে উদাহরণস্বরূপ
এমসিএমিলাব

Array.Copyবরং একটি বিশেষ সংস্করণ - উদাহরণস্বরূপ এটি কেবল একই র‌্যাঙ্ক অ্যারে অনুলিপি করতে পারে।
নভোচারী

উত্তর:


59

যেহেতু প্যারামিটারগুলি Buffer.BlockCopyইনডেক্স-ভিত্তিকের চেয়ে বাইট-ভিত্তিক Array.Copy, তাই আপনি যদি ব্যবহার করেন তবে আপনার কোডটি স্ক্রু তৈরির সম্ভাবনা বেশি , তাই আমি কেবল Buffer.BlockCopyআমার কোডের একটি পারফরম্যান্স-সমালোচনা বিভাগে ব্যবহার করব।


9
সম্পূর্ণ একমত. বাফার.ব্লককপি-তে ত্রুটির জন্য অনেক বেশি জায়গা রয়েছে। এটিকে সহজ রাখুন এবং আপনার প্রোগ্রাম থেকে কোনও রস বের করার চেষ্টা করবেন না যতক্ষণ না আপনি জানেন যে রসটি কোথায় রয়েছে (প্রোফাইলিং)।
স্টিফেন

5
আপনি যদি বাইট নিয়ে কাজ করছেন []? ব্লককপি সহ অন্য কোনও গেটছ আছে?
কোকো

4
@ থিকোপ: আপনি যদি বাইট নিয়ে কাজ করছেন [] তবে ব্লককপি ব্যবহার করা সম্ভবত ভাল, যদি না পরে "বাইট" এর সংজ্ঞাটি বাইট ব্যতীত অন্য কোনও জায়গায় পরিবর্তিত করা হয়, যা সম্ভবত অন্যান্য অংশগুলিতে বেশ নেতিবাচক প্রভাব ফেলবে আপনার কোড যাইহোক। :) কেবলমাত্র অন্য সম্ভাব্য গোটচা হ'ল ব্লককপি কেবল স্ট্রেইট বাইট করে, তাই এটি অন্তর্নিহিততাটিকে বিবেচনায় নেয় না, তবে এটি কেবল একটি উইন্ডোজ নন মেশিনে খেলতে আসবে, এবং কেবলমাত্র যদি আপনি কোডটি আঁকেন d প্রথম স্থান. এছাড়াও, আপনি মনো ব্যবহার করছেন তবে কিছু অদ্ভুত পার্থক্য থাকতে পারে।
মুসিজেনেসিস

6
আমার নিজের পরীক্ষায়, অ্যারে.কপি () বাফার.ব্লককপি () এর সাথে পারফরম্যান্সে খুব মিল। 640 এলিমেন্ট বাইট অ্যারে নিয়ে কাজ করার সময় বাফার.ব্লককপি আমার জন্য ধারাবাহিক <10% দ্রুত (যা আমি সবচেয়ে বেশি আগ্রহী সে অনুসারে)। তবে আপনার নিজের ডেটা দিয়ে আপনার নিজের টেস্টিং করা উচিত, কারণ এটি সম্ভবত ডেটা, ডেটা ধরণের, অ্যারের মাপ এবং এর উপর নির্ভর করে পৃথক হবে। আমার মনে রাখা উচিত যে দুটি পদ্ধতিই অ্যারে.ক্লোন () ব্যবহার করার চেয়ে প্রায় 3x দ্রুত এবং সম্ভবত লুপের জন্য এটি অনুলিপি করার চেয়ে 20x দ্রুত।
কেন স্মিথ

3
@ কেভিনমিলার: আহ, UInt16উপাদান প্রতি দুটি বাইট। যদি আপনি অ্যারের উপাদানগুলির সংখ্যার সাথে এই অ্যারেটিকে ব্লককপিতে পাস করেন তবে অবশ্যই অর্ধেক অ্যারেটি অনুলিপি করা হবে। এটি সঠিকভাবে কাজ করার জন্য আপনাকে প্রতিটি উপাদান (2) এর আকারের দৈর্ঘ্য প্যারামিটার হিসাবে কয়েক গুণ উপাদানের সংখ্যা পাস করতে হবে । এমএসডিএন.মাইক্রোসফট /en-us/library/… এবং INT_SIZEউদাহরণগুলির জন্য অনুসন্ধান করুন ।
মুসিজেনেসিস

129

প্রস্তাবনা

আমি দেরিতে দলে যোগ দিচ্ছি, তবে ৩২ কে ভিউ নিয়ে এই অধিকার পাওয়ার পক্ষে এটি মূল্যবান। পোস্ট করা উত্তরের বেশিরভাগ মাইক্রোব্যাঙ্কমার্কিং কোড এ পর্যন্ত এক বা একাধিক গুরুতর প্রযুক্তিগত ত্রুটিগুলিতে ভুগছে, এর মধ্যে পরীক্ষার লুপগুলি (যা গুরুতর জিসি আর্টিকাগুলি প্রবর্তন করে) ভেরিয়েবল বনাম ডিটারমিনিটিক এক্সিকিউশন ফ্লো পরীক্ষা না করে জেআইটি ওয়ার্মআপ, এবং আন্ত-পরীক্ষার পরিবর্তনশীলতা ট্র্যাকিং করা হয় না। তদতিরিক্ত, বেশিরভাগ উত্তরগুলি বিভিন্ন বাফার আকার এবং বিভিন্ন প্রকারভেদে আদিম ধরণের প্রভাবগুলি (32-বিট বা 64-বিট সিস্টেমের ক্ষেত্রে) পরীক্ষা করে নি। এই প্রশ্নটি আরও বিস্তৃতভাবে সমাধান করার জন্য, আমি এটি তৈরি করেছি এমন একটি কাস্টম মাইক্রোব্যাঙ্কমার্কিং ফ্রেমওয়ার্ক যা আমি সাধারণ "গোটচস" সবচেয়ে বেশি কমিয়ে আউট করে তোলে developed 32-বিট মেশিন এবং একটি 64-বিট মেশিন উভয়ের জন্য .NET 4.0 রিলিজ মোডে পরীক্ষা করা হয়েছিল। 20 টি টেস্ট রানের ফলাফল গড়ে গড়ে ছিল, যেখানে প্রতিটি রান পদ্ধতিতে 1 মিলিয়ন ট্রায়াল ছিল। আদিম ধরণের পরীক্ষিত ছিলbyte(1 বাইট), int(4 বাইট) এবং double(8 বাইট)। তিনটি পদ্ধতির পরীক্ষা করা হয়েছিল: Array.Copy(), Buffer.BlockCopy()একটি লুপ, এবং সহজ প্রতি সূচক নিয়োগ। ডেটা এখানে পোস্ট করার জন্য খুব প্রচুর পরিমাণে, তাই আমি গুরুত্বপূর্ণ পয়েন্ট সংক্ষেপে করব।

টেকওয়েস

  • আপনার বাফার দৈর্ঘ্য 75-100 বা তার কম হয়, তাহলে একটি সুনির্দিষ্ট লুপ কপি রুটিন সাধারণত দ্রুত (5 সম্পর্কে% করে) হয় চেয়ে Array.Copy()বা Buffer.BlockCopy()3 আদিম উভয় 32 বিট এবং 64-বিট মেশিনে পরীক্ষা করা ধরনের জন্য। তদতিরিক্ত, সুস্পষ্ট লুপ অনুলিপি রুটিন দুটি বিকল্পের তুলনায় পারফরম্যান্সে লক্ষণীয়ভাবে কম পরিবর্তনশীলতা রয়েছে। ভাল পারফরম্যান্স প্রায় অবশ্যই সিপিইউ এল 1 / এল 2 / এল 3 মেমরি ক্যাশে কোনও পদ্ধতি কল ওভারহেড সঙ্গে একযোগে মেশিন ক্যাশে দ্বারা শোষণ রেফারেন্স স্থানীয়তার কারণে ।
    • জন্য doubleবাফার 32 বিট মেশিন শুধুমাত্র : স্পষ্ট লুপ কপি রুটিন ভাল চেয়ে সব বাফার জন্য উভয় বিকল্প 100 কিলোবাইট পর্যন্ত পরীক্ষিত মাপ হয়। অন্যান্য পদ্ধতির তুলনায় উন্নতি 3-5% ভাল। এটি হ'ল কারণ স্থানীয় 32-বিট প্রস্থের পারফরম্যান্স Array.Copy()এবং Buffer.BlockCopy()সম্পূর্ণ অবনতি ঘটে । সুতরাং আমি ধরে নিই একই প্রভাবটি longবাফারগুলিতেও প্রযোজ্য ।
  • 100 ডলার ছাড়িয়ে বাফার আকারের জন্য, স্পষ্টভাবে লুপ অনুলিপি করা অন্যান্য 2 টি পদ্ধতির তুলনায় খুব ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে হয়ে যায় (একটি নির্দিষ্ট ব্যতিক্রম কেবলমাত্র উল্লিখিত হয়েছে) particular পার্থক্যটি সবচেয়ে লক্ষণীয় byte[], যেখানে স্পষ্টত লুপ অনুলিপি বড় বাফার আকারে 7x বা আরও ধীর হয়ে যেতে পারে become
  • সাধারণভাবে, 3 আদিম ধরনের জন্য পরীক্ষিত এবং সব বাফার মাপ জুড়ে, Array.Copy()এবং Buffer.BlockCopy()প্রায় অভিন্নরুপে সঞ্চালিত। গড়ে, Array.Copy()যদিও - 2 সম্পর্কে% বা কম সময় নিয়ে যাওয়া (0.5% ভাল টিপিক্যাল কিন্তু 0.2%) খুব সামান্য প্রান্ত আছে বলে মনে হয় Buffer.BlockCopy()করেনি মাঝেমধ্যে এটা বীট। অজানা কারণে, Buffer.BlockCopy()তুলনায় লক্ষণীয়ভাবে আরও বেশি আন্তঃ-পরীক্ষা পরিবর্তনশীলতা রয়েছে Array.Copy()। আমার একাধিক প্রশমন চেষ্টা করেও কেন এটি সম্পর্কে অপারেশনাল তত্ত্ব না থাকা সত্ত্বেও এই প্রভাবটি দূর করা যায়নি।
  • কারণ Array.Copy()একটি "বুদ্ধিমান", আরও সাধারণ এবং অনেক বেশি নিরাপদ পদ্ধতি, খুব সামান্য দ্রুত হওয়া এবং গড়পড়তা কম পরিবর্তনশীলতা ছাড়াও Buffer.BlockCopy()প্রায় সমস্ত সাধারণ ক্ষেত্রে এটিকে অগ্রাধিকার দেওয়া উচিত । Buffer.BlockCopy()উত্স এবং গন্তব্য অ্যারে মানের ধরণগুলি (কেন স্মিথের উত্তরে নির্দেশিত হিসাবে) পৃথক হলে একমাত্র ব্যবহারের ক্ষেত্রে উল্লেখযোগ্যভাবে আরও ভাল হবে। যদিও এই Array.Copy()দৃশ্যটি সাধারণ নয়, এর প্রত্যক্ষ castালাইয়ের তুলনায় ক্রমাগত "নিরাপদ" মান ধরণের কাস্টিংয়ের কারণে এখানে খুব খারাপভাবে পারফর্ম করতে পারে Buffer.BlockCopy()
  • একই ধরণের অ্যারে অনুলিপি করার Array.Copy()চেয়ে দ্রুত স্ট্যাকওভারফ্লো এর বাইরে থেকে অতিরিক্ত প্রমাণ Buffer.BlockCopy()পাওয়া যাবে

একটি সরাইয়া হিসাবে, এটি দেখা যাচ্ছে যে 100-একটি অ্যারের দৈর্ঘ্য প্রায় যখন .NET হয় Array.Clear()প্রথম (সেটিং একটি অ্যারের একটি সুনির্দিষ্ট লুপ নিয়োগ ক্লিয়ারিং বীট শুরু false, 0বা, null)। এটি উপরের আমার অনুরূপ অনুসন্ধানের সাথে সামঞ্জস্যপূর্ণ। এই পৃথক মানদণ্ডগুলি
বিশেষ সস

আপনি যখন বাফার আকার বলতে; আপনি বাইট, বা উপাদান গণনা মানে?
dmarra

আমার উপরের উত্তরে, "বাফার দৈর্ঘ্য" এবং "বাফার সাইজ" উভয়ই সাধারণত উপাদান গণনা উল্লেখ করে।
বিশেষ সস

আমার একটি উদাহরণ রয়েছে যেখানে আমার প্রায়শই 8 বাইটের ডেটা 5 বাইট দ্বারা অফসেট করা উত্স থেকে বাফার রিডিংয়ে অনুলিপি করা উচিত। আমি স্পষ্টভাবে লুপ অনুলিপিটি উল্লেখযোগ্যভাবে দ্রুত হতে পেয়েছি এবং তারপরে বাফার.ব্লককপি বা অ্যারে.কপি ব্যবহার করুন। Loop Results for 1000000 iterations 17.9515ms. Buffer.BlockCopy Results for 1000000 iterations 39.8937ms. Array.Copy Results for 1000000 iterations 45.9059ms তবে, যদি অনুলিপি আকার> ~ 20 বাইট স্পষ্ট লুপ উল্লেখযোগ্যভাবে ধীর হয়।
টড কানিংহাম

@ টডকানিংহাম, 8 বাইট ডেটা? আপনি দীর্ঘ সমতা মানে? হয় একক উপাদান (দ্রুত মারা যাওয়া) কাস্ট করুন এবং অনুলিপি করুন বা কেবল সেই লুপটি ম্যানুয়ালি আনরোল করুন।
নভোচারী 13

67

যখন এটি ব্যবহারে বোধগম্য হয় তার আরেকটি উদাহরণ Buffer.BlockCopy()হ'ল যখন আপনাকে প্রিমিটিভগুলির একটি অ্যারে সরবরাহ করা হয় (বলুন, শর্টস), এবং এটিকে বাইটের অ্যারেতে রূপান্তরিত করা দরকার (বলুন, নেটওয়ার্কের মাধ্যমে সংক্রমণের জন্য)। সিলভারলাইট অডিওসিংকের অডিও নিয়ে কাজ করার সময় আমি এই পদ্ধতিটি ঘন ঘন ব্যবহার করি। এটি নমুনাটিকে short[]অ্যারে হিসাবে সরবরাহ করে তবে আপনি byte[]যে প্যাকেট জমা দিচ্ছেন তা তৈরি করার সময় আপনাকে এটিটিকে অ্যারেতে রূপান্তর করতে হবে Socket.SendAsync()। আপনি BitConverterএকের পর এক অ্যারে ব্যবহার করতে এবং পুনরাবৃত্তি করতে পারেন , তবে এটি করার জন্য এটি অনেক দ্রুত (আমার পরীক্ষার প্রায় 20x):

Buffer.BlockCopy(shortSamples, 0, packetBytes, 0, shortSamples.Length * sizeof(short)).  

এবং একই কৌশলটি বিপরীতেও কাজ করে:

Buffer.BlockCopy(packetBytes, readPosition, shortSamples, 0, payloadLength);

এটি নিরাপদ সি # তে যত কাছাকাছি (void *)মেমরি পরিচালনার ধরণের যা আপনি সি এবং সি ++ তে সাধারণ।


6
এটি একটি দুর্দান্ত ধারণা - আপনি কি কখনও এডিয়নেস নিয়ে সমস্যা নিয়ে যান?
ফিলিপ

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

কেনের ব্লগকপি সম্পর্কে ব্লগকপি সম্পর্কে একটি নিবন্ধ আছে: ব্লগ.ওল্ডবেথিয়লজিয়ান ডটকম
ড্রু নোকস ২

4
নোট কোর ২.১ থেকে যেহেতু আপনি অনুলিপি না করে এটি করতে পারেন তা নোট করুন। MemoryMarshal.AsBytes<T>অথবা MemoryMarshal.Cast<TFrom, TTo>আপনাকে নিজের কোনও আদিম সিক্যুয়েন্সকে অন্য আদিম এর সিকোয়েন হিসাবে ব্যাখ্যা করতে দেয়।
টিমো

16

আমার পরীক্ষার উপর ভিত্তি করে, পারফরম্যান্স বাফার.ব্লককপিটিকে অ্যারে.কপির চেয়ে বেশি পছন্দ করার কোনও কারণ নয় । আমার পরীক্ষার থেকে অ্যারে.কপি আসলে বাফার.ব্লককপির চেয়ে দ্রুত is

var buffer = File.ReadAllBytes(...);

var length = buffer.Length;
var copy = new byte[length];

var stopwatch = new Stopwatch();

TimeSpan blockCopyTotal = TimeSpan.Zero, arrayCopyTotal = TimeSpan.Zero;

const int times = 20;

for (int i = 0; i < times; ++i)
{
    stopwatch.Start();
    Buffer.BlockCopy(buffer, 0, copy, 0, length);
    stopwatch.Stop();

    blockCopyTotal += stopwatch.Elapsed;

    stopwatch.Reset();

    stopwatch.Start();
    Array.Copy(buffer, 0, copy, 0, length);
    stopwatch.Stop();

    arrayCopyTotal += stopwatch.Elapsed;

    stopwatch.Reset();
}

Console.WriteLine("bufferLength: {0}", length);
Console.WriteLine("BlockCopy: {0}", blockCopyTotal);
Console.WriteLine("ArrayCopy: {0}", arrayCopyTotal);
Console.WriteLine("BlockCopy (average): {0}", TimeSpan.FromMilliseconds(blockCopyTotal.TotalMilliseconds / times));
Console.WriteLine("ArrayCopy (average): {0}", TimeSpan.FromMilliseconds(arrayCopyTotal.TotalMilliseconds / times));

উদাহরণ আউটপুট:

bufferLength: 396011520
BlockCopy: 00:00:02.0441855
ArrayCopy: 00:00:01.8876299
BlockCopy (average): 00:00:00.1020000
ArrayCopy (average): 00:00:00.0940000

1
এই উত্তরটি একটি মন্তব্য বেশি হওয়া সম্পর্কে দুঃখিত, কিন্তু একটি মন্তব্যের জন্য এটি দীর্ঘ ছিল। যেহেতু conক্যমত্যটি দেখে মনে হয়েছিল যে বাফার.ব্লককপিটি পারফরম্যান্সের জন্য ভাল, তাই আমি ভেবেছিলাম প্রত্যেকেরই সচেতন হওয়া উচিত যে আমি পরীক্ষার সাথে conকমত্য নিশ্চিত করতে পারিনি was
কেভিন

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

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

1
অ্যারে যুক্ত করার মতো op কপি উত্স পজিশনের জন্য দীর্ঘ সমর্থন করে তাই বড় বাইট অ্যারেগুলিকে ভেঙে এটি পরিসীমা ব্যতিক্রমের বাইরে ফেলে দেয় না।
অ্যালেক্সওয়েস্ট

2
আমি সবেমাত্র পরীক্ষার তৈরি করেছি ( বিটবুককেট.আর.ব্রেকি /৪/ tutis / commits/… ) আমি বলব আপনি যখন বাইট অ্যারে নিয়ে কাজ করছেন তখন দুটি পদ্ধতির মধ্যে ব্যবহারিক পারফরম্যান্সের কোনও পার্থক্য নেই।
ইগোর ব্রেজক

4

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

যদি আমরা 0,1,2,3,4 দিয়ে একটি ইন্টার অ্যারে তৈরি করি এবং প্রয়োগ করি:

অ্যারে.কপি (অ্যারে, 0, অ্যারে, 1, অ্যারে। দৈর্ঘ্য - 1);

আমরা প্রত্যাশার সাথে 0,0,1,2,3 দিয়ে শেষ করব।

এটি ব্লককপি দিয়ে চেষ্টা করুন এবং আমরা পাই: 0,0,2,3,4। যদি আমি এর array[0]=-1পরে নিয়োগ করি তবে এটি প্রত্যাশা অনুযায়ী -1,0,2,3,4 হয়ে যায়, তবে অ্যারের দৈর্ঘ্য যদি 6 এর মতো হয় তবে আমরা -1,256,2,3,4,5 পাই। বিপজ্জনক জিনিস। একটি বাইট অ্যারে অন্যটিতে অনুলিপি করা ছাড়া ব্লককপি ব্যবহার করবেন না।

অন্য একটি ক্ষেত্রে রয়েছে যেখানে আপনি কেবল অ্যারে ব্যবহার করতে পারেন op কপি: যদি অ্যারের আকার 2 ^ 31 এর বেশি হয়। অ্যারে.কপি একটি longআকার পরামিতি সঙ্গে একটি ওভারলোড আছে । ব্লককপিতে এটি নেই।


2
ব্লককপি সহ আপনার পরীক্ষার ফলাফল অপ্রত্যাশিত নয়। কারণ ব্লক অনুলিপি একবারে একটি বাইটের চেয়ে একবারে ডেটার অংশগুলি অনুলিপি করার চেষ্টা করে। একটি 32 বিট সিস্টেমে এটি একবারে 4 বাইট অনুলিপি করে, একটি 64 বিট সিস্টেমে এটি একবারে 8 বাইট অনুলিপি করে।
ফারাপ

তাই প্রত্যাশিত অপরিবর্তিত আচরণ।
বিনকি

2

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

আমি 1000000 এর সাথে 1000000 সিক্যুয়াল ডাবলসের অ্যারের জন্য প্রতিটি চেষ্টা করে যাচাই করেছিলাম to তবে আমি তখন প্রথম 900000 চক্র উপেক্ষা এবং বাকি বাকি গড়। সেক্ষেত্রে বাফার উচ্চতর।

private static void BenchmarkArrayCopies()
        {
            long[] bufferRes = new long[1000000];
            long[] arrayCopyRes = new long[1000000];
            long[] manualCopyRes = new long[1000000];

            double[] src = Enumerable.Range(0, 1000000).Select(x => (double)x).ToArray();

            for (int i = 0; i < 1000000; i++)
            {
                bufferRes[i] = ArrayCopyTests.ArrayBufferBlockCopy(src).Ticks;
            }

            for (int i = 0; i < 1000000; i++)
            {
                arrayCopyRes[i] = ArrayCopyTests.ArrayCopy(src).Ticks;
            }

            for (int i = 0; i < 1000000; i++)
            {
                manualCopyRes[i] = ArrayCopyTests.ArrayManualCopy(src).Ticks;
            }

            Console.WriteLine("Loop Copy: {0}", manualCopyRes.Average());
            Console.WriteLine("Array.Copy Copy: {0}", arrayCopyRes.Average());
            Console.WriteLine("Buffer.BlockCopy Copy: {0}", bufferRes.Average());

            //more accurate results - average last 1000

            Console.WriteLine();
            Console.WriteLine("----More accurate comparisons----");

            Console.WriteLine("Loop Copy: {0}", manualCopyRes.Where((l, i) => i > 900000).ToList().Average());
            Console.WriteLine("Array.Copy Copy: {0}", arrayCopyRes.Where((l, i) => i > 900000).ToList().Average());
            Console.WriteLine("Buffer.BlockCopy Copy: {0}", bufferRes.Where((l, i) => i > 900000).ToList().Average());
            Console.ReadLine();
        }

public class ArrayCopyTests
    {
        private const int byteSize = sizeof(double);

        public static TimeSpan ArrayBufferBlockCopy(double[] original)
        {
            Stopwatch watch = new Stopwatch();
            double[] copy = new double[original.Length];
            watch.Start();
            Buffer.BlockCopy(original, 0 * byteSize, copy, 0 * byteSize, original.Length * byteSize);
            watch.Stop();
            return watch.Elapsed;
        }

        public static TimeSpan ArrayCopy(double[] original)
        {
            Stopwatch watch = new Stopwatch();
            double[] copy = new double[original.Length];
            watch.Start();
            Array.Copy(original, 0, copy, 0, original.Length);
            watch.Stop();
            return watch.Elapsed;
        }

        public static TimeSpan ArrayManualCopy(double[] original)
        {
            Stopwatch watch = new Stopwatch();
            double[] copy = new double[original.Length];
            watch.Start();
            for (int i = 0; i < original.Length; i++)
            {
                copy[i] = original[i];
            }
            watch.Stop();
            return watch.Elapsed;
        }
    }

https://github.com/chivandikwa/Random-Benchmarks


5
আমি আপনার উত্তরের কোনও সময়সীমার ফলাফল দেখতে পাচ্ছি না। কনসোল আউটপুট অন্তর্ভুক্ত করুন।
টুলমেকারস্টেভ

0

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

    private static T[] CopyArray<T>(T[] a) where T:struct 
    {
        T[] res = new T[a.Length];
        int size = Marshal.SizeOf(typeof(T));
        DateTime time1 = DateTime.Now;
        Buffer.BlockCopy(a,0,res,0, size*a.Length);
        Console.WriteLine("Using Buffer blockcopy: {0}", (DateTime.Now - time1).Milliseconds);
        return res;
    }

    static void Main(string[] args)
    {
        int simulation_number = 50000000;
        int[] testarray1 = new int[simulation_number];

        int begin = 0;
        Random r = new Random();
        while (begin != simulation_number)
        {
            testarray1[begin++] = r.Next(0, 10000);
        }

        var copiedarray = CopyArray(testarray1);

        var testarray2 = new int[testarray1.Length];
        DateTime time2 = DateTime.Now;
        Array.Copy(testarray1, testarray2, testarray1.Length);
        Console.WriteLine("Using Array.Copy(): {0}", (DateTime.Now - time2).Milliseconds);
    }

3
কোনও অপরাধ নয় তবে আপনার পরীক্ষার ফলাফলটি সত্যই সহায়ক নয়;) সর্বোপরি "20 মিমি দ্রুত" আপনাকে সামগ্রিক সময় না জেনে কিছু বলে না। আপনি এই দুটি পরীক্ষা খুব আলাদা পদ্ধতিতে চালিয়েছেন। ব্লককপি মামলায় একটি অতিরিক্ত পদ্ধতি কল এবং আপনার অ্যারে.কপি ক্ষেত্রে আপনার লক্ষ্য অ্যারের বরাদ্দ নেই। মাল্টিথ্রেডিং ওঠানামা (সম্ভাব্য টাস্ক স্যুইচ, কোর স্যুইচ) এর কারণে আপনি প্রতিবার পরীক্ষা চালানোর সময় সহজেই বিভিন্ন ফলাফল পেতে পারেন।
বুনি 83

@ বুন্নি 83 মন্তব্যটির জন্য ধন্যবাদ। আমি টাইমার লোকেশনটি সামান্য সংশোধন করেছি যা এখনই একটি ভাল তুলনা করা উচিত। এবং আমি কিছুটা অবাক হয়েছি যে ব্লককপি আরে কোডির চেয়ে মোটেও দ্রুত নয়।
stt106
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.