2014-11-03 16 views
5

Bir dizi sıralama algoritmasını karşılaştırmak için ev ödevimi yapıyorum ve garip bir fenomene rastladım. Şeyler beklendiği gibi oldu: insertionsort 20 inçlik tablo gibi bir şey için kazanma, aksi halde çabukluğu, heapsort ve mergesort üstün performans. 500.000 inçlik bir tabloya kadar (bellekte saklanır). 5.000.000 inç (hala hafızada saklanır) için, hızlı bağlantı, aniden daha kötü hale gelir, ardından heapsort ve mergesort. Sayılar her zaman eşit olarak dağıtılır, rasgele pencereler sanal bellek kapalıdır. Bunun sebebi ne olabilir?büyük tablolar için garip yavaş quicksort

 void quicksortit(T *tab,int s) { 
        if (s==0 || s==1) return; 
        T tmp; 
        if (s==2) { 
         if (tab[0]>tab[1]) { 
             tmp=tab[0]; 
             tab[0]=tab[1]; 
             tab[1]=tmp; 
             } 
         return; 
         } 
        T pivot=tab[s-1]; 
        T *f1,*f2; 
        f1=f2=tab; 
        for(int i=0;i<s;i++) 
          if (*f2>pivot) 
           f2++; 
          else { 
           tmp=*f1; 
           *f1=*f2; 
           *f2=tmp; 
           f1++; f2++; 
           } 
        quicksortit(tab,(f1-1)-tab); 
        quicksortit(f1,f2-f1); 
    }; 
+0

ama benim ilk tahminim işlemci cache fazla sayıda yaşıyoruz olduğu Örneğin

Daha büyük veri kümeleri nedeniyle. –

+0

Büyük dizilerle, algoritmayı çalıştırmaktansa iyi bir pivot değeri seçmek daha önemlidir. 'P pivot = tab [s/2]' yi deneyin ve bunun nasıl yardımcı olduğunu görün – smac89

+0

Kodunuzun her bir çalışması için tohum değerinizi değiştiriyor musunuz, yoksa her zaman aynı 5 milyonluk boyut dizisini kullanıyor musunuz? – jxh

cevap

11

Dizide çok sayıda yineleme olduğunda algoritma başarısız oluyor. Bunu sadece büyük değerlerde fark ettiniz, çünkü büyük bir yayılma alanı olan
aralığındaki rastgele değerleri beslemektesiniz (rand: (0 - RAND_MAX) ile rand() kullandığınızı varsayalım ve bu problem sadece büyük dizilerde görünüyor.

Aynı sayıda bir diziyi sıralamaya çalıştığınızda (100000 aynı sayıları ayırmayı deneyin, program çökecektir) ilk önce tüm dizi boyunca gereksiz şekilde değiştiren öğelerden geçeceksiniz. Daha sonra ikiye dizi bölme, ancak büyük dizisi yalnızca 1 azaltılmıştır:

    v 
quicksortit(tab,(f1-1)-tab); 

Böylece Algoritma (n^2) O olur ve aynı zamanda istifin, çok büyük miktarda tüketir. Daha iyi bir pivot aramak, bu durumda size yardımcı olmayacaktır, bunun yerine bu kusuru sergilemeyen bir quicksort() sürümü seçin.

değiştirilmiş bir sürümü olan
function quicksort(array) 
    if length(array) > 1 
     pivot := select middle, or a median of first, last and middle 
     left := first index of array 
     right := last index of array 
     while left <= right 
      while array[left] < pivot 
       left := left + 1 
      while array[right] > pivot 
       right := right - 1 
      if left <= right 
       swap array[left] with array[right] 
       left := left + 1 
       right := right - 1 
     quicksort(array from first index to right) 
     quicksort(array from left to last index) 

: Sana verdiğim ne sistem bilmiyorum http://rosettacode.org/wiki/Sorting_algorithms/Quicksort

+1

Teşekkürler. Bu aslında kısmen sebebi. Başlangıçta, sayılar 0-9999 aralığındaydı. 'RAND_MAX' aralığındaki sayıların sıralanması bazı şeyleri biraz daha iyi hale getirir, yani hız sınırının kötü gittiği limiti artırır. – Domin

1

Diziniz artık L3 önbellekten daha büyük olabilir.

Quicksort bölümleme işlemi, rasgele öğeleri dizinin bir ucundan diğerine taşır. Tipik bir intel L3 önbellek 8MB gibi. 5M 4-byte elemanları ile - diziniz 20MB'dir. ve bir ucundan diğerine yazıyorsunuz.

Önbellek L3'ü ana belleğe kaydeder ve daha yüksek düzeyde önbellek eksiklerinden çok daha yavaş olabilir.

Şimdiye kadar olan tüm sıralama işlemi tamamen CPU'nun içinde çalışıyordu.

+0

Teşekkürler, bu durumda olabilir. Bu kodu farklı bir makinede belki farklı bir CPU ile kontrol edeceğim.Benimki i7-2630QM'dir (4 çekirdekli olarak 6MB ** l3 önbellek). – Domin

+0

Yine de ne yapmam gerekiyor olsa da, quicksort'un neden mergesort'tan çok farklı olduğunu. Heapsort'un L3 önbellek kısıtlaması ile çok kötü yapılabileceği oldukça açık - öğeler neredeyse rastgele bir şekilde okunup yazılıyor. Ancak, hem fastsort hem de mergesort tablosuna yerel olarak erişilir. Hızlı sıralama, orijinal tablonun parçalarına, "f1" ve "f2" yakınındaki bir işaretçiye yakın bir yerde saklanmalıdır. Mergesort'un, iki hareketli göstergenin yanında sadece iki yarım diziyi değil, aynı zamanda birleştirdiği tablonun en azından bir kısmını da depolaması gerekir. – Domin

İlgili konular