Skip to content

Commit 3a1f9e9

Browse files
committed
Merge remote-tracking branch 'artem/bfs-operations' into merged
2 parents b1e5f4f + f899288 commit 3a1f9e9

20 files changed

Lines changed: 733 additions & 21 deletions

File tree

src/GraphBLAS-sharp/Algorithms/BFS.fs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ module BFS =
1616
while not break' do
1717
currentLevel <- currentLevel + 1
1818

19+
let! currentLevelScalar = Scalar.create currentLevel
20+
1921
let! frontierMask = Vector.mask frontier
20-
do! Vector.fillSubVector levels frontierMask (Scalar currentLevel) // v[q] = d
22+
do! Vector.fillSubVector frontierMask levels currentLevelScalar
2123

2224
let! levelsComplemented = Vector.complemented levels
2325
do! Matrix.mxvWithMask AnyAll.bool levelsComplemented transposed frontier // q[!v] = (A' ||.&& q)' = q' ||.&& A -- replace + comp

src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@ module TriangleCounting =
1010
let! transposed = matrix' |> Matrix.transpose
1111

1212
let! lowerTriangularMask = lowerTriangular |> Matrix.mask
13-
let! (Scalar count) =
14-
(matrix', transposed)
15-
||> Matrix.mxmWithMask AddMult.int lowerTriangularMask
16-
>>= Matrix.reduce Add.int
13+
let! result = (matrix', transposed) ||> Matrix.mxmWithMask AddMult.int lowerTriangularMask
14+
let! count = result |> Matrix.reduce Add.int
1715

18-
return count
16+
return! (Scalar.exportValue count)
1917
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
open GraphBLAS.FSharp.Backend.COOVector.Utilities.AssignSubVector
8+
9+
module internal AssignSubVector =
10+
let private runNotEmpty (leftIndices: int[]) (leftValues: 'a[]) (rightIndices: int[]) (rightValues: 'a[]) (maskIndices: int[]) : OpenCLEvaluation<int[] * 'a[]> = opencl {
11+
let! bitmap, maskValues = intersect rightIndices rightValues maskIndices
12+
13+
let! resultIndices, resultValues, rawPositions = filter leftIndices leftValues maskIndices maskValues bitmap
14+
15+
let! rawPositions = preparePositions resultIndices rawPositions
16+
17+
return! setPositions resultIndices resultValues rawPositions
18+
}
19+
20+
let run (leftIndices: int[]) (leftValues: 'a[]) (rightIndices: int[]) (rightValues: 'a[]) (maskIndices: int[]) : OpenCLEvaluation<int[] * 'a[]> =
21+
if leftValues.Length = 0 then
22+
opencl {
23+
let! resultIndices = Copy.run rightIndices
24+
let! resultValues = Copy.run rightValues
25+
26+
return resultIndices, resultValues
27+
}
28+
29+
elif rightIndices.Length = 0 then
30+
opencl {
31+
return leftIndices, leftValues
32+
}
33+
34+
else
35+
runNotEmpty leftIndices leftValues rightIndices rightValues maskIndices

src/GraphBLAS-sharp/Backend/COOVector/EWiseAdd.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
55
open GraphBLAS.FSharp
66
open GraphBLAS.FSharp.Backend.Common
77
open GraphBLAS.FSharp.Backend.COOVector.Utilities
8+
open GraphBLAS.FSharp.Backend.COOVector.Utilities.EWiseAdd
89

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

src/GraphBLAS-sharp/Backend/COOVector/Utilities/Merge.fs renamed to src/GraphBLAS-sharp/Backend/COOVector/Utilities/EWiseAdd/Merge.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace GraphBLAS.FSharp.Backend.COOVector.Utilities
1+
namespace GraphBLAS.FSharp.Backend.COOVector.Utilities.EWiseAdd
22

33
open Brahma.OpenCL
44
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic

src/GraphBLAS-sharp/Backend/COOVector/Utilities/PreparePositions.fs renamed to src/GraphBLAS-sharp/Backend/COOVector/Utilities/EWiseAdd/PreparePositions.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace GraphBLAS.FSharp.Backend.COOVector.Utilities
1+
namespace GraphBLAS.FSharp.Backend.COOVector.Utilities.EWiseAdd
22

33
open Brahma.OpenCL
44
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic

0 commit comments

Comments
 (0)