Parallel QuickSort using CCR
Since there was some requests to get the code for the parallel QuickSort mentioned here I decided to post the code I used. This is not a complete listing. You need the samples that can be downloaded from here. This listing is an extension to the Sort class in Chapter6/ParallelSort/Sort.cs.
1: private static DispatcherQueue queue =
2: new DispatcherQueue("CcrQueue");
3: private static Port<SortInfo> infoPort = new Port<SortInfo>();
4: private static Port<int> resultPort = new Port<int>();
5: private static EventWaitHandle done =
6: new EventWaitHandle(false, EventResetMode.ManualReset);
7: private static int remaining = 0;
8: private static int[] theArray = null;
9:
10: class SortInfo
11: {
12: public int from;
13: public int to;
14: public int depth;
15: }
16:
17: public static void CcrQuickSort(int[] array)
18: {
19: theArray = array;
20: remaining = array.Length;
21: Arbiter.Activate(queue,
22: Arbiter.Receive(true, infoPort, CcrSortPart));
23: Arbiter.Activate(queue,
24: Arbiter.Receive(false, resultPort, CcrSortPartDone));
25: infoPort.Post(
26: new SortInfo
27: {
28: from = 0,
29: to = array.Length,
30: depth =
31: (int) Math.Log(Environment.ProcessorCount,2)+4
32: });
33: done.WaitOne();
34: }
35:
36: private static void CcrSortPartDone(int count)
37: {
38: remaining -= count;
39: if (remaining <= 0)
40: done.Set();
41: else
42: Arbiter.Activate(queue,
43: Arbiter.Receive(false, resultPort, CcrSortPartDone));
44: }
45:
46: private static void CcrSortPart(SortInfo info)
47: {
48: if (info.from == info.to)
49: return;
50: if (info.to - info.from <= Threshold)
51: {
52: InsertionSort(theArray, info.from, info.to);
53: resultPort.Post(info.to - info.from);
54: }
55: else
56: {
57: int pivot = info.from;
58: pivot = Partition(theArray, info.from, info.to, pivot);
59: if (info.depth > 0)
60: {
61: infoPort.Post(new SortInfo
62: {
63: from = info.from,
64: to = pivot,
65: depth = info.depth - 1
66: });
67: infoPort.Post(new SortInfo
68: {
69: from = pivot + 1,
70: to = info.to,
71: depth = info.depth - 1
72: });
73: }
74: else
75: {
76: CcrSortPart(new SortInfo
77: {
78: from = info.from,
79: to = pivot
80: });
81: CcrSortPart(new SortInfo
82: {
83: from = pivot + 1,
84: to = info.to
85: });
86: }
87: resultPort.Post(1);
88: }
89: }
The use of a static array and remaining counter are obviously not a great design for your typical application, but sneaked in there in the hunt for a saving a few microseconds. Didn't really matter...