Skip to content

Commit 918edae

Browse files
committed
Added filling vector from scalar with mask
1 parent 3929b4e commit 918edae

12 files changed

Lines changed: 478 additions & 21 deletions

File tree

src/App/Program.fs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,36 @@ let main argv =
2323

2424
let mutable oclContext = OpenCLEvaluationContext()
2525

26-
let len = 16777217
26+
let subLen = 128
27+
let modulo = 3
28+
let len = subLen * modulo
2729
let vector = COOVector.FromTuples(len + 5, Array.init len id, Array.create len 1)
30+
let maskVector = COOVector.FromTuples(len, Array.init subLen (fun i -> modulo * i), Array.create subLen true)
31+
// let len = 100
32+
// let vector = COOVector.FromTuples(len, [|0;1;2;3;4;5|], [|10;20;30;50;80;130|])
33+
// let maskVector = COOVector.FromTuples(len, [|1;5;7|], [|true;true;true|])
2834

2935
let workflow = graphblas {
30-
let! scalar = Vector.reduce Add.int (VectorCOO vector)
31-
do! Scalar.synchronize scalar
32-
return! (Scalar.extractValue scalar)
36+
let! mask = Vector.mask (VectorCOO maskVector)
37+
let! value = Scalar.create 0
38+
do! Vector.fillSubVector mask value (VectorCOO vector)
39+
40+
do! Vector.synchronize (VectorCOO vector)
41+
42+
return vector
3343
}
3444

3545
let result =
3646
workflow
3747
|> EvalGB.withClContext oclContext
3848
|> EvalGB.runSync
3949

40-
printfn "Result: %A" result
50+
// printfn "Result: %A" result
4151

42-
// let indices = resultVector.Indices
43-
// let values = resultVector.Values
52+
let indices = result.Indices
53+
let values = result.Values
4454

45-
// for i in 0 .. indices.Length - 1 do
46-
// printfn "(%i, %A)" indices.[i] values.[i]
55+
for i in 0 .. indices.Length - 1 do
56+
printfn "(%i, %A)" indices.[i] values.[i]
4757

4858
0
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
namespace GraphBLAS.FSharp.Backend.COOVector.EWiseAdd
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+
[<AutoOpen>]
10+
module internal Merge =
11+
let merge (leftIndices: int[]) (leftValues: 'a[]) (rightIndices: int[]) (rightValues: 'a[]) (mask: Mask1D option) : OpenCLEvaluation<int[] * 'a[]> = opencl {
12+
let workGroupSize = Utils.workGroupSize
13+
let firstSide = leftValues.Length
14+
let secondSide = rightValues.Length
15+
let sumOfSides = firstSide + secondSide
16+
17+
let merge =
18+
<@
19+
fun (ndRange: _1D)
20+
(firstIndicesBuffer: int[])
21+
(firstValuesBuffer: 'a[])
22+
(secondIndicesBuffer: int[])
23+
(secondValuesBuffer: 'a[])
24+
(allIndicesBuffer: int[])
25+
(allValuesBuffer: 'a[]) ->
26+
27+
let i = ndRange.GlobalID0
28+
29+
let mutable beginIdxLocal = local ()
30+
let mutable endIdxLocal = local ()
31+
let localID = ndRange.LocalID0
32+
if localID < 2 then
33+
let mutable x = localID * (workGroupSize - 1) + i - 1
34+
if x >= sumOfSides then x <- sumOfSides - 1
35+
let diagonalNumber = x
36+
37+
let mutable leftEdge = diagonalNumber + 1 - secondSide
38+
if leftEdge < 0 then leftEdge <- 0
39+
40+
let mutable rightEdge = firstSide - 1
41+
if rightEdge > diagonalNumber then rightEdge <- diagonalNumber
42+
43+
while leftEdge <= rightEdge do
44+
let middleIdx = (leftEdge + rightEdge) / 2
45+
let firstIndex = firstIndicesBuffer.[middleIdx]
46+
let secondIndex = secondIndicesBuffer.[diagonalNumber - middleIdx]
47+
if firstIndex < secondIndex then leftEdge <- middleIdx + 1 else rightEdge <- middleIdx - 1
48+
49+
// Here localID equals either 0 or 1
50+
if localID = 0 then beginIdxLocal <- leftEdge else endIdxLocal <- leftEdge
51+
barrier ()
52+
53+
let beginIdx = beginIdxLocal
54+
let endIdx = endIdxLocal
55+
let firstLocalLength = endIdx - beginIdx
56+
let mutable x = workGroupSize - firstLocalLength
57+
if endIdx = firstSide then x <- secondSide - i + localID + beginIdx
58+
let secondLocalLength = x
59+
60+
//First indices are from 0 to firstLocalLength - 1 inclusive
61+
//Second indices are from firstLocalLength to firstLocalLength + secondLocalLength - 1 inclusive
62+
let localIndices = localArray<int> workGroupSize
63+
64+
if localID < firstLocalLength then
65+
localIndices.[localID] <- firstIndicesBuffer.[beginIdx + localID]
66+
if localID < secondLocalLength then
67+
localIndices.[firstLocalLength + localID] <- secondIndicesBuffer.[i - beginIdx]
68+
barrier ()
69+
70+
if i < sumOfSides then
71+
let mutable leftEdge = localID + 1 - secondLocalLength
72+
if leftEdge < 0 then leftEdge <- 0
73+
74+
let mutable rightEdge = firstLocalLength - 1
75+
if rightEdge > localID then rightEdge <- localID
76+
77+
while leftEdge <= rightEdge do
78+
let middleIdx = (leftEdge + rightEdge) / 2
79+
let firstIndex = localIndices.[middleIdx]
80+
let secondIndex = localIndices.[firstLocalLength + localID - middleIdx]
81+
if firstIndex < secondIndex then leftEdge <- middleIdx + 1 else rightEdge <- middleIdx - 1
82+
83+
let boundaryX = rightEdge
84+
let boundaryY = localID - leftEdge
85+
86+
// boundaryX and boundaryY can't be off the right edge of array (only off the left edge)
87+
let isValidX = boundaryX >= 0
88+
let isValidY = boundaryY >= 0
89+
90+
let mutable fstIdx = 0
91+
if isValidX then fstIdx <- localIndices.[boundaryX]
92+
93+
let mutable sndIdx = 0
94+
if isValidY then sndIdx <- localIndices.[firstLocalLength + boundaryY]
95+
96+
if not isValidX || isValidY && fstIdx < sndIdx then
97+
allIndicesBuffer.[i] <- sndIdx
98+
allValuesBuffer.[i] <- secondValuesBuffer.[i - localID - beginIdx + boundaryY]
99+
else
100+
allIndicesBuffer.[i] <- fstIdx
101+
allValuesBuffer.[i] <- firstValuesBuffer.[beginIdx + boundaryX]
102+
@>
103+
104+
let allIndices = Array.zeroCreate sumOfSides
105+
let allValues = Array.create sumOfSides Unchecked.defaultof<'a>
106+
107+
do! RunCommand merge <| fun kernelPrepare ->
108+
let ndRange = _1D(Utils.workSize sumOfSides, workGroupSize)
109+
kernelPrepare
110+
ndRange
111+
leftIndices
112+
leftValues
113+
rightIndices
114+
rightValues
115+
allIndices
116+
allValues
117+
118+
return allIndices, allValues
119+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
namespace GraphBLAS.FSharp.Backend.COOVector.EWiseAdd
2+
3+
open Brahma.OpenCL
4+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
5+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
6+
open GraphBLAS.FSharp.Backend.Common
7+
open Microsoft.FSharp.Quotations
8+
9+
[<AutoOpen>]
10+
module internal PreparePositions =
11+
let preparePositions (allIndices: int[]) (allValues: 'a[]) (plus: Expr<'a -> 'a -> 'a>) : OpenCLEvaluation<int[]> = opencl {
12+
let length = allValues.Length
13+
14+
let preparePositions =
15+
<@
16+
fun (ndRange: _1D)
17+
(allIndicesBuffer: int[])
18+
(allValuesBuffer: 'a[])
19+
(rawPositionsBuffer: int[]) ->
20+
21+
let i = ndRange.GlobalID0
22+
23+
if i < length - 1 && allIndicesBuffer.[i] = allIndicesBuffer.[i + 1] then
24+
rawPositionsBuffer.[i] <- 0
25+
26+
//Do not drop explicit zeroes
27+
allValuesBuffer.[i + 1] <- (%plus) allValuesBuffer.[i] allValuesBuffer.[i + 1]
28+
29+
//Drop explicit zeroes
30+
// let localResultBuffer = (%plus) allValuesBuffer.[i] allValuesBuffer.[i + 1]
31+
// if localResultBuffer = zero then rawPositionsBuffer.[i + 1] <- 0 else allValuesBuffer.[i + 1] <- localResultBuffer
32+
@>
33+
34+
let rawPositions = Array.create length 1
35+
36+
do! RunCommand preparePositions <| fun kernelPrepare ->
37+
let ndRange = _1D(Utils.workSize (length - 1), Utils.workGroupSize)
38+
kernelPrepare
39+
ndRange
40+
allIndices
41+
allValues
42+
rawPositions
43+
44+
return rawPositions
45+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace GraphBLAS.FSharp.Backend.COOVector
2+
3+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
4+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
5+
open GraphBLAS.FSharp.Backend.Common
6+
open GraphBLAS.FSharp.Backend.COOVector.Utilities
7+
8+
module internal FillSubVector =
9+
let private runNotEmpty (leftIndices: int[]) (leftValues: 'a[]) (rightIndices: int[]) (scalar: 'a[]) : OpenCLEvaluation<int[] * 'a[]> = opencl {
10+
let! allIndices, allValues = mergeWithScalar leftIndices leftValues rightIndices scalar
11+
12+
let! rawPositions = preparePositionsWithoutPlus allIndices
13+
14+
return! setPositions allIndices allValues rawPositions
15+
}
16+
17+
let run (leftIndices: int[]) (leftValues: 'a[]) (rightIndices: int[]) (scalar: 'a[]) : OpenCLEvaluation<int[] * 'a[]> =
18+
if leftValues.Length = 0 then
19+
opencl {
20+
let! resultIndices = Copy.run rightIndices
21+
let! resultValues = Replicate.run rightIndices.Length scalar
22+
23+
return resultIndices, resultValues
24+
}
25+
26+
elif rightIndices.Length = 0 then
27+
opencl {
28+
return leftIndices, leftValues
29+
}
30+
31+
else
32+
runNotEmpty leftIndices leftValues rightIndices scalar
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
namespace GraphBLAS.FSharp.Backend.COOVector.FillSubVector
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+
[<AutoOpen>]
10+
module internal Merge =
11+
let merge (leftIndices: int[]) (leftValues: 'a[]) (rightIndices: int[]) (scalar: 'a[]) : OpenCLEvaluation<int[] * 'a[]> = opencl {
12+
let workGroupSize = Utils.workGroupSize
13+
let firstSide = leftValues.Length
14+
let secondSide = rightIndices.Length
15+
let sumOfSides = firstSide + secondSide
16+
17+
let merge =
18+
<@
19+
fun (ndRange: _1D)
20+
(firstIndicesBuffer: int[])
21+
(firstValuesBuffer: 'a[])
22+
(secondIndicesBuffer: int[])
23+
(scalarBuffer: 'a[])
24+
(allIndicesBuffer: int[])
25+
(allValuesBuffer: 'a[]) ->
26+
27+
let i = ndRange.GlobalID0
28+
29+
let mutable beginIdxLocal = local ()
30+
let mutable endIdxLocal = local ()
31+
let localID = ndRange.LocalID0
32+
if localID < 2 then
33+
let mutable x = localID * (workGroupSize - 1) + i - 1
34+
if x >= sumOfSides then x <- sumOfSides - 1
35+
let diagonalNumber = x
36+
37+
let mutable leftEdge = diagonalNumber + 1 - secondSide
38+
if leftEdge < 0 then leftEdge <- 0
39+
40+
let mutable rightEdge = firstSide - 1
41+
if rightEdge > diagonalNumber then rightEdge <- diagonalNumber
42+
43+
while leftEdge <= rightEdge do
44+
let middleIdx = (leftEdge + rightEdge) / 2
45+
let firstIndex = firstIndicesBuffer.[middleIdx]
46+
let secondIndex = secondIndicesBuffer.[diagonalNumber - middleIdx]
47+
if firstIndex < secondIndex then leftEdge <- middleIdx + 1 else rightEdge <- middleIdx - 1
48+
49+
// Here localID equals either 0 or 1
50+
if localID = 0 then beginIdxLocal <- leftEdge else endIdxLocal <- leftEdge
51+
barrier ()
52+
53+
let beginIdx = beginIdxLocal
54+
let endIdx = endIdxLocal
55+
let firstLocalLength = endIdx - beginIdx
56+
let mutable x = workGroupSize - firstLocalLength
57+
if endIdx = firstSide then x <- secondSide - i + localID + beginIdx
58+
let secondLocalLength = x
59+
60+
//First indices are from 0 to firstLocalLength - 1 inclusive
61+
//Second indices are from firstLocalLength to firstLocalLength + secondLocalLength - 1 inclusive
62+
let localIndices = localArray<int> workGroupSize
63+
64+
if localID < firstLocalLength then
65+
localIndices.[localID] <- firstIndicesBuffer.[beginIdx + localID]
66+
if localID < secondLocalLength then
67+
localIndices.[firstLocalLength + localID] <- secondIndicesBuffer.[i - beginIdx]
68+
barrier ()
69+
70+
if i < sumOfSides then
71+
let mutable leftEdge = localID + 1 - secondLocalLength
72+
if leftEdge < 0 then leftEdge <- 0
73+
74+
let mutable rightEdge = firstLocalLength - 1
75+
if rightEdge > localID then rightEdge <- localID
76+
77+
while leftEdge <= rightEdge do
78+
let middleIdx = (leftEdge + rightEdge) / 2
79+
let firstIndex = localIndices.[middleIdx]
80+
let secondIndex = localIndices.[firstLocalLength + localID - middleIdx]
81+
if firstIndex < secondIndex then leftEdge <- middleIdx + 1 else rightEdge <- middleIdx - 1
82+
83+
let boundaryX = rightEdge
84+
let boundaryY = localID - leftEdge
85+
86+
// boundaryX and boundaryY can't be off the right edge of array (only off the left edge)
87+
let isValidX = boundaryX >= 0
88+
let isValidY = boundaryY >= 0
89+
90+
let mutable fstIdx = 0
91+
if isValidX then fstIdx <- localIndices.[boundaryX]
92+
93+
let mutable sndIdx = 0
94+
if isValidY then sndIdx <- localIndices.[firstLocalLength + boundaryY]
95+
96+
if not isValidX || isValidY && fstIdx < sndIdx then
97+
allIndicesBuffer.[i] <- sndIdx
98+
allValuesBuffer.[i] <- scalarBuffer.[0]
99+
else
100+
allIndicesBuffer.[i] <- fstIdx
101+
allValuesBuffer.[i] <- firstValuesBuffer.[beginIdx + boundaryX]
102+
@>
103+
104+
let allIndices = Array.zeroCreate sumOfSides
105+
let allValues = Array.create sumOfSides Unchecked.defaultof<'a>
106+
107+
do! RunCommand merge <| fun kernelPrepare ->
108+
let ndRange = _1D(Utils.workSize sumOfSides, workGroupSize)
109+
kernelPrepare
110+
ndRange
111+
leftIndices
112+
leftValues
113+
rightIndices
114+
scalar
115+
allIndices
116+
allValues
117+
118+
return allIndices, allValues
119+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
namespace GraphBLAS.FSharp.Backend.COOVector.FillSubVector
2+
3+
open Brahma.OpenCL
4+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
5+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
6+
open GraphBLAS.FSharp.Backend.Common
7+
8+
[<AutoOpen>]
9+
module internal PreparePositions =
10+
let preparePositions (allIndices: int[]) : OpenCLEvaluation<int[]> = opencl {
11+
let length = allIndices.Length
12+
13+
let preparePositions =
14+
<@
15+
fun (ndRange: _1D)
16+
(allIndicesBuffer: int[])
17+
(rawPositionsBuffer: int[]) ->
18+
19+
let i = ndRange.GlobalID0
20+
21+
if i < length - 1 && allIndicesBuffer.[i] = allIndicesBuffer.[i + 1] then rawPositionsBuffer.[i] <- 0
22+
@>
23+
24+
let rawPositions = Array.create length 1
25+
26+
do! RunCommand preparePositions <| fun kernelPrepare ->
27+
let ndRange = _1D(Utils.workSize (length - 1), Utils.workGroupSize)
28+
kernelPrepare
29+
ndRange
30+
allIndices
31+
rawPositions
32+
33+
return rawPositions
34+
}

0 commit comments

Comments
 (0)