|
1 | 1 | namespace GraphBLAS.FSharp.Backend.COOMatrix |
2 | 2 |
|
3 | | -open Brahma.OpenCL |
4 | 3 | open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic |
5 | 4 | open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation |
6 | 5 | open GraphBLAS.FSharp |
7 | 6 | open GraphBLAS.FSharp.Backend.Common |
8 | 7 |
|
9 | 8 | module internal EWiseAdd = |
10 | | - let run (matrixLeft: COOMatrix<'a>) (matrixRight: COOMatrix<'a>) (mask: Mask2D option) (semiring: ISemiring<'a>) : OpenCLEvaluation<COOMatrix<'a>> = |
11 | | - let workGroupSize = Utils.workGroupSize |
12 | | - let (ClosedBinaryOp append) = semiring.Plus |
13 | | - let zero = semiring.Zero |
| 9 | + let cooNotEmpty (matrixLeft: COOFormat<'a>) (matrixRight: COOFormat<'a>) (mask: Mask2D option) (semiring: Semiring<'a>) : OpenCLEvaluation<COOFormat<'a>> = opencl { |
| 10 | + let! allRows, allColumns, allValues = Merge.runForMatrix matrixLeft matrixRight mask |
14 | 11 |
|
15 | | - //It is useful to consider that the first array is longer than the second one |
16 | | - let firstRows, firstColumns, firstValues, secondRows, secondColumns, secondValues, plus = |
17 | | - if matrixLeft.Rows.Length > matrixRight.Rows.Length then |
18 | | - matrixLeft.Rows, matrixLeft.Columns, matrixLeft.Values, matrixRight.Rows, matrixRight.Columns, matrixRight.Values, append |
19 | | - else |
20 | | - matrixRight.Rows, matrixRight.Columns, matrixRight.Values, matrixLeft.Rows, matrixLeft.Columns, matrixLeft.Values, <@ fun x y -> (%append) y x @> |
| 12 | + let (BinaryOp append) = semiring.PlusMonoid.Append |
| 13 | + let! rawPositions = PreparePositions.runForMatrix allRows allColumns allValues append |
21 | 14 |
|
22 | | - let filterThroughMask = |
23 | | - opencl { |
24 | | - //TODO |
25 | | - () |
26 | | - } |
27 | | - |
28 | | - let allRows = Array.zeroCreate <| firstRows.Length + secondRows.Length |
29 | | - let allColumns = Array.zeroCreate <| firstColumns.Length + secondColumns.Length |
30 | | - let allValues = Array.create (firstValues.Length + secondValues.Length) zero |
31 | | - |
32 | | - let longSide = firstRows.Length |
33 | | - let shortSide = secondRows.Length |
34 | | - |
35 | | - let allRowsLength = allRows.Length |
36 | | - |
37 | | - let createSortedConcatenation = |
38 | | - <@ |
39 | | - fun (ndRange: _1D) |
40 | | - (firstRowsBuffer: int[]) |
41 | | - (firstColumnsBuffer: int[]) |
42 | | - (firstValuesBuffer: 'a[]) |
43 | | - (secondRowsBuffer: int[]) |
44 | | - (secondColumnsBuffer: int[]) |
45 | | - (secondValuesBuffer: 'a[]) |
46 | | - (allRowsBuffer: int[]) |
47 | | - (allColumnsBuffer: int[]) |
48 | | - (allValuesBuffer: 'a[]) -> |
| 15 | + let! resultRows, resultColumns, resultValues = SetPositions.runForMatrix allRows allColumns allValues rawPositions |
49 | 16 |
|
50 | | - let i = ndRange.GlobalID0 |
51 | | - |
52 | | - if i < allRowsLength then |
53 | | - let f n = if 0 > n + 1 - shortSide then 0 else n + 1 - shortSide |
54 | | - let mutable leftEdge = f i |
55 | | - |
56 | | - let g n = if n > longSide - 1 then longSide - 1 else n |
57 | | - let mutable rightEdge = g i |
58 | | - |
59 | | - while leftEdge <= rightEdge do |
60 | | - let middleIdx = (leftEdge + rightEdge) / 2 |
61 | | - let firstRow = firstRowsBuffer.[middleIdx] |
62 | | - let firstColumn = firstColumnsBuffer.[middleIdx] |
63 | | - let secondRow = secondRowsBuffer.[i - middleIdx] |
64 | | - let secondColumn = secondColumnsBuffer.[i - middleIdx] |
65 | | - if firstRow < secondRow || firstRow = secondRow && firstColumn < secondColumn then leftEdge <- middleIdx + 1 else rightEdge <- middleIdx - 1 |
66 | | - |
67 | | - let boundaryX = rightEdge |
68 | | - let boundaryY = i - leftEdge |
69 | | - |
70 | | - if boundaryX < 0 then |
71 | | - allRowsBuffer.[i] <- secondRowsBuffer.[boundaryY] |
72 | | - allColumnsBuffer.[i] <- secondColumnsBuffer.[boundaryY] |
73 | | - allValuesBuffer.[i] <- secondValuesBuffer.[boundaryY] |
74 | | - elif boundaryY < 0 then |
75 | | - allRowsBuffer.[i] <- firstRowsBuffer.[boundaryX] |
76 | | - allColumnsBuffer.[i] <- firstColumnsBuffer.[boundaryX] |
77 | | - allValuesBuffer.[i] <- firstValuesBuffer.[boundaryX] |
78 | | - else |
79 | | - let firstRow = firstRowsBuffer.[boundaryX] |
80 | | - let firstColumn = firstColumnsBuffer.[boundaryX] |
81 | | - let secondRow = secondRowsBuffer.[boundaryY] |
82 | | - let secondColumn = secondColumnsBuffer.[boundaryY] |
83 | | - if firstRow < secondRow || firstRow = secondRow && firstColumn < secondColumn then |
84 | | - allRowsBuffer.[i] <- secondRow |
85 | | - allColumnsBuffer.[i] <- secondColumn |
86 | | - allValuesBuffer.[i] <- secondValuesBuffer.[boundaryY] |
87 | | - else |
88 | | - allRowsBuffer.[i] <- firstRow |
89 | | - allColumnsBuffer.[i] <- firstColumn |
90 | | - allValuesBuffer.[i] <- firstValuesBuffer.[boundaryX] |
91 | | - @> |
| 17 | + return { |
| 18 | + RowCount = matrixLeft.RowCount |
| 19 | + ColumnCount = matrixLeft.ColumnCount |
| 20 | + Rows = resultRows |
| 21 | + Columns = resultColumns |
| 22 | + Values = resultValues |
| 23 | + } |
| 24 | + } |
92 | 25 |
|
93 | | - let createSortedConcatenation = |
| 26 | + let coo (matrixLeft: COOFormat<'a>) (matrixRight: COOFormat<'a>) (mask: Mask2D option) (semiring: Semiring<'a>) : OpenCLEvaluation<COOFormat<'a>> = |
| 27 | + if matrixLeft.Values.Length = 0 then |
94 | 28 | opencl { |
95 | | - let binder kernelP = |
96 | | - let ndRange = _1D(Utils.workSize allRows.Length, workGroupSize) |
97 | | - kernelP |
98 | | - ndRange |
99 | | - firstRows |
100 | | - firstColumns |
101 | | - firstValues |
102 | | - secondRows |
103 | | - secondColumns |
104 | | - secondValues |
105 | | - allRows |
106 | | - allColumns |
107 | | - allValues |
108 | | - do! RunCommand createSortedConcatenation binder |
| 29 | + let! resultRows = Copy.run matrixRight.Rows |
| 30 | + let! resultColumns = Copy.run matrixRight.Columns |
| 31 | + let! resultValues = Copy.run matrixRight.Values |
| 32 | + |
| 33 | + return { |
| 34 | + RowCount = matrixRight.RowCount |
| 35 | + ColumnCount = matrixRight.ColumnCount |
| 36 | + Rows = resultRows |
| 37 | + Columns = resultColumns |
| 38 | + Values = resultValues |
| 39 | + } |
109 | 40 | } |
110 | | - |
111 | | - let auxiliaryArray = Array.create allRows.Length 1 |
112 | | - |
113 | | - let fillAuxiliaryArray = |
114 | | - <@ |
115 | | - fun (ndRange: _1D) |
116 | | - (allRowsBuffer: int[]) |
117 | | - (allColumnsBuffer: int[]) |
118 | | - (allValuesBuffer: 'a[]) |
119 | | - (auxiliaryArrayBuffer: int[]) -> |
120 | | - |
121 | | - let i = ndRange.GlobalID0 + 1 |
122 | | - |
123 | | - if i < allRowsLength && allRowsBuffer.[i - 1] = allRowsBuffer.[i] && allColumnsBuffer.[i - 1] = allColumnsBuffer.[i] then |
124 | | - auxiliaryArrayBuffer.[i] <- 0 |
125 | | - let localResultBuffer = (%plus) allValuesBuffer.[i - 1] allValuesBuffer.[i] |
126 | | - //Drop explicit zeroes |
127 | | - if localResultBuffer = zero then auxiliaryArrayBuffer.[i] <- 0 else allValuesBuffer.[i] <- localResultBuffer |
128 | | - @> |
129 | | - |
130 | | - let fillAuxiliaryArray = |
| 41 | + elif matrixRight.Values.Length = 0 then |
131 | 42 | opencl { |
132 | | - let binder kernelP = |
133 | | - let ndRange = _1D(Utils.workSize (allRows.Length - 1), workGroupSize) |
134 | | - kernelP |
135 | | - ndRange |
136 | | - allRows |
137 | | - allColumns |
138 | | - allValues |
139 | | - auxiliaryArray |
140 | | - do! RunCommand fillAuxiliaryArray binder |
| 43 | + let! resultRows = Copy.run matrixLeft.Rows |
| 44 | + let! resultColumns = Copy.run matrixLeft.Columns |
| 45 | + let! resultValues = Copy.run matrixLeft.Values |
| 46 | + |
| 47 | + return { |
| 48 | + RowCount = matrixLeft.RowCount |
| 49 | + ColumnCount = matrixLeft.ColumnCount |
| 50 | + Rows = resultRows |
| 51 | + Columns = resultColumns |
| 52 | + Values = resultValues |
| 53 | + } |
141 | 54 | } |
| 55 | + else cooNotEmpty matrixLeft matrixRight mask semiring |
142 | 56 |
|
143 | | - let auxiliaryArrayLength = auxiliaryArray.Length |
144 | | - |
145 | | - let createUnion = |
146 | | - <@ |
147 | | - fun (ndRange: _1D) |
148 | | - (allRowsBuffer: int[]) |
149 | | - (allColumnsBuffer: int[]) |
150 | | - (allValuesBuffer: 'a[]) |
151 | | - (auxiliaryArrayBuffer: int[]) |
152 | | - (prefixSumArrayBuffer: int[]) |
153 | | - (resultRowsBuffer: int[]) |
154 | | - (resultColumnsBuffer: int[]) |
155 | | - (resultValuesBuffer: 'a[]) -> |
| 57 | + let sparseNotEmpty (leftIndices: int[]) (leftValues: 'a[]) (rightIndices: int[]) (rightValues: 'a[]) (mask: Mask1D option) (semiring: Semiring<'a>) : OpenCLEvaluation<int[] * 'a[]> = opencl { |
| 58 | + let! allIndices, allValues = Merge.runForVector leftIndices leftValues rightIndices rightValues mask |
156 | 59 |
|
157 | | - let i = ndRange.GlobalID0 |
| 60 | + let (BinaryOp append) = semiring.PlusMonoid.Append |
| 61 | + let! rawPositions = PreparePositions.runForVector allIndices allValues append |
158 | 62 |
|
159 | | - if i < auxiliaryArrayLength && auxiliaryArrayBuffer.[i] = 1 then |
160 | | - let index = prefixSumArrayBuffer.[i] - 1 |
| 63 | + return! SetPositions.runForVector allIndices allValues rawPositions |
| 64 | + } |
161 | 65 |
|
162 | | - resultRowsBuffer.[index] <- allRowsBuffer.[i] |
163 | | - resultColumnsBuffer.[index] <- allColumnsBuffer.[i] |
164 | | - resultValuesBuffer.[index] <- allValuesBuffer.[i] |
165 | | - @> |
166 | | - |
167 | | - let resultRows = Array.zeroCreate allRows.Length |
168 | | - let resultColumns = Array.zeroCreate allColumns.Length |
169 | | - let resultValues = Array.create allValues.Length zero |
170 | | - |
171 | | - let createUnion = |
| 66 | + let sparse (leftIndices: int[]) (leftValues: 'a[]) (rightIndices: int[]) (rightValues: 'a[]) (mask: Mask1D option) (semiring: Semiring<'a>) : OpenCLEvaluation<int[] * 'a[]> = |
| 67 | + if leftValues.Length = 0 then |
172 | 68 | opencl { |
173 | | - let! prefixSumArray = Scan.v2 auxiliaryArray |
174 | | - let binder kernelP = |
175 | | - let ndRange = _1D(Utils.workSize auxiliaryArray.Length, workGroupSize) |
176 | | - kernelP |
177 | | - ndRange |
178 | | - allRows |
179 | | - allColumns |
180 | | - allValues |
181 | | - auxiliaryArray |
182 | | - prefixSumArray |
183 | | - resultRows |
184 | | - resultColumns |
185 | | - resultValues |
186 | | - do! RunCommand createUnion binder |
187 | | - } |
| 69 | + let! resultIndices = Copy.run rightIndices |
| 70 | + let! resultValues = Copy.run rightValues |
188 | 71 |
|
189 | | - opencl { |
190 | | - do! createSortedConcatenation |
191 | | - do! filterThroughMask |
192 | | - do! fillAuxiliaryArray |
193 | | - do! createUnion |
| 72 | + return resultIndices, resultValues |
| 73 | + } |
| 74 | + elif rightIndices.Length = 0 then |
| 75 | + opencl { |
| 76 | + let! resultIndices = Copy.run leftIndices |
| 77 | + let! resultValues = Copy.run leftValues |
194 | 78 |
|
195 | | - return { |
196 | | - RowCount = matrixLeft.RowCount |
197 | | - ColumnCount = matrixLeft.ColumnCount |
198 | | - Rows = resultRows |
199 | | - Columns = resultColumns |
200 | | - Values = resultValues |
| 79 | + return resultIndices, resultValues |
201 | 80 | } |
202 | | - } |
| 81 | + else sparseNotEmpty leftIndices leftValues rightIndices rightValues mask semiring |
0 commit comments