Skip to content

Commit be08dd9

Browse files
committed
Add first version of possible reorganization
1 parent e0a1597 commit be08dd9

7 files changed

Lines changed: 401 additions & 236 deletions

File tree

src/GraphBLAS-sharp/Abstracts.fs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,25 @@ and Mask2D(rowIndices: int[], columnIndices: int[], rowCount: int, columnCount:
9696
member this.RowCount = rowCount
9797
member this.ColumnCount = columnCount
9898
member this.IsComplemented = isComplemented
99+
100+
type COOFormat<'a> = {
101+
RowCount: int
102+
ColumnCount: int
103+
Rows: int[]
104+
Columns: int[]
105+
Values: 'a[]
106+
}
107+
108+
type CSRFormat<'a> = {
109+
ColumnCount: int
110+
RowPointers: int[]
111+
ColumnIndices: int[]
112+
Values: 'a[]
113+
}
114+
with
115+
static member CreateEmpty<'a>() = {
116+
RowPointers = Array.zeroCreate<int> 0
117+
ColumnIndices = Array.zeroCreate<int> 0
118+
Values = Array.zeroCreate<'a> 0
119+
ColumnCount = 0
120+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
namespace GraphBLAS.FSharp.Backend.Common
2+
3+
open Brahma.OpenCL
4+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
5+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
6+
open Utils
7+
8+
// functions in mudule could be named run\get\if\it\t
9+
// like mentioned here https://www.reddit.com/r/fsharp/comments/5kvsyk/modules_or_namespaces/dbt0zf7?utm_source=share&utm_medium=web2x&context=3
10+
module internal Scan =
11+
let rec v1 (inputArray: int[]) =
12+
let outputArray = Array.zeroCreate inputArray.Length
13+
14+
if inputArray.Length = 1 then
15+
let fillOutputArray =
16+
<@
17+
fun (ndRange: _1D)
18+
(inputArrayBuffer: int[])
19+
(outputArrayBuffer: int[]) ->
20+
21+
let i = ndRange.GlobalID0
22+
outputArrayBuffer.[i] <- inputArrayBuffer.[i]
23+
@>
24+
25+
opencl {
26+
let binder kernelP =
27+
let ndRange = _1D(outputArray.Length)
28+
kernelP
29+
ndRange
30+
inputArray
31+
outputArray
32+
do! RunCommand fillOutputArray binder
33+
return outputArray
34+
}
35+
else
36+
let intermediateArray = Array.zeroCreate ((inputArray.Length + 1) / 2)
37+
let inputArrayLength = inputArray.Length
38+
let intermediateArrayLength = intermediateArray.Length
39+
40+
let fillIntermediateArray =
41+
<@
42+
fun (ndRange: _1D)
43+
(inputArrayBuffer: int[])
44+
(intermediateArrayBuffer: int[]) ->
45+
46+
let i = ndRange.GlobalID0
47+
if i < intermediateArrayLength then
48+
if 2 * i + 1 < inputArrayLength then
49+
intermediateArrayBuffer.[i] <- inputArrayBuffer.[2 * i] + inputArrayBuffer.[2 * i + 1]
50+
else intermediateArrayBuffer.[i] <- inputArrayBuffer.[2 * i]
51+
@>
52+
53+
let fillIntermediateArray =
54+
opencl {
55+
let binder kernelP =
56+
let ndRange = _1D(workSize intermediateArray.Length, workGroupSize)
57+
kernelP
58+
ndRange
59+
inputArray
60+
intermediateArray
61+
do! RunCommand fillIntermediateArray binder
62+
}
63+
64+
let fillOutputArray =
65+
<@
66+
fun (ndRange: _1D)
67+
(auxiliaryPrefixSumArrayBuffer: int[])
68+
(inputArrayBuffer: int[])
69+
(outputArrayBuffer: int[]) ->
70+
71+
let i = ndRange.GlobalID0
72+
if i < inputArrayLength then
73+
let j = (i - 1) / 2
74+
if i % 2 = 0 then
75+
if i = 0 then outputArrayBuffer.[i] <- inputArrayBuffer.[i]
76+
else outputArrayBuffer.[i] <- auxiliaryPrefixSumArrayBuffer.[j] + inputArrayBuffer.[i]
77+
else outputArrayBuffer.[i] <- auxiliaryPrefixSumArrayBuffer.[j]
78+
@>
79+
80+
opencl {
81+
do! fillIntermediateArray
82+
let! auxiliaryPrefixSumArray = v1 intermediateArray
83+
84+
let binder kernelP =
85+
let ndRange = _1D(workSize inputArray.Length, workGroupSize)
86+
kernelP
87+
ndRange
88+
auxiliaryPrefixSumArray
89+
inputArray
90+
outputArray
91+
do! RunCommand fillOutputArray binder
92+
93+
return outputArray
94+
}
95+
96+
let v2 (inputArray: int[]) =
97+
let firstIntermediateArray = Array.copy inputArray
98+
let secondIntermediateArray = Array.copy inputArray
99+
let outputArrayLength = firstIntermediateArray.Length
100+
101+
let updateResult =
102+
<@
103+
fun (ndRange: _1D)
104+
(offset: int)
105+
(firstIntermediateArrayBuffer: int[])
106+
(secondIntermediateArrayBuffer: int[]) ->
107+
108+
let i = ndRange.GlobalID0
109+
if i < outputArrayLength then
110+
if i < offset then firstIntermediateArrayBuffer.[i] <- secondIntermediateArrayBuffer.[i]
111+
else firstIntermediateArrayBuffer.[i] <- secondIntermediateArrayBuffer.[i] + secondIntermediateArrayBuffer.[i - offset]
112+
@>
113+
114+
let binder offset firstIntermediateArray secondIntermediateArray kernelP =
115+
let ndRange = _1D(workSize outputArrayLength, workGroupSize)
116+
kernelP
117+
ndRange
118+
offset
119+
firstIntermediateArray
120+
secondIntermediateArray
121+
122+
let swap (a, b) = (b, a)
123+
let mutable arrays = firstIntermediateArray, secondIntermediateArray
124+
125+
opencl {
126+
let mutable offset = 1
127+
while offset < outputArrayLength do
128+
arrays <- swap arrays
129+
do! RunCommand updateResult <| (binder offset <|| arrays)
130+
offset <- offset * 2
131+
132+
return (fst arrays)
133+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace GraphBLAS.FSharp.Backend.Common
2+
3+
module internal Utils =
4+
let workGroupSize = 128
5+
let workSize n =
6+
let m = n - 1
7+
m - m % workGroupSize + workGroupSize
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
namespace GraphBLAS.FSharp.Backend
2+
3+
open Brahma.OpenCL
4+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
5+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
6+
open GraphBLAS.FSharp
7+
open GraphBLAS.FSharp.Backend.Common
8+
9+
module internal EWiseAdd =
10+
let coo (matrixLeft: COOFormat<'a>) (matrixRight: COOFormat<'a>) (mask: Mask2D option) (semiring: Semiring<'a>) : OpenCLEvaluation<COOFormat<'a>> =
11+
let workGroupSize = Utils.workGroupSize
12+
let (BinaryOp append) = semiring.PlusMonoid.Append
13+
let zero = semiring.PlusMonoid.Zero
14+
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 @>
21+
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[]) ->
49+
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+
@>
92+
93+
let createSortedConcatenation =
94+
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
109+
}
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 =
131+
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
141+
}
142+
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[]) ->
156+
157+
let i = ndRange.GlobalID0
158+
159+
if i < auxiliaryArrayLength && auxiliaryArrayBuffer.[i] = 1 then
160+
let index = prefixSumArrayBuffer.[i] - 1
161+
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 =
172+
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+
}
188+
189+
opencl {
190+
do! createSortedConcatenation
191+
do! filterThroughMask
192+
do! fillAuxiliaryArray
193+
do! createUnion
194+
195+
return {
196+
RowCount = matrixLeft.RowCount
197+
ColumnCount = matrixLeft.ColumnCount
198+
Rows = resultRows
199+
Columns = resultColumns
200+
Values = resultValues
201+
}
202+
}

src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
<Compile Include="Operators.fs" />
1515
<Compile Include="Monoid.fs" />
1616
<Compile Include="Semiring.fs" />
17-
<Compile Include="Toolbox.fs" />
1817
<Compile Include="Scalar.fs" />
1918
<Compile Include="Abstracts.fs" />
19+
<Compile Include="Backend/Common/Utils.fs" />
20+
<Compile Include="Backend/Common/Scan.fs" />
21+
<Compile Include="Backend//EWiseAdd.fs" />
2022
<Compile Include="Implementations.fs" />
2123
<Compile Include="Matrix.fs" />
2224
<Compile Include="Vector.fs" />

0 commit comments

Comments
 (0)