2011-05-10 24 views
13

Bir 2D dizilimini sahip olduğum tek bir değerle doldurmak istiyorum, ancak, bunu yapmak mümkün olduğunca hızlı bir şekilde yapmak istiyorum. 200k + ve üzeri zaman içinde bu dizilerin 200'den fazlası olacaktır. Buffer.BlockCopy ve Array.Copy'ye baktım, ancak her ikisi de kaynakların tek bir değer olmasıyla birlikte, sahip olduğum tek dizinin hedef olduğu kaynak/hedef olarak dizileri de alıyorlar.Tek bir değerle bir diziyi doldurmanın en hızlı yolu

Bir diziyi bir dizi değil, tek bir değer olan bir diziyle doldurmanın en hızlı yolu nedir?

+0

farklı şekillerde bir çift, bu adam daha yaygın olanlarından birkaç tane dışarı listeye aldı - ve o kriter kendisine bile nezaketini: http://www.dotnetperls.com/initialize-array İlkel olsalar bile, bellekte 200K'lık öğeler tutmak büyük bir yığın bellek yiyor - ne yapıyorsunuz? zaman erişim (ürün başına)? – debracey

+0

Çoğaltılamaz bir soru olamazdı, o diziyle diziye intialize etmek istediğini söylemedi, bir valeu – user613326

cevap

1

Bazı ilgili bilgiler için bkz. What is the equivalent of memset in C#?.

Bu soruda belirtildiği gibi (bunun bir dupe'sine oldukça yakın), unmanaged code'a girmek istemediğiniz sürece for döngüsü genellikle en iyisidir.

Yani bu oldukça hızlı olmalıdır:

int[] arr = new int[MAX_ELEMENTS]; 
for (int i = 0; i < arr.Length; ++i) 
{ 
    array[i] = MY_VALUE; 
} 

her şeyi olduğu gibi performansla ilgili bir şey çalışma almak, sonra darboğaz ne ölçün. "Tedbir" e vurgulayın. darboğaz ne olduğunu tahmin çalışmak genellikle kötü bir fikir (geçerli:.

1

Array.Copy daha iyi döngü için daha iyi duruma olabilir, bu nedenle kullanmak olasıdır

void FillArray<T>(T[] arr, T fillValue) 
{ 
    int i = 0; 
    if (arr.Length > 16) { 
    { 
     do { 
      array[i++] = fillValue; 
     } while (i < arr.Length) 
     while (i + 16 < arr.Length) { 
      Array.Copy(arr, 0, arr, i, 16); 
      i = i + 16; 
     } 
    } 
    while (i < arr.Length) 
    { 
     array[i++] = fillValue; 
    } 
} 

(Bir performansını görmek isterdim Bu ve farklı tür ve dizi boyutları için bu döngü arasındaki karşılaştırma)

8

Bulduğum en hızlı yöntem, kopyanın her seferinde iki katına çıkarılmasıyla birlikte Array.Copy yazılımını kullanır. tek bir değer veya bir değer dizisi olan dizi

20.000.000 dizi öğeyle yaptığım testte, bu işlev for döngüsünden iki kat daha hızlıdır.

using System; 

namespace Extensions 
{ 
    public static class ArrayExtensions 
    { 
     public static void Fill<T>(this T[] destinationArray, params T[] value) 
     { 
      if (destinationArray == null) 
      { 
       throw new ArgumentNullException("destinationArray"); 
      } 

      if (value.Length >= destinationArray.Length) 
      { 
       throw new ArgumentException("Length of value array must be less than length of destination"); 
      } 

      // set the initial array value 
      Array.Copy(value, destinationArray, value.Length); 

      int arrayToFillHalfLength = destinationArray.Length/2; 
      int copyLength; 

      for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1) 
      { 
       Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength); 
      } 

      Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength); 
     } 
    } 
} 

Ben http://coding.grax.com/2011/11/initialize-array-to-value-in-c-very.html bu konuda blogged ve http://coding.grax.com/2014/04/better-array-fill-function.html

+2

ile büyük bir bölüm için dizileri doldurmak anlamına gelebilirdi. [,] 'myLargeArray.Fill (yeni: Fill' uzatma ve (bu T [,] destinationArray T [,] değer)' doldurun 'kamu statik boşluğa imzasını değiştirdi ve şöyle denir {{double.NaN}, {double.NaN}}); ve iyi çalıştı. Teşekkürler! – Kaboo

İlgili konular