Added pre-processor directive to control verbosity of output and another pre-processor to control use of ConcurrentQueue instead of normal Queues. No differences observed, but I was able to find the point of thread contention is copy constructor of BoggleBoard :)
Dev Ghai

Dev Ghai commited on 2014-01-06 00:29:54
Showing 2 changed files, with 33 additions and 9 deletions.

... ...
@@ -1,6 +1,7 @@
1
-#define DEVELOPING
1
+#define ROLL_WITH_DEFAULTS
2 2
 #define DO_THREADED
3 3
 #define DO_UNTHREADED
4
+//#define VERBOSE
4 5
 
5 6
 using System;
6 7
 using System.Collections.Generic;
... ...
@@ -27,17 +28,17 @@ namespace Boggle
27 28
             Stopwatch st = new Stopwatch();
28 29
             BoggleList bl = new BoggleList();
29 30
             Console.WriteLine("Current directory: {0}", Directory.GetCurrentDirectory());
30
-#if !DEVELOPING
31
+#if !ROLL_WITH_DEFAULTS
31 32
             string input;
32 33
             bool isError = false;
33 34
 #endif
34
-            int boardSideLength = 10;
35
+            int boardSideLength = 100;
35 36
             int minWordLength = 4;
36 37
 
37 38
             char wordListInput = 'Z';
38 39
             SupportedLists listToUseForLookup;
39 40
 
40
-#if !DEVELOPING
41
+#if !ROLL_WITH_DEFAULTS
41 42
             do
42 43
             {
43 44
                 isError = false;
... ...
@@ -69,7 +70,7 @@ namespace Boggle
69 70
                     throw new Exception("Unexpected!!");
70 71
             }
71 72
 
72
-#if !DEVELOPING
73
+#if !ROLL_WITH_DEFAULTS
73 74
             do
74 75
             {
75 76
                 isError = false;
... ...
@@ -110,7 +111,7 @@ namespace Boggle
110 111
             }
111 112
             boardString = randomDefaultString.ToString();
112 113
 
113
-#if !DEVELOPING
114
+#if !ROLL_WITH_DEFAULTS
114 115
             do
115 116
             {
116 117
                 isError = false;
... ...
@@ -126,14 +127,18 @@ namespace Boggle
126 127
             boardString = boardString.ToUpper();
127 128
 
128 129
             BoggleBoard board = new BoggleBoard(boardSideLength, boardString);
130
+#if VERBOSE
129 131
             board.Print();
132
+#endif
130 133
             BoggleSolver solver = new BoggleSolver(board, bl, minWordLength);
131 134
             st.Reset();
132 135
 #if DO_UNTHREADED
133 136
             st.Start();
134 137
             HashSet<WordOnBoard> wordsUnThreaded = solver.GetWordsOnBoard(false);
135 138
             st.Stop();
139
+#if VERBOSE
136 140
             PrintWords(wordsUnThreaded);
141
+#endif
137 142
 
138 143
             Console.WriteLine("Got solution in {0} ms. Number of words (UNTHREADED): {1}\n\n", st.ElapsedMilliseconds, wordsUnThreaded.Count);
139 144
 #endif
... ...
@@ -142,7 +147,9 @@ namespace Boggle
142 147
             st.Start();
143 148
             HashSet<WordOnBoard> wordsThreaded = solver.GetWordsOnBoard(true);
144 149
             st.Stop();
150
+#if VERBOSE
145 151
             PrintWords(wordsThreaded);
152
+#endif
146 153
             Console.WriteLine("\nGot solution in {0} ms. Number of words (THREADED): {1}.", st.ElapsedMilliseconds, wordsThreaded.Count);
147 154
 #endif
148 155
 #if DO_THREADED && DO_UNTHREADED
... ...
@@ -1,4 +1,9 @@
1
+#define CONCURRENT
2
+
1 3
 using System;
4
+#if CONCURRENT
5
+using System.Collections.Concurrent;
6
+#endif
2 7
 using System.Collections.Generic;
3 8
 using System.Text;
4 9
 using System.Threading;
... ...
@@ -15,11 +20,13 @@ namespace Boggle
15 20
         //WaitHandle.WaitAll can wait at most for 64 handles.
16 21
         int _MaxParallelSolvers;
17 22
         ManualResetEvent[] doneEvents;
23
+#if CONCURRENT
24
+        ConcurrentQueue<int> openSlots;
25
+#else
18 26
         Queue<int> openSlots;
27
+#endif
19 28
         int[] correspondingSlots;
20 29
 
21
-        static int doneEventCount;
22
-
23 30
         /// <summary>
24 31
         /// Constructor.
25 32
         /// </summary>
... ...
@@ -35,7 +42,11 @@ namespace Boggle
35 42
             _wordsOnBoard = new HashSet<WordOnBoard>(_wordEqualityComparer);
36 43
             _MaxParallelSolvers = _Board.Tiles.Length > 64 ? 64 : _Board.Tiles.Length;
37 44
             doneEvents = new ManualResetEvent[_MaxParallelSolvers];
45
+#if CONCURRENT
46
+            openSlots = new ConcurrentQueue<int>();
47
+#else
38 48
             openSlots = new Queue<int>();
49
+#endif
39 50
             correspondingSlots = new int[_Board.Tiles.Length];
40 51
 
41 52
             for (int i = 0; i < _MaxParallelSolvers; i++)
... ...
@@ -78,12 +89,18 @@ namespace Boggle
78 89
             int nextSlot;
79 90
             while (tileIndex < _Board.Tiles.Length)
80 91
             {
92
+#if CONCURRENT
93
+                while (openSlots.TryDequeue(out nextSlot) && tileIndex < _Board.Tiles.Length)
94
+#else
81 95
                 while (openSlots.Count > 0 && tileIndex < _Board.Tiles.Length)
96
+#endif
82 97
                 {
83 98
                     //Resume from the previous value
84 99
                     i = tileIndex / _Board.SideLength;
85 100
                     j = tileIndex % _Board.SideLength;
101
+#if !CONCURRENT
86 102
                     nextSlot = openSlots.Dequeue();
103
+#endif
87 104
                     if (doneEvents[nextSlot] != null)
88 105
                         doneEvents[nextSlot].Reset();
89 106
                     else
... ...
@@ -106,7 +123,7 @@ namespace Boggle
106 123
         private void CollectWordsFromPivotThreaded(Object obj)
107 124
         {
108 125
             Tile passedTile = (Tile)obj;
109
-            //Copy the board
126
+            //Copy the board. TODO: SHIT LOADS OF CONTENTION HERE BECAUSE BOGGLEBOARD IS NOT THREAD-FRIENDLY YET.
110 127
             BoggleBoard boardForThisThread = new BoggleBoard(this._Board);
111 128
             //Initialize a list that will hold the tiles that will make up the word. Its max size will be square of side.
112 129
             List<Tile> newWordList = new List<Tile>(_Board.Tiles.Length);
113 130