|
1 |
| -Array queue is a bounded lock-based FIFO queue using |
2 |
| -an array. It uses 2 separate locks for head and tail. |
| 1 | +A Combining Tree is an N-ary tree of nodes, that follows |
| 2 | +software combining to reduce memory contention while |
| 3 | +updating a shared value. |
| 4 | + |
| 5 | +The shared value is placed at the root of the tree, and |
| 6 | +threads perfrom `getAndOp()` at the leaf nodes. Each leaf |
| 7 | +node handles N threads. The combined value is then |
| 8 | +propagated up the tree by an active thread. There can be |
| 9 | +several active threads, but eventually one active thread |
| 10 | +updates the root node. It then shares this message to all |
| 11 | +other threads behind it. |
| 12 | + |
| 13 | +This was contention at a single memory location is avoided. |
| 14 | +However, i guess that such a design is normally useful |
| 15 | +only in hardware, as it becomes too slow in software. |
| 16 | +Useful for educational purposes. |
| 17 | + |
| 18 | +```java |
| 19 | +CombiningTree.getAndOp(x, op): |
| 20 | +Gets current value, and then updates it. |
| 21 | +x: value to OP with, op: binary op |
| 22 | +1. Select leaf index using thread id. |
| 23 | +2. Perform get & op at desired leaf. |
| 24 | +``` |
| 25 | + |
| 26 | +```java |
| 27 | +CombiningTree.getAndOp(x, op, i): |
| 28 | +Gets current value, and then updates it. |
| 29 | +x: value to OP with, op: binary op, i: leaf index |
| 30 | +1. Perform get & op at desired leaf (ensure in limit). |
| 31 | +``` |
3 | 32 |
|
4 | 33 | ```java
|
5 |
| -enq(): |
6 |
| -1. Lock tail. |
7 |
| -2. Try enq. |
8 |
| -3. Unlock tail. |
| 34 | +Node.getAndOp(x, op) |
| 35 | +Gets current value, and then updates it. |
| 36 | +x: value to OP (accumulate), op: binary operator |
| 37 | +1. Wait until node is free. |
| 38 | +2. Perform get & op based on 3 possible cases. |
| 39 | +2a. Root node |
| 40 | +2b. Active thread (first to visit node) |
| 41 | +2c. Passive thread (visits later) |
9 | 42 | ```
|
10 | 43 |
|
11 | 44 | ```java
|
12 |
| -deq(): |
13 |
| -1. Lock head. |
14 |
| -2. Try deq. |
15 |
| -3. Unlock head. |
| 45 | +Node.getAndOpRoot(x, op) |
| 46 | +Performs get & op for root node. |
| 47 | +x: value to OP (accumulate), op: binary operator |
| 48 | +1. Get old value, by combining (a). |
| 49 | +2. Empty the node. |
| 50 | +3. Insert a OP x |
| 51 | +3. Return old value. |
16 | 52 | ```
|
17 | 53 |
|
18 | 54 | ```java
|
19 |
| -tryEnq(): |
20 |
| -1. Ensure queue is not full |
21 |
| -2. Save data at tail. |
22 |
| -3. Increment tail. |
| 55 | +Node.getAndOpActive(x, op) |
| 56 | +Performs get & op for active thread. |
| 57 | +x: value to OP (accumulate), op: binary operator |
| 58 | +1. Insert value. |
| 59 | +2. Wait until node is full, or timeout. |
| 60 | +3. We have the values, so start pushing. |
| 61 | +4. Combine values into one with OP. |
| 62 | +5. Push combined value to parent. |
| 63 | +6. Distribute recieved value for all threads. |
| 64 | +7. Start the pulling process. |
| 65 | +8. Decrement count (we have our pulled value). |
| 66 | +9. Return pulled value. |
23 | 67 | ```
|
24 | 68 |
|
25 | 69 | ```java
|
26 |
| -tryDeq(): |
27 |
| -1. Ensure queue is not empty. |
28 |
| -2. Return data at head. |
29 |
| -3. Increment head. |
| 70 | +Node.getAndOpPassive(x, op) |
| 71 | +Performs get & op for passive thread. |
| 72 | +x: value to OP (accumulate), op: binary operator |
| 73 | +1. Insert value. |
| 74 | +2. Wait until active thread has pulled value. |
| 75 | +3. Decrement count, one pulled value processed. |
| 76 | +4. If count is 0, the node is free. |
| 77 | +5. Return value of this thread. |
30 | 78 | ```
|
31 | 79 |
|
32 | 80 | ```bash
|
@@ -63,11 +111,12 @@ Total: 2500
|
63 | 111 | Was valid? true
|
64 | 112 | ```
|
65 | 113 |
|
66 |
| -See [ArrayQueue.java] for code, [Main.java] for test, and [repl.it] for output. |
| 114 | +See [CombiningTree.java], [Node.java] for code, [Main.java] for test, and [repl.it] for output. |
67 | 115 |
|
68 |
| -[ArrayQueue.java]: https://repl.it/@wolfram77/array-queue#ArrayQueue.java |
69 |
| -[Main.java]: https://repl.it/@wolfram77/array-queue#Main.java |
70 |
| -[repl.it]: https://array-queue.wolfram77.repl.run |
| 116 | +[CombiningTree.java]: https://repl.it/@wolfram77/combining-tree#CombiningTree.java |
| 117 | +[Node.java]: https://repl.it/@wolfram77/combining-tree#Node.java |
| 118 | +[Main.java]: https://repl.it/@wolfram77/combining-tree#Main.java |
| 119 | +[repl.it]: https://combining-tree.wolfram77.repl.run |
71 | 120 |
|
72 | 121 |
|
73 | 122 | ### references
|
|
0 commit comments