簡體   English   中英

為什么我的C#quicksort實現明顯慢於List <T> 。分類

[英]Why is my C# quicksort implementation significantly slower than List<T>.Sort

我在C#中實現了一個quicksort版本,並執行了一些快速基准測試來與C# List<T>.Sort 我發現我的實現比庫版本慢得多。 我想知道為什么。 這是一些粗略的基准數字。 對於輸入,我使用了一個隨機(均勻)生成的整數列表,其中包含很少的重復元素。 請注意,所有基准時間均為多次運行的平均值

100,000 elements
My code         0.096 seconds
List<T>.Sort    0.011 seconds

1,000,000 elements
My code         1.10 seconds
List<T>.Sort    0.14 seconds

我的代碼如下。 以下是我嘗試過的優化列表及其結果:

  • 在線 - 我試圖在線我的SwapChoosePivotIndex函數我看到了大約10%的改進。
  • 樞軸選擇 - 我知道我正在使用天真的樞軸選擇方法。 我也試過使用三個隨機元素的中位數。 這並沒有帶來太大的改善。 我猜這是因為我用於基准測試的輸入數據是均勻隨機的。
  • 並行性 - 我嘗試並行進行遞歸分區調用。 這似乎實際上增加了執行時間。
  • 特殊外殼小輸入 - 我嘗試切換到小輸入的插入排序(如List<T>.Sort聲稱要做)。 這產生了大約20%的改善。

通過這些優化的組合,我已經能夠將我的代碼降低到

100,000 elements -   0.062 seconds
1,000,000 elements - 0.740 seconds 

這仍然比庫Sort慢得多。 在我的代碼中有沒有明顯的解釋性能差距,或者是從更小的調整中剩下的70-80%的差距? 請注意,下面的代碼是我未經優化的基礎版本

public class Quicksorter<T> where T : IComparable<T>
{
    protected Random random;
    public Quicksorter()
    {
        random = new Random();
    }

    public void Sort(IList<T> items)
    {
        Partition(items, 0, items.Count-1);
    }

    private void Partition(IList<T> items, int startIndex, int endIndex)
    {
        if (startIndex >= endIndex)
            return;

        int pivotIndex = ChoosePivotIndex(items, startIndex, endIndex);
        T pivot = items[pivotIndex];

        // swap pivot and first element
        Swap(items, startIndex, pivotIndex);

        int partitionIndex = startIndex + 1;
        for (int frontierIndex = partitionIndex; frontierIndex <= endIndex; frontierIndex++)
        {
            if (items[frontierIndex].CompareTo(pivot) < 0)
            {
                Swap(items, frontierIndex, partitionIndex);
                partitionIndex++;
            }
        }
        // put pivot back
        items[startIndex] = items[partitionIndex-1];
        items[partitionIndex - 1] = pivot;

        // recursively sort left half
        Partition(items, startIndex, partitionIndex - 2);
        // recursively sort right half
        Partition(items, partitionIndex, endIndex);
    }

    protected virtual int ChoosePivotIndex(IList<T> items, int startIndex, int endIndex)
    {
        return random.Next(startIndex, endIndex);
    }

    private void Swap(IList<T> items, int aIndex, int bIndex)
    {
        T temp = items[aIndex];
        items[aIndex] = items[bIndex];
        items[bIndex] = temp;
    }
}

因為.NET Framework具有整數,字符串和其他內置類型的特殊情況排序方法。 它們不會產生調用代表進行比較等的成本。如果您使用內置類型比較排序,那么庫排序通常要快得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM