SORU
22 NİSAN 2015, ÇARŞAMBA


İç içe döngüler için daha hızlı bir alternatif?

Sayı kombinasyonları bir listesini oluşturmak için bir ihtiyaç var. Sayıları int yerine byte kullanabilmesi için oldukça küçük. Ancak mümkün olan her kombinasyonu elde etmek için çok sayıda iç içe geçmiş döngüleri gerektirir. Eğer peşinde olduğum şey yapmak için daha verimli bir yolu varsa merak ediyorum. Kod şimdiye kadar

var data = new List<byte[]>();
for (byte a = 0; a < 2; a  )
for (byte b = 0; b < 3; b  )
for (byte c = 0; c < 4; c  )
for (byte d = 0; d < 3; d  )
for (byte e = 0; e < 4; e  )
for (byte f = 0; f < 3; f  )
for (byte g = 0; g < 3; g  )
for (byte h = 0; h < 4; h  )
for (byte i = 0; i < 2; i  )
for (byte j = 0; j < 4; j  )
for (byte k = 0; k < 4; k  )
for (byte l = 0; l < 3; l  )
for (byte m = 0; m < 4; m  )
{
    data.Add(new [] {a, b, c, d, e, f, g, h, i, j, k, l, m});
}

BitArray bir şey düşünüyordum ama uygulamaya nasıl emin değilim.

Herhangi bir öneri büyük mutluluk duyacağız. Alternatif olarak, belki de bu istediğim şeyi yapmanın en hızlı yolu nedir?

EDİT Hızlı puan (orijinal sonrası bu koymadım özür dilerim) birkaç:

  • Numaraları ve sipariş onları (2, 3, 4, 3, 4, 3, 3 vb) çok önemli, bu yüzden kullanarak bir çözüm gibi Generating Permutations using LINQ yaramaz çünkü en yüksek değerler her bir 'sütun' farklı
  • Bir matematikçi değilim, eğer teknik terimleri kullanıyorum değilse özür dilerim 'permütasyon ve doğru:) kombinasyonları.'
  • Benyapınbu kombinasyon tek seferde doldurmak için gerek - sadece veya başka bir dizin tabanlı bir tane alabilirim
  • byte int, ben kullanmaktan daha hızlıdırgaranti. Ayrıca in yerine bayt 67m dizileri için çok fazla bellek kullanımı daha iyi
  • Nihai hedefim burada iç içe döngüler için daha hızlı bir alternatif aramak.
  • Düşündüm kullanarak paralel programlama, ama nedeniyle yinelemeli doğa çalışıyorum ulaşmak bulamadım ve bir şekilde bunu başarıyla (bile ConcurrentBag) - ancak ben mutlu olmak için yanlış olduğunu kanıtladı :)

SONUÇ

Caramiriel biraz zaman döngüler kapalı tıraş olan mikro-optimizasyonu iyi sağladı, doğru cevap olarak işaretledim. Eric de daha hızlı ön tahsis Listesine belirtti. Ama, bu aşamada iç içe döngüler aslında bunu yapmanın en hızlı yolu gibi görünüyor (moral bozucu, biliyorum!).

Eğer kriter ile 10 ** her döngüde 13 döngüler 4 sayma ile gitmeye çalışıyordum tam olarak denemek istiyorsanız - bu listede yaklaşık 67m çizgiler yapar. Benim makine (ı5-3320M 2.6 GHz) 2.2 s optimize edilmiş versiyonunu yapmak gerekir.

CEVAP
22 NİSAN 2015, ÇARŞAMBA


Bir yapı özelliklerini kullanmak ve peşin yapısı ayırabilirsiniz. Kapalı örneğinde bazı seviyeleri aşağıda kestim, ama bu detayları çözmek mümkün olacak eminim. Çalışır orijinal (serbest mod) göre yaklaşık 5-6 kat daha hızlı.

Blok:

struct ByteBlock
{
    public byte A;
    public byte B;
    public byte C;
    public byte D;
    public byte E;
}

Döngü:

var data = new ByteBlock[2byte4byte4];
var counter = 0;

var bytes = new ByteBlock();

for (byte a = 0; a < 2; a  )
{
    bytes.A = a;
    for (byte b = 0; b < 3; b  )
    {
        bytes.B = b;
        for (byte c = 0; c < 4; c  )
        {
            bytes.C = c;
            for (byte d = 0; d < 3; d  )
            {
                bytes.D = d;
                for (byte e = 0; e < 4; e  )
                {
                    bytes.E = e;
                    data[counter  ] = bytes;
                }
            }
        }
    }
}

Hızlı listeye eklemek için yeni bir liste her zaman ayırmak değil çünkü. Ayrıca bu listeyi oluştururken bu yana, diğer her değer (a,b,c,d,e) başvuru gerekiyor. Her değer sadece bir kere döngünün içinde değiştirilmiş olduğunu varsayabilirsiniz, bunu yapmak için (veri yerellik) optimize edebilelim.

Ayrıca okuma yan etkileri yorumlar.

Cevap List<T> yerine T[] bir kullanım için düzenlenmiş.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • chrmoe

    chrmoe

    7 Kasım 2006
  • 10 Daughters, 2 Sons

    10 Daughters

    10 Mart 2009
  • UCBerkeley

    UCBerkeley

    3 Mayıs 2006