Skip to content

Commit 3929b4e

Browse files
committed
Added and tested operation of reducing vector
1 parent 2027a50 commit 3929b4e

13 files changed

Lines changed: 340 additions & 7 deletions

File tree

GraphBLAS-sharp.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "GraphBLAS-sharp.Benchmarks"
1717
EndProject
1818
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "docsTool", "docsTool\docsTool.fsproj", "{8855EC73-F6A1-43D3-AFBC-04A3E09F9BD9}"
1919
EndProject
20+
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "App", "src\App\App.fsproj", "{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}"
21+
EndProject
2022
Global
2123
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2224
Debug|Any CPU = Debug|Any CPU
@@ -78,10 +80,23 @@ Global
7880
{4C6EB3D0-B6BF-4FF5-BC77-CC7CB3F307E6}.Release|x64.Build.0 = Release|Any CPU
7981
{4C6EB3D0-B6BF-4FF5-BC77-CC7CB3F307E6}.Release|x86.ActiveCfg = Release|Any CPU
8082
{4C6EB3D0-B6BF-4FF5-BC77-CC7CB3F307E6}.Release|x86.Build.0 = Release|Any CPU
83+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
84+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
85+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Debug|x64.ActiveCfg = Debug|Any CPU
86+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Debug|x64.Build.0 = Debug|Any CPU
87+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Debug|x86.ActiveCfg = Debug|Any CPU
88+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Debug|x86.Build.0 = Debug|Any CPU
89+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
90+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Release|Any CPU.Build.0 = Release|Any CPU
91+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Release|x64.ActiveCfg = Release|Any CPU
92+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Release|x64.Build.0 = Release|Any CPU
93+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Release|x86.ActiveCfg = Release|Any CPU
94+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6}.Release|x86.Build.0 = Release|Any CPU
8195
EndGlobalSection
8296
GlobalSection(NestedProjects) = preSolution
8397
{5D30E174-2538-47AC-8443-318C8C5DC2C9} = {C397A34C-84F1-49E7-AEBC-2F9F2B196216}
8498
{1CA2E092-2320-451D-A4F0-9ED7C7C528CA} = {ACBEE43C-7A88-4FB1-9B06-DB064D22B29F}
8599
{4C6EB3D0-B6BF-4FF5-BC77-CC7CB3F307E6} = {DEF656DE-BCED-4C49-B5ED-950D4A29B78B}
100+
{B2C13ACA-2BF7-4C9F-9C3A-94B2B0228BB6} = {C397A34C-84F1-49E7-AEBC-2F9F2B196216}
86101
EndGlobalSection
87102
EndGlobal

src/App/App.fsproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp3.1</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<Compile Include="Program.fs" />
10+
</ItemGroup>
11+
12+
<ItemGroup>
13+
<ProjectReference Include="..\Graphblas-sharp\Graphblas-sharp.fsproj" />
14+
</ItemGroup>
15+
16+
</Project>

src/App/Program.fs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
open System
2+
open GraphBLAS.FSharp
3+
open GraphBLAS.FSharp.Predefined
4+
open Brahma.OpenCL
5+
open Brahma.FSharp.OpenCL.Core
6+
open Brahma.FSharp.OpenCL.Extensions
7+
open Helpers
8+
open FSharp.Quotations.Evaluator
9+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
10+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
11+
12+
[<EntryPoint>]
13+
let main argv =
14+
15+
// let leftVector = SparseVector<float>(30, [| 0;2;4;6;8;10;12;14 |], [| 4.3; 5.5; 32.4; 56.43; 54.67; 563.43; 765.43; 23.43 |])
16+
// let rightVector = SparseVector<float>(30, [| 1;3;5;7;9;11;13;15 |], [| -4.3; -5.5; -32.4; -0.43; 32.4; 56.43; 54.67; 563.43 |])
17+
18+
// let leftTuples : VectorTuples<int> = { Indices = [||]; Values = [||] }
19+
// let rightTuples : VectorTuples<int> = { Indices = [||]; Values = [||] }
20+
21+
// let leftVector = COOVector.FromTuples(100, [| 1;2;3;4;5 |], [| 5; 32; 56; 54; 563 |])
22+
// let rightVector = COOVector.FromTuples(100, [| 1;4;5;6;7;8;9 |], [| 32; -54; 54; 563; 563; 765; 23 |])
23+
24+
let mutable oclContext = OpenCLEvaluationContext()
25+
26+
let len = 16777217
27+
let vector = COOVector.FromTuples(len + 5, Array.init len id, Array.create len 1)
28+
29+
let workflow = graphblas {
30+
let! scalar = Vector.reduce Add.int (VectorCOO vector)
31+
do! Scalar.synchronize scalar
32+
return! (Scalar.extractValue scalar)
33+
}
34+
35+
let result =
36+
workflow
37+
|> EvalGB.withClContext oclContext
38+
|> EvalGB.runSync
39+
40+
printfn "Result: %A" result
41+
42+
// let indices = resultVector.Indices
43+
// let values = resultVector.Values
44+
45+
// for i in 0 .. indices.Length - 1 do
46+
// printfn "(%i, %A)" indices.[i] values.[i]
47+
48+
0

src/GraphBLAS-sharp/Algorithms/BFS.fs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ module BFS =
1212
let mutable currentLevel = 1
1313
while currentLevel < vertexCount do
1414
let! frontierMask = Vector.mask frontier
15-
do! levels |> Vector.fillSubVector frontierMask (Scalar currentLevel)
15+
let! currentLevelScalar = Scalar.create currentLevel
16+
do! levels |> Vector.fillSubVector frontierMask currentLevelScalar
1617

1718
let! levelsComplemented = Vector.complemented levels
1819
let! frontier = (frontier, matrix) ||> Vector.vxmWithMask AnyAll.bool levelsComplemented

src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ module TriangleCounting =
1111

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

16-
return count
16+
do! Scalar.synchronize count
17+
18+
return! (Scalar.extractValue count)
1719
}

src/GraphBLAS-sharp/Backend/COOVector/Utilities/Merge.fs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,111 @@ module internal Merge =
117117

118118
return allIndices, allValues
119119
}
120+
121+
let mergeWithScalar (leftIndices: int[]) (leftValues: 'a[]) (rightIndices: int[]) (scalar: 'a) (mask: Mask1D option) : OpenCLEvaluation<int[] * 'a[]> = opencl {
122+
let workGroupSize = Utils.workGroupSize
123+
let firstSide = leftValues.Length
124+
let secondSide = rightIndices.Length
125+
let sumOfSides = firstSide + secondSide
126+
127+
let merge =
128+
<@
129+
fun (ndRange: _1D)
130+
(firstIndicesBuffer: int[])
131+
(firstValuesBuffer: 'a[])
132+
(secondIndicesBuffer: int[])
133+
(allIndicesBuffer: int[])
134+
(allValuesBuffer: 'a[]) ->
135+
136+
let i = ndRange.GlobalID0
137+
138+
let mutable beginIdxLocal = local ()
139+
let mutable endIdxLocal = local ()
140+
let localID = ndRange.LocalID0
141+
if localID < 2 then
142+
let mutable x = localID * (workGroupSize - 1) + i - 1
143+
if x >= sumOfSides then x <- sumOfSides - 1
144+
let diagonalNumber = x
145+
146+
let mutable leftEdge = diagonalNumber + 1 - secondSide
147+
if leftEdge < 0 then leftEdge <- 0
148+
149+
let mutable rightEdge = firstSide - 1
150+
if rightEdge > diagonalNumber then rightEdge <- diagonalNumber
151+
152+
while leftEdge <= rightEdge do
153+
let middleIdx = (leftEdge + rightEdge) / 2
154+
let firstIndex = firstIndicesBuffer.[middleIdx]
155+
let secondIndex = secondIndicesBuffer.[diagonalNumber - middleIdx]
156+
if firstIndex < secondIndex then leftEdge <- middleIdx + 1 else rightEdge <- middleIdx - 1
157+
158+
// Here localID equals either 0 or 1
159+
if localID = 0 then beginIdxLocal <- leftEdge else endIdxLocal <- leftEdge
160+
barrier ()
161+
162+
let beginIdx = beginIdxLocal
163+
let endIdx = endIdxLocal
164+
let firstLocalLength = endIdx - beginIdx
165+
let mutable x = workGroupSize - firstLocalLength
166+
if endIdx = firstSide then x <- secondSide - i + localID + beginIdx
167+
let secondLocalLength = x
168+
169+
//First indices are from 0 to firstLocalLength - 1 inclusive
170+
//Second indices are from firstLocalLength to firstLocalLength + secondLocalLength - 1 inclusive
171+
let localIndices = localArray<int> workGroupSize
172+
173+
if localID < firstLocalLength then
174+
localIndices.[localID] <- firstIndicesBuffer.[beginIdx + localID]
175+
if localID < secondLocalLength then
176+
localIndices.[firstLocalLength + localID] <- secondIndicesBuffer.[i - beginIdx]
177+
barrier ()
178+
179+
if i < sumOfSides then
180+
let mutable leftEdge = localID + 1 - secondLocalLength
181+
if leftEdge < 0 then leftEdge <- 0
182+
183+
let mutable rightEdge = firstLocalLength - 1
184+
if rightEdge > localID then rightEdge <- localID
185+
186+
while leftEdge <= rightEdge do
187+
let middleIdx = (leftEdge + rightEdge) / 2
188+
let firstIndex = localIndices.[middleIdx]
189+
let secondIndex = localIndices.[firstLocalLength + localID - middleIdx]
190+
if firstIndex < secondIndex then leftEdge <- middleIdx + 1 else rightEdge <- middleIdx - 1
191+
192+
let boundaryX = rightEdge
193+
let boundaryY = localID - leftEdge
194+
195+
// boundaryX and boundaryY can't be off the right edge of array (only off the left edge)
196+
let isValidX = boundaryX >= 0
197+
let isValidY = boundaryY >= 0
198+
199+
let mutable fstIdx = 0
200+
if isValidX then fstIdx <- localIndices.[boundaryX]
201+
202+
let mutable sndIdx = 0
203+
if isValidY then sndIdx <- localIndices.[firstLocalLength + boundaryY]
204+
205+
if not isValidX || isValidY && fstIdx < sndIdx then
206+
allIndicesBuffer.[i] <- sndIdx
207+
allValuesBuffer.[i] <- scalar
208+
else
209+
allIndicesBuffer.[i] <- fstIdx
210+
allValuesBuffer.[i] <- firstValuesBuffer.[beginIdx + boundaryX]
211+
@>
212+
213+
let allIndices = Array.zeroCreate sumOfSides
214+
let allValues = Array.create sumOfSides Unchecked.defaultof<'a>
215+
216+
do! RunCommand merge <| fun kernelPrepare ->
217+
let ndRange = _1D(Utils.workSize sumOfSides, workGroupSize)
218+
kernelPrepare
219+
ndRange
220+
leftIndices
221+
leftValues
222+
rightIndices
223+
allIndices
224+
allValues
225+
226+
return allIndices, allValues
227+
}

src/GraphBLAS-sharp/Backend/Common/PrefixSum.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module internal rec PrefixSum =
1212
let mutable verticesArrays = firstVertices, secondVertices
1313
let swap (a, b) = (b, a)
1414

15-
let mutable verticesLength = (inputArray.Length - 1) / workGroupSize + 1
15+
let mutable verticesLength = firstVertices.Length
1616
let mutable bunchLength = workGroupSize
1717

1818
do! scan inputArray inputArray.Length (fst verticesArrays) verticesLength totalSum
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
namespace GraphBLAS.FSharp.Backend.Common
2+
3+
open Brahma.OpenCL
4+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
5+
open Microsoft.FSharp.Quotations
6+
7+
module internal rec Sum =
8+
let run (inputArray: 'a[]) (plus: Expr<'a -> 'a -> 'a>) (zero: 'a) =
9+
if inputArray.Length = 0 then
10+
opencl { return [|zero|] }
11+
else
12+
runNotEmpty inputArray plus zero
13+
14+
let private runNotEmpty (inputArray: 'a[]) (plus: Expr<'a -> 'a -> 'a>) (zero: 'a) = opencl {
15+
let workGroupSize = Utils.workGroupSize
16+
17+
let firstVertices = Array.zeroCreate <| (inputArray.Length - 1) / workGroupSize + 1
18+
let secondVertices = Array.zeroCreate <| (firstVertices.Length - 1) / workGroupSize + 1
19+
let mutable verticesArrays = firstVertices, secondVertices
20+
let swap (a, b) = (b, a)
21+
22+
let mutable verticesLength = firstVertices.Length
23+
24+
do! scan inputArray inputArray.Length (fst verticesArrays) plus zero
25+
while verticesLength > workGroupSize do
26+
let fstVertices = fst verticesArrays
27+
let sndVertices = snd verticesArrays
28+
do! scan fstVertices verticesLength sndVertices plus zero
29+
30+
verticesArrays <- swap verticesArrays
31+
verticesLength <- (verticesLength - 1) / workGroupSize + 1
32+
33+
let result = Array.create 1 zero
34+
35+
let fstVertices = fst verticesArrays
36+
do! scan fstVertices verticesLength result plus zero
37+
38+
return result
39+
}
40+
41+
let private scan (inputArray: 'a[]) (inputArrayLength: int) (vertices: 'a[]) (plus: Expr<'a -> 'a -> 'a>) (zero: 'a) = opencl {
42+
let workGroupSize = Utils.workGroupSize
43+
44+
let scan =
45+
<@
46+
fun (ndRange: _1D)
47+
(resultBuffer: 'a[])
48+
(verticesBuffer: 'a[]) ->
49+
50+
let i = ndRange.GlobalID0
51+
let localID = ndRange.LocalID0
52+
53+
let resultLocalBuffer = localArray<'a> workGroupSize
54+
if i < inputArrayLength then resultLocalBuffer.[localID] <- resultBuffer.[i] else resultLocalBuffer.[localID] <- zero
55+
56+
let mutable step = 2
57+
while step <= workGroupSize do
58+
barrier ()
59+
if localID < workGroupSize / step then
60+
let i = step * (localID + 1) - 1
61+
resultLocalBuffer.[i] <- (%plus) resultLocalBuffer.[i] resultLocalBuffer.[i - (step >>> 1)]
62+
step <- step <<< 1
63+
barrier ()
64+
65+
if localID = workGroupSize - 1 then verticesBuffer.[i / workGroupSize] <- resultLocalBuffer.[localID]
66+
@>
67+
68+
do! RunCommand scan <| fun kernelPrepare ->
69+
let ndRange = _1D(Utils.workSize inputArrayLength, workGroupSize)
70+
kernelPrepare
71+
ndRange
72+
inputArray
73+
vertices
74+
}

src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
<?xml version="1.0" encoding="utf-8"?>
21
<Project Sdk="Microsoft.NET.Sdk">
32
<PropertyGroup>
43
<TargetFrameworks>netstandard2.1;net461</TargetFrameworks>
@@ -21,6 +20,7 @@
2120
<Compile Include="Backend/Common/Copy.fs" />
2221
<Compile Include="Backend/Common/PrefixSum.fs" />
2322
<Compile Include="Backend/Common/RemoveDuplicates.fs" />
23+
<Compile Include="Backend/Common/Sum.fs" />
2424
<Compile Include="Backend/CSRMatrix/Mxv.fs" />
2525
<Compile Include="Backend/COOMatrix/Utilities/Merge.fs" />
2626
<Compile Include="Backend/COOMatrix/Utilities/PreparePositions.fs" />
@@ -32,6 +32,7 @@
3232
<Compile Include="Backend/COOVector/Utilities/SetPositions.fs" />
3333
<Compile Include="Backend/COOVector/EWiseAdd.fs" />
3434
<Compile Include="IO/MtxReader.fs" />
35+
<Compile Include="Methods/Scalar.fs" />
3536
<Compile Include="Methods/Matrix.fs" />
3637
<Compile Include="Methods/Vector.fs" />
3738
<Compile Include="Predefined/Monoids/Any.fs" />
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
namespace GraphBLAS.FSharp
2+
3+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
4+
5+
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
6+
module Scalar =
7+
8+
(*
9+
constructors
10+
*)
11+
12+
let internal createFromArray (value: 'a[]) : GraphblasEvaluation<Scalar<'a>> = graphblas { return Scalar.FromArray(value) }
13+
14+
let create (value: 'a) : GraphblasEvaluation<Scalar<'a>> = createFromArray [|value|]
15+
16+
(*
17+
methods
18+
*)
19+
20+
let copy (scalar: Scalar<'a>) : GraphblasEvaluation<Scalar<'a>> = failwith "Not Implemented yet"
21+
22+
let synchronize (scalar: Scalar<'a>) : GraphblasEvaluation<unit> =
23+
opencl {
24+
let! _ = ToHost scalar.Value
25+
26+
return ()
27+
}
28+
|> EvalGB.fromCl
29+
30+
(*
31+
assignment and extraction
32+
*)
33+
34+
let extractValue (scalar: Scalar<'a>) : GraphblasEvaluation<'a> = graphblas { return scalar.Value.[0] }
35+
36+
let internal extractArray (scalar: Scalar<'a>) : GraphblasEvaluation<'a[]> = graphblas { return scalar.Value }
37+
38+
let assignValue (scalar: Scalar<'a>) (target: Scalar<'a>) : GraphblasEvaluation<unit> =
39+
failwith "Not Implemented yet"

0 commit comments

Comments
 (0)