উত্তর:
অ্যারে (জ্যাজেড অ্যারে) এর অ্যারে বহুমাত্রিক অ্যারেগুলির চেয়ে দ্রুত এবং আরও কার্যকরভাবে ব্যবহার করা যেতে পারে। বহুমাত্রিক অ্যারেগুলিতে ভাল সিনট্যাক্স রয়েছে।
আপনি যদি দাগযুক্ত এবং বহুমাত্রিক অ্যারেগুলি ব্যবহার করে কিছু সাধারণ কোড লিখেন এবং তারপরে একটি আইএল বিচ্ছিন্নকরণকারীর সাহায্যে সংকলিত অ্যাসেমব্লিকে পরিদর্শন করেন তবে আপনি দেখতে পাবেন যে জাগড (বা একক মাত্রিক) অ্যারেগুলি থেকে স্টোরেজ এবং পুনরুদ্ধারটি সহজ আইএল নির্দেশনা রয়েছে যখন বহুমাত্রিক অ্যারেগুলির জন্য একই ক্রিয়াকলাপটি পদ্ধতি অনুরোধ যা সর্বদা ধীর হয়।
নিম্নলিখিত পদ্ধতিগুলি বিবেচনা করুন:
static void SetElementAt(int[][] array, int i, int j, int value)
{
array[i][j] = value;
}
static void SetElementAt(int[,] array, int i, int j, int value)
{
array[i, j] = value;
}
তাদের আইএল নিম্নলিখিত হবে:
.method private hidebysig static void SetElementAt(int32[][] 'array',
int32 i,
int32 j,
int32 'value') cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldelem.ref
IL_0003: ldarg.2
IL_0004: ldarg.3
IL_0005: stelem.i4
IL_0006: ret
} // end of method Program::SetElementAt
.method private hidebysig static void SetElementAt(int32[0...,0...] 'array',
int32 i,
int32 j,
int32 'value') cil managed
{
// Code size 10 (0xa)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: ldarg.3
IL_0004: call instance void int32[0...,0...]::Set(int32,
int32,
int32)
IL_0009: ret
} // end of method Program::SetElementAt
ঝাঁকুনিযুক্ত অ্যারেগুলি ব্যবহার করার সময় আপনি সহজেই সারি অদলবদল এবং সারি পুনরায় আকার হিসাবে এই ধরনের ক্রিয়াকলাপ সম্পাদন করতে পারেন। হতে পারে কিছু ক্ষেত্রে বহুমাত্রিক অ্যারেগুলির ব্যবহার আরও সুরক্ষিত হবে, তবে মাইক্রোসফ্ট এফএক্সকপও বলেছে যে আপনি যখন আপনার প্রকল্পগুলি বিশ্লেষণ করতে ব্যবহার করেন তখন জ্যাগড অ্যারেগুলি বহুমাত্রিকের পরিবর্তে ব্যবহার করা উচিত।
একটি বহুমাত্রিক অ্যারে একটি দুর্দান্ত লিনিয়ার মেমরি লেআউট তৈরি করে যখন একটি জেগড অ্যারে ইন্ডিরেশনের বেশ কয়েকটি অতিরিক্ত স্তর বোঝায়।
jagged[3][6]
ঝাঁকুনিযুক্ত অ্যারেতে মূল্য অনুসন্ধান করা এইভাবে var jagged = new int[10][5]
কাজ করে: সূচক 3 (যা একটি অ্যারে) তে উপাদানটি সন্ধান করুন এবং সেই অ্যারেতে সূচক 6-এ উপাদানটি দেখুন (যা একটি মান)। এই ক্ষেত্রে প্রতিটি মাত্রার জন্য, একটি অতিরিক্ত চেহারা আছে (এটি একটি ব্যয়বহুল মেমরি অ্যাক্সেস প্যাটার্ন)।
একটি বহুমাত্রিক অ্যারে মেমরিতে রৈখিকভাবে বিছানো হয়, প্রকৃত মান সূচকগুলি একসাথে গুণ করে পাওয়া যায়। যাইহোক, অ্যারের দেওয়া var mult = new int[10,30]
, Length
যে বহুমাত্রিক অ্যারের সম্পত্তি মোট সংখ্যা ফেরৎ উপাদান অর্থাত্ 10 * 30 = 300।
Rank
একটি খাঁজকাটা অ্যারের সম্পত্তি সবসময় 1, কিন্তু একটি বহুমাত্রিক অ্যারের কোনো পদে থাকতে পারে। যে GetLength
কোনও অ্যারের পদ্ধতিটি প্রতিটি মাত্রার দৈর্ঘ্য পেতে ব্যবহার করা যেতে পারে। এই উদাহরণে বহুমাত্রিক অ্যারের জন্য mult.GetLength(1)
30 প্রদান করে।
বহুমাত্রিক অ্যারে সূচক করা দ্রুত হয়। উদাহরণস্বরূপ, বহুমাত্রিক অ্যারেটি দেওয়া mult[1,7]
= উদাহরণস্বরূপ = 30 * 1 + 7 = 37, সেই সূচকটিতে উপাদানটি পান 37 This এটি একটি আরও ভাল মেমরি অ্যাক্সেস প্যাটার্ন কারণ শুধুমাত্র একটি মেমরি অবস্থান জড়িত যা অ্যারের ভিত্তি ঠিকানা।
একটি বহুমাত্রিক অ্যারে সুতরাং একটি অবিচ্ছিন্ন মেমরি ব্লক বরাদ্দ করে, যখন একটি জেগড অ্যারে বর্গক্ষেত্র হতে হবে jagged[1].Length
না , উদাহরণস্বরূপ সমান jagged[2].Length
করতে হবে না, যা কোনও বহুমাত্রিক অ্যারের ক্ষেত্রে সত্য।
পারফরম্যান্স অনুযায়ী, বহুমাত্রিক অ্যারেগুলি দ্রুত হওয়া উচিত। অনেক দ্রুত, তবে সত্যই খারাপ সিএলআর বাস্তবায়নের কারণে তারা তা করছে না।
23.084 16.634 15.215 15.489 14.407 13.691 14.695 14.398 14.551 14.252
25.782 27.484 25.711 20.844 19.607 20.349 25.861 26.214 19.677 20.171
5.050 5.085 6.412 5.225 5.100 5.751 6.650 5.222 6.770 5.305
প্রথম সারিতে হ'ল দাগযুক্ত অ্যারের সময়, দ্বিতীয়টি বহুমাত্রিক অ্যারে প্রদর্শন করে এবং তৃতীয়টি, ভাল এটি কেমন হওয়া উচিত। প্রোগ্রামটি নীচে দেখানো হয়েছে, এফওয়াইআই এটি চলমান মনোতে পরীক্ষা করা হয়েছিল। (উইন্ডোজের সময়সীমা বেশিরভাগ সিএলআর বাস্তবায়নের বিভিন্নতার কারণে) different
উইন্ডোজগুলিতে, জেগড অ্যারেগুলির সময়গুলি বহুল মাত্রিক অ্যারেটি দেখতে কেমন হওয়া উচিত তার নিজের ব্যাখ্যা হিসাবে একই হিসাবে, 'একক ()' দেখুন greatly দুর্ভাগ্যক্রমে উইন্ডোজ জেআইটি-সংকলকটি সত্যই বোকা, এবং দুর্ভাগ্যক্রমে এই পারফরম্যান্স আলোচনাকে কঠিন করে তোলে, অনেকগুলি অসঙ্গতি রয়েছে।
এগুলি আমি উইন্ডোতে পেয়েছি এমন সময়গুলি, এখানে একই সমঝোতা, প্রথম সারিতে ঝাঁকুনিযুক্ত অ্যারে, দ্বিতীয় বহুমাত্রিক এবং তৃতীয়টি আমার বহুমাত্রিকের নিজস্ব বাস্তবায়ন, মনোর তুলনায় উইন্ডোতে এটি কতটা ধীর হয় তা লক্ষ করুন।
8.438 2.004 8.439 4.362 4.936 4.533 4.751 4.776 4.635 5.864
7.414 13.196 11.940 11.832 11.675 11.811 11.812 12.964 11.885 11.751
11.355 10.788 10.527 10.541 10.745 10.723 10.651 10.930 10.639 10.595
সোর্স কোড:
using System;
using System.Diagnostics;
static class ArrayPref
{
const string Format = "{0,7:0.000} ";
static void Main()
{
Jagged();
Multi();
Single();
}
static void Jagged()
{
const int dim = 100;
for(var passes = 0; passes < 10; passes++)
{
var timer = new Stopwatch();
timer.Start();
var jagged = new int[dim][][];
for(var i = 0; i < dim; i++)
{
jagged[i] = new int[dim][];
for(var j = 0; j < dim; j++)
{
jagged[i][j] = new int[dim];
for(var k = 0; k < dim; k++)
{
jagged[i][j][k] = i * j * k;
}
}
}
timer.Stop();
Console.Write(Format,
(double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
}
Console.WriteLine();
}
static void Multi()
{
const int dim = 100;
for(var passes = 0; passes < 10; passes++)
{
var timer = new Stopwatch();
timer.Start();
var multi = new int[dim,dim,dim];
for(var i = 0; i < dim; i++)
{
for(var j = 0; j < dim; j++)
{
for(var k = 0; k < dim; k++)
{
multi[i,j,k] = i * j * k;
}
}
}
timer.Stop();
Console.Write(Format,
(double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
}
Console.WriteLine();
}
static void Single()
{
const int dim = 100;
for(var passes = 0; passes < 10; passes++)
{
var timer = new Stopwatch();
timer.Start();
var single = new int[dim*dim*dim];
for(var i = 0; i < dim; i++)
{
for(var j = 0; j < dim; j++)
{
for(var k = 0; k < dim; k++)
{
single[i*dim*dim+j*dim+k] = i * j * k;
}
}
}
timer.Stop();
Console.Write(Format,
(double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
}
Console.WriteLine();
}
}
সহজভাবে বলতে গেলে বহুমাত্রিক অ্যারেগুলি ডিবিএমএসের একটি টেবিলের অনুরূপ।
অ্যারের অ্যারে (জ্যাজেড অ্যারে) আপনাকে প্রতিটি উপাদানকে একই ধরণের পরিবর্তনশীল দৈর্ঘ্যের আরেকটি অ্যারে ধরে রাখতে দেয়।
সুতরাং, আপনি যদি নিশ্চিত হন যে ডেটার গঠনটি কোনও টেবিলের মতো দেখাচ্ছে (স্থির সারি / কলাম), আপনি একটি বহুমাত্রিক অ্যারে ব্যবহার করতে পারেন। জেগড অ্যারে স্থির উপাদান এবং প্রতিটি উপাদান পরিবর্তনশীল দৈর্ঘ্যের একটি অ্যারে ধরে রাখতে পারে
উদাহরণস্বরূপ Psuedocode:
int[,] data = new int[2,2];
data[0,0] = 1;
data[0,1] = 2;
data[1,0] = 3;
data[1,1] = 4;
উপরেরটিকে 2x2 টেবিল হিসাবে ভাবুন:
1 | 2 3 | 4
int[][] jagged = new int[3][];
jagged[0] = new int[4] { 1, 2, 3, 4 };
jagged[1] = new int[2] { 11, 12 };
jagged[2] = new int[3] { 21, 22, 23 };
উপরের দিক থেকে প্রতিটি সারিতে ভেরিয়েবল সংখ্যক কলামের সংখ্যা হিসাবে ভাবুন:
1 | 2 | 3 | 4 11 | 12 21 | 22 | 23
উপস্থাপনা: এই মন্তব্যটি Okutane দ্বারা প্রদত্ত উত্তরটি সম্বোধন করার উদ্দেশ্যে করা হয়েছে , তবে এসও এর নির্বোধ খ্যাতি সিস্টেমের কারণে আমি এটি যেখানে এটি পোস্ট করতে পারি না can
পদ্ধতির কলগুলির কারণে আপনার দাবিটি অন্যটির তুলনায় ধীর। আরও জটিল সীমানা-পরীক্ষা করা অ্যালগরিদমের কারণে একজনের তুলনায় অন্যটি ধীর। আপনি সহজেই এটি আইএল নয়, সংকলিত সমাবেশে দেখে যাচাই করতে পারেন। উদাহরণস্বরূপ, আমার 4.5.৪ ইনস্টল-এ, ইএক্স এবং এডিএক্স-এ সংরক্ষিত সূচীগুলি সহ ইকেক্স দ্বারা নির্দেশিত একটি দ্বি-মাত্রিক অ্যারেতে সংরক্ষিত একটি উপাদান (এডেক্সে পয়েন্টার মাধ্যমে) অ্যাক্সেস করা দেখতে এরকম দেখাচ্ছে:
sub eax,[ecx+10]
cmp eax,[ecx+08]
jae oops //jump to throw out of bounds exception
sub edx,[ecx+14]
cmp edx,[ecx+0C]
jae oops //jump to throw out of bounds exception
imul eax,[ecx+0C]
add eax,edx
lea edx,[ecx+eax*4+18]
এখানে আপনি দেখতে পাবেন যে পদ্ধতি কল থেকে কোনও ওভারহেড নেই। সীমানা পরীক্ষা করা শূন্য-শূন্য সূচকগুলির সম্ভাবনার জন্য খুব সংশ্লেষিত ধন্যবাদ, যা জ্যাজেড অ্যারেগুলির সাথে অফারে নেই এমন কার্যকারিতা। আমরা যদি শূন্য-বিহীন ক্ষেত্রে সাব, সিএমপি এবং জেএমপিগুলি সরিয়ে ফেলি তবে কোডটি বেশ সমাধান করে (x*y_max+y)*sizeof(ptr)+sizeof(array_header)
। এই গণনাটি প্রায় দ্রুত (কোনও গুণকে শিফট দ্বারা প্রতিস্থাপন করা যেতে পারে, কারণ এটিই কারণ যা আমরা বাইটগুলি দুটি বিটের শক্তি হিসাবে আকার হিসাবে বেছে নিই) কোনও উপাদানটিতে এলোমেলো অ্যাক্সেসের জন্য অন্য কিছু হিসাবে।
আরেকটি জটিলতা হ'ল প্রচুর কেস রয়েছে যেখানে একটি আধুনিক সংকলক একক মাত্রার অ্যারেতে পুনরাবৃত্তি করার সময় উপাদান অ্যাক্সেসের জন্য নেস্টেড সীমা-চেকিং অপ্টিমাইজ করবে। ফলাফলটি এমন কোড যা মূলত অ্যারের সংলগ্ন মেমরির উপরে একটি সূচক পয়েন্টারটিকে অগ্রসর করে। বহুমাত্রিক অ্যারেগুলিতে নিষ্পাপ পুনরাবৃত্তি সাধারণত নেস্টেড যুক্তিযুক্ত একটি অতিরিক্ত স্তর জড়িত, তাই একটি সংকলক অপারেশন অনুকূলিতকরণ কম সম্ভাবনা। সুতরাং, যদিও একটি একক উপাদান অ্যাক্সেসের সীমানা-চেকিং ওভারহেড অ্যারের মাত্রা এবং আকারগুলির সাথে ধ্রুবক রানটাইমকে সঞ্চারিত করে, তফাতটি পরিমাপের জন্য একটি সাধারণ পরীক্ষা-নিরীক্ষা কার্যকর করতে অনেক সময় বেশি সময় নিতে পারে।
আমি এটি আপডেট করতে চাই, কারণ .NET কোর মধ্যে বহু-মাত্রিক অ্যারে জ্যাগড অ্যারেগুলির চেয়ে দ্রুত । আমি জন লেডেগ্রেনের কাছ থেকে পরীক্ষাগুলি চালিয়েছি এবং এগুলি .NET কোর ২.০ পূর্বরূপ দেখুন 2.
Debug (code optimalization disabled)
Running jagged
187.232 200.585 219.927 227.765 225.334 222.745 224.036 222.396 219.912 222.737
Running multi-dimensional
130.732 151.398 131.763 129.740 129.572 159.948 145.464 131.930 133.117 129.342
Running single-dimensional
91.153 145.657 111.974 96.436 100.015 97.640 94.581 139.658 108.326 92.931
Release (code optimalization enabled)
Running jagged
108.503 95.409 128.187 121.877 119.295 118.201 102.321 116.393 125.499 116.459
Running multi-dimensional
62.292 60.627 60.611 60.883 61.167 60.923 62.083 60.932 61.444 62.974
Running single-dimensional
34.974 33.901 34.088 34.659 34.064 34.735 34.919 34.694 35.006 34.796
আমি বিচ্ছিন্নতাগুলিতে দেখেছি এবং এটি আমি খুঁজে পেয়েছি
jagged[i][j][k] = i * j * k;
কার্যকর করার জন্য 34 নির্দেশাবলীর প্রয়োজন
multi[i, j, k] = i * j * k;
কার্যকর করার জন্য 11 নির্দেশাবলীর প্রয়োজন
single[i * dim * dim + j * dim + k] = i * j * k;
কার্যকর করতে 23 নির্দেশের প্রয়োজন
আমি একক মাত্রিক অ্যারেগুলি কেন বহুমাত্রিকের চেয়ে দ্রুততর ছিল তা সনাক্ত করতে সক্ষম হইনি তবে আমার অনুমান যে এটি সিপিইউতে তৈরি কিছু অনুকূলকরণের সাথে করা উচিত
মাল্টি-ডাইমেনশন অ্যারে (এন -1) -ডাইমেনশন ম্যাট্রিক্স।
সুতরাং int[,] square = new int[2,2]
বর্গাকার ম্যাট্রিক্সের 2x2 হয় int[,,] cube = new int [3,3,3]
বর্গাকার ম্যাট্রিক্সের 3x3 - একটি ঘনক্ষেত্র। আনুপাতিকতা প্রয়োজন হয় না।
জেগড অ্যারে কেবল অ্যারের অ্যারে - এমন একটি অ্যারে যেখানে প্রতিটি ঘরে একটি অ্যারে থাকে।
এমডিএ তাই সমানুপাতিক, জেডি নাও হতে পারে! প্রতিটি কোষে নির্বিচারে দৈর্ঘ্যের একটি অ্যারে থাকতে পারে!
অন্যান্য উত্তরগুলি ছাড়াও, নোট করুন যে একটি বহুমাত্রিক অ্যারেটি স্তূপের উপর একটি বড় চঙ্কিল বস্তু হিসাবে বরাদ্দ করা হয়েছে। এর কিছু জড়িত রয়েছে:
<gcAllowVeryLargeObjects>
বহুমাত্রিক অ্যারে জন্য পথ সামনে ইস্যু কি কখনো আসতে হবে আপনি শুধুমাত্র কি কখনো খাঁজকাটা অ্যারে ব্যবহার করুন।রূপান্তরকরণের জন্য ব্যবহারের জন্য এসেম্বনব্লি, ক্লাস, পদ্ধতি এবং সঞ্চিত পদ্ধতিগুলির একটি ডাটাবেস তৈরি করতে আমি ইল্ডাস্ম দ্বারা উত্পাদিত .il ফাইলগুলি পার্স করছি। আমি নিম্নলিখিতটি পেরিয়ে এসেছি, যা আমার পার্সিং ভেঙে দিয়েছে।
.method private hidebysig instance uint32[0...,0...]
GenerateWorkingKey(uint8[] key,
bool forEncryption) cil managed
সার্জ লিডিন, এপ্রেস রচিত বিশেষজ্ঞ। নেট 2.0 আইএল এসেমব্লার বইটি 2006, অধ্যায় 8, আদিম প্রকার ও স্বাক্ষর, পৃষ্ঠা 149-150 প্রকাশ করেছে।
<type>[]
বলা হয় এর ভেক্টর <type>
,
<type>[<bounds> [<bounds>**] ]
এর অ্যারে বলা হয় <type>
**
অর্থ পুনরাবৃত্তি হতে পারে, [ ]
অর্থ alচ্ছিক।
উদাহরণ: চলুন <type> = int32
।
1) অপরিবর্তিত int32[...,...]
নিম্ন সীমানা এবং আকারের একটি দ্বিমাত্রিক অ্যারে
2) int32[2...5]
নীচের গণ্ডি 2 এবং আকার 4 এর এক-মাত্রিক অ্যারে।
3) int32[0...,0...]
নিম্ন সীমা 0 এবং অপরিবর্তিত আকারের একটি দ্বিমাত্রিক অ্যারে।
টম
double[,]
একটি আয়তক্ষেত্রাকার অ্যারে, যখনdouble[][]
এটি "জাগেড অ্যারে" হিসাবে পরিচিত। প্রথমটিতে প্রতিটি সারির জন্য একই সংখ্যক "কলাম" থাকবে, যখন দ্বিতীয়টিতে (সম্ভাব্যভাবে) প্রতিটি সারির জন্য আলাদা আলাদা সংখ্যক "কলাম" থাকবে।