Skip to content

Commit a1d3e19

Browse files
committed
Move matrix and vector operations
1 parent 6418bfd commit a1d3e19

8 files changed

Lines changed: 186 additions & 50 deletions

File tree

src/GraphBLAS-sharp/Algorithms/BFS.fs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
88

99
[<AutoOpen>]
1010
module BFS =
11-
let levelBFS (matrix: Matrix<bool>) (source: int) : OpenCLEvaluation<Vector<int>> =
12-
let vertexCount = matrix.RowCount
11+
let levelBFS (matrix: Matrix<bool>) (source: int) : GraphblasEvaluation<Vector<int>> =
12+
let vertexCount = Matrix.rowCount matrix
1313
let levels = Vector.ofArray <| Array.zeroCreate vertexCount <| (=) 0
1414
let frontier = Vector.ofTuples vertexCount [source, true]
1515

16-
opencl {
16+
graphblas {
1717
let mutable currentLevel = 1
1818
while currentLevel < vertexCount do
19-
let! frontierMask = frontier.GetMask()
20-
do! levels.Assign(frontierMask, Scalar currentLevel)
21-
let! levelsComplemented = levels.GetMask(isComplemented = true)
22-
let! frontier = frontier.Vxm matrix levelsComplemented AnyAll.bool
19+
let! frontierMask = Vector.mask frontier
20+
do! Vector.fillSubVector frontierMask (Scalar currentLevel) levels
21+
let! levelsComplemented = Vector.complemented levels
22+
let! frontier = Vector.vxm AnyAll.bool levelsComplemented frontier matrix
2323
currentLevel <- currentLevel + 1
2424

2525
return levels

src/GraphBLAS-sharp/Algorithms/SSSP.fs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
77

88
[<AutoOpen>]
99
module SSSP =
10-
let SSSP (matrix: Matrix<float>) (source: int) : OpenCLEvaluation<Vector<float>> =
11-
let vertexCount = matrix.RowCount
10+
let SSSP (matrix: Matrix<float>) (source: int) : GraphblasEvaluation<Vector<float>> =
11+
let vertexCount = Matrix.rowCount matrix
1212
let distance = Vector.ofTuples vertexCount [source, 0.]
1313

14-
opencl {
14+
graphblas {
1515
for _ in 1 .. vertexCount - 1 do
16-
let! step = distance.Vxm matrix None MinAdd.float
17-
do! distance.Assign(None, step)
16+
let! step = Vector.vxm MinAdd.float None distance matrix
17+
do! distance |> Vector.assignSubVector None step
1818

1919
return distance
2020
}

src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
77

88
[<AutoOpen>]
99
module TriangleCounting =
10-
// скорее всего, тут не скаляр возвращать нужно, а инт
11-
let sandiaTriangleCount (lowerTriangular: Matrix<bool>) : OpenCLEvaluation<Scalar<int>> =
10+
let sandiaTriangleCount (lowerTriangular: Matrix<bool>) : GraphblasEvaluation<int> =
1211
let bool2int = function
1312
| true -> 1
1413
| false -> 0
1514

16-
opencl {
17-
let! convertedMatrix = lowerTriangular.Apply None (UnaryOp <@ bool2int @>)
18-
let! convertedTransposed = convertedMatrix.Transpose()
19-
let! lowerTriangularMask = lowerTriangular.GetMask()
20-
let! result = convertedMatrix.Mxm convertedTransposed lowerTriangularMask AddMult.int
21-
return! result.Reduce Add.int
15+
graphblas {
16+
let! convertedMatrix = lowerTriangular |> Matrix.apply (UnaryOp <@ bool2int @>) None
17+
let! convertedTransposed = convertedMatrix |> Matrix.transpose
18+
let! lowerTriangularMask = lowerTriangular |> Matrix.mask
19+
let! result = Matrix.mxm AddMult.int lowerTriangularMask convertedMatrix convertedTransposed
20+
let! (Scalar count) = result |> Matrix.reduce Add.int
21+
return count
2222
}

src/GraphBLAS-sharp/GraphblasEvaluation.fs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,44 @@ module EvalGB =
2424
let x = run env reader
2525
run env (f x)
2626

27+
let ret x =
28+
EvalGB <| fun _ -> x
29+
2730
// EvalGB.liftCl x === liftM EvalGB x
2831
let liftCl clEvaluation =
2932
EvalGB <| fun env ->
30-
clEvaluation
31-
|> runCl env.ClContext
33+
runCl env.ClContext clEvaluation
34+
35+
let runWithClContext clContext (EvalGB action) =
36+
action { ClContext = clContext }
3237

3338
type GraphblasBuilder() =
34-
// monad
3539
member this.Bind(x, f) = EvalGB.bind f x
36-
member this.Return x = EvalGB <| fun _ -> x
40+
member this.Return x = EvalGB.ret x
3741
member this.ReturnFrom x = x
3842

43+
member this.Zero() =
44+
EvalGB.ret ()
45+
46+
member this.Combine(m1, m2) =
47+
EvalGB <| fun env ->
48+
EvalGB.run env m1
49+
EvalGB.run env m2
50+
51+
member this.Delay rest =
52+
EvalGB <| fun env ->
53+
EvalGB.run env <| rest ()
54+
55+
member this.While(predicate, body) =
56+
EvalGB <| fun env ->
57+
while predicate () do
58+
EvalGB.run env body
59+
60+
member this.For(sequence, f) =
61+
EvalGB <| fun env ->
62+
for elem in sequence do
63+
EvalGB.run env (f elem)
64+
3965
[<AutoOpen>]
4066
module GraphblasBuilder =
4167
let graphblas = GraphblasBuilder()

src/GraphBLAS-sharp/Methods/Matrix.fs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
44
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
55
open GraphBLAS.FSharp.Backend
66

7-
type MatrixTuples<'a when 'a : struct and 'a : equality> =
7+
type MatrixTuples<'a> =
88
{
99
RowIndices: int[]
1010
ColumnIndices: int[]
@@ -46,11 +46,41 @@ module Matrix =
4646
methods
4747
*)
4848

49+
let rowCount (matrix: Matrix<'a>) : int = failwith "Not Implemented yet"
50+
let columnCount (matrix: Matrix<'a>) : int = failwith "Not Implemented yet"
51+
let clear (matrix: Matrix<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
52+
let copy (matrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'a>> = failwith "Not Implemented yet"
53+
let resize (rowCount: int) (columnCount: int) (matrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'a>> = failwith "Not Implemented yet"
54+
let nnz (matrix: Matrix<'a>) : GraphblasEvaluation<int> = failwith "Not Implemented yet"
55+
let tuples (matrix: Matrix<'a>) : GraphblasEvaluation<MatrixTuples<'a>> = failwith "Not Implemented yet"
56+
let mask (matrix: Matrix<'a>) : GraphblasEvaluation<Mask2D option> = failwith "Not Implemented yet"
57+
let complemented (matrix: Matrix<'a>) : GraphblasEvaluation<Mask2D option> = failwith "Not Implemented yet"
58+
// let finish \ eval \ toHost
59+
60+
(*
61+
assignment, extraction and filling
62+
*)
63+
64+
let extractSubMatrix (mask: Mask2D option) (matrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'a>> = failwith "Not Implemented yet"
65+
let extractSubRow (rowIdx: int) (mask: Mask2D option) (matrix: Matrix<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
66+
let extractSubCol (colIdx: int) (mask: Mask2D option) (matrix: Matrix<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
67+
let extractElement (rowIdx: int) (colIdx: int) (matrix: Matrix<'a>) : GraphblasEvaluation<Scalar<'a>> = failwith "Not Implemented yet"
68+
let assignSubMatrix (mask: Mask2D option) (source: Matrix<'a>) (target: Matrix<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
69+
let assignSubRow (rowIdx: int) (mask: Mask2D option) (source: Vector<'a>) (target: Matrix<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
70+
let assignSubCol (colIdx: int) (mask: Mask2D option) (source: Vector<'a>) (target: Matrix<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
71+
let assignElement (rowIdx: int) (colIdx: int) (source: Scalar<'a>) (target: Matrix<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
72+
let fillSubMatrix (mask: Mask2D option) (filler: Scalar<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
73+
let fillSubRow (rowIdx: int) (mask: Mask2D option) (filler: Scalar<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
74+
let fillSubCol (colIdx: int) (mask: Mask2D option) (filler: Scalar<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
75+
4976
(*
5077
operations
5178
*)
5279

53-
let eWiseAdd (leftMatrix: Matrix<'a>) (rightMatrix: Matrix<'a>) (mask: Mask2D option) (semiring: ISemiring<'a>) =
80+
let mxm (semiring: ISemiring<'a>) (mask: Mask2D option) (leftMatrix: Matrix<'a>) (rightMatrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'a>> = failwith "Not Implemented yet"
81+
let mxv (semiring: ISemiring<'a>) (mask: Mask1D option) (matrix: Matrix<'a>) (vector: Vector<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
82+
83+
let eWiseAdd (semiring: ISemiring<'a>) (mask: Mask2D option) (leftMatrix: Matrix<'a>) (rightMatrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'a>> =
5484
let operationResult =
5585
match leftMatrix, rightMatrix with
5686
| MatrixCOO left, MatrixCOO right ->
@@ -61,3 +91,12 @@ module Matrix =
6191
| _ -> failwith "Not Implemented"
6292

6393
graphblas { return! EvalGB.liftCl operationResult }
94+
95+
let eWiseMult (semiring: ISemiring<'a>) (mask: Mask2D option) (leftMatrix: Matrix<'a>) (rightMatrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'a>> = failwith "Not Implemented yet"
96+
let apply (mapper: UnaryOp<'a, 'b>) (mask: Mask2D option) (matrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'b>> = failwith "Not Implemented yet"
97+
let prune (predicate: UnaryOp<'a, bool>) (mask: Mask2D option) (matrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'a>> = failwith "Not Implemented yet"
98+
let reduceRows (monoid: IMonoid<'a>) (mask: Mask1D) (matrix: Matrix<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
99+
let reduceCols (monoid: IMonoid<'a>) (mask: Mask1D) (matrix: Matrix<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
100+
let reduce (monoid: IMonoid<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation<Scalar<'a>> = failwith "Not Implemented yet"
101+
let transpose (matrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'b>> = failwith "Not Implemented yet"
102+
let kronecker (semiring: ISemiring<'a>) (mask: Mask2D option) (leftMatrix: Matrix<'a>) (rightMatrix: Matrix<'a>) : GraphblasEvaluation<Matrix<'a>> = failwith "Not Implemented yet"

src/GraphBLAS-sharp/Methods/Vector.fs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,30 @@
11
namespace GraphBLAS.FSharp
22

3+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
4+
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
5+
open GraphBLAS.FSharp.Backend
6+
7+
type VectorTuples<'a> =
8+
{
9+
Indices: int[]
10+
Values: 'a[]
11+
}
12+
13+
member this.ToHost() =
14+
opencl {
15+
let! _ = ToHost this.Indices
16+
let! _ = ToHost this.Values
17+
18+
return this
19+
}
20+
321
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
422
module Vector =
23+
24+
(*
25+
constructors
26+
*)
27+
528
let build (size: int) (indices: int[]) (values: int[]) : Vector<'a> =
629
failwith "Not Implemented yet"
730

@@ -17,3 +40,40 @@ module Vector =
1740

1841
let zeroCreate (size: int) : Vector<'a> =
1942
failwith "Not Implemented yet"
43+
44+
45+
(*
46+
methods
47+
*)
48+
49+
let size (vector: Vector<'a>) : int = failwith "Not Implemented yet"
50+
let clear (vector: Vector<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
51+
let copy (vector: Vector<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
52+
let resize (size: int) (vector: Vector<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
53+
let nnz (vector: Vector<'a>) : GraphblasEvaluation<int> = failwith "Not Implemented yet"
54+
let tuples (vector: Vector<'a>) : GraphblasEvaluation<VectorTuples<'a>> = failwith "Not Implemented yet"
55+
let mask (vector: Vector<'a>) : GraphblasEvaluation<Mask1D option> = failwith "Not Implemented yet"
56+
let complemented (vector: Vector<'a>) : GraphblasEvaluation<Mask1D option> = failwith "Not Implemented yet"
57+
// let finish \ eval \ toHost
58+
59+
(*
60+
assignment, extraction and filling
61+
*)
62+
63+
// добавить функции, чтобы разделить поведение при наличии и отсутствии маски (assignSubVector и assignVector)
64+
let extractSubVector (mask: Mask1D option) (vector: Vector<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
65+
let extractElement (idx: int) (vector: Vector<'a>) : GraphblasEvaluation<Scalar<'a>> = failwith "Not Implemented yet"
66+
let assignSubVector (mask: Mask1D option) (source: Vector<'a>) (target: Vector<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
67+
let assignElement (idx: int) (source: Scalar<'a>) (target: Vector<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
68+
let fillSubVector (mask: Mask1D option) (filler: Scalar<'a>) (vector: Vector<'a>) : GraphblasEvaluation<unit> = failwith "Not Implemented yet"
69+
70+
(*
71+
operations
72+
*)
73+
74+
let vxm (semiring: ISemiring<'a>) (mask: Mask1D option) (vector: Vector<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
75+
let eWiseAdd (semiring: ISemiring<'a>) (mask: Mask1D option) (leftVector: Vector<'a>) (rightVector: Vector<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
76+
let eWiseMult (semiring: ISemiring<'a>) (mask: Mask2D option) (leftVector: Vector<'a>) (rightVector: Vector<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
77+
let apply (mapper: UnaryOp<'a, 'b>) (mask: Mask1D option) (vector: Vector<'a>) : GraphblasEvaluation<Vector<'b>> = failwith "Not Implemented yet"
78+
let prune (predicate: UnaryOp<'a, bool>) (mask: Mask1D option) (vector: Vector<'a>) : GraphblasEvaluation<Vector<'a>> = failwith "Not Implemented yet"
79+
let reduce (monoid: IMonoid<'a>) (vector: Vector<'a>) : GraphblasEvaluation<Scalar<'a>> = failwith "Not Implemented yet"

src/GraphBLAS-sharp/Objects/Matrix.fs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,23 @@ and COOMatrix<'a> =
2020
Columns: int[]
2121
Values: 'a[]
2222
}
23+
24+
static member FromTuples(rowCount: int, columnCount: int, rows: int[], columns: int[], values: 'a[]) =
25+
{
26+
RowCount = rowCount
27+
ColumnCount = columnCount
28+
Rows = rows
29+
Columns = columns
30+
Values = values
31+
}
32+
33+
static member FromArray2D(array: 'a[,], isZero: 'a -> bool) =
34+
let (rows, cols, vals) =
35+
array
36+
|> Seq.cast<'a>
37+
|> Seq.mapi (fun idx v -> (idx / Array2D.length2 array, idx % Array2D.length2 array, v))
38+
|> Seq.filter (fun (i, j, v) -> not <| isZero v)
39+
|> Array.ofSeq
40+
|> Array.unzip3
41+
42+
COOMatrix.FromTuples(Array2D.length1 array, Array2D.length2 array, rows, cols, vals)

tests/GraphBLAS-sharp.Tests/OperationsTests/EWiseAddTests.fs

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -89,22 +89,7 @@ type PairOfSparseMatricesOfEqualSize =
8989
]
9090
) |> Arb.fromGen
9191

92-
let createMatrix<'a when 'a : struct and 'a : equality> matrixFormat args =
93-
match matrixFormat with
94-
| CSR ->
95-
Activator.CreateInstanceGeneric<CSRMatrix<_>>(
96-
Array.singleton typeof<'a>, args
97-
)
98-
|> unbox<CSRMatrix<'a>>
99-
:> Matrix<'a>
100-
| COO ->
101-
Activator.CreateInstanceGeneric<COOMatrix<_>>(
102-
Array.singleton typeof<'a>, args
103-
)
104-
|> unbox<COOMatrix<'a>>
105-
:> Matrix<'a>
106-
107-
let logger = Log.create "Sample"
92+
let logger = Log.create "eWiseAddTests"
10893

10994
let checkCorrectnessGeneric<'a when 'a : struct and 'a : equality>
11095
(sum: 'a -> 'a -> 'a)
@@ -114,6 +99,11 @@ let checkCorrectnessGeneric<'a when 'a : struct and 'a : equality>
11499
(case: OperationCase)
115100
(matrixA: 'a[,], matrixB: 'a[,]) =
116101

102+
let createMatrixFromArray2D matrixFormat array isZero =
103+
match matrixFormat with
104+
| CSR -> failwith "Not implemented"
105+
| COO -> MatrixCOO <| COOMatrix.FromArray2D(array, isZero)
106+
117107
let eWiseAddNaive (matrixA: 'a[,]) (matrixB: 'a[,]) =
118108
let left = matrixA |> Seq.cast<'a>
119109
let right = matrixB |> Seq.cast<'a>
@@ -141,8 +131,8 @@ let checkCorrectnessGeneric<'a when 'a : struct and 'a : equality>
141131

142132
let eWiseAddGB (matrixA: 'a[,]) (matrixB: 'a[,]) =
143133
try
144-
let left = createMatrix<'a> case.MatrixCase [|matrixA; isZero|]
145-
let right = createMatrix<'a> case.MatrixCase [|matrixB; isZero|]
134+
let left = createMatrixFromArray2D case.MatrixCase matrixA isZero
135+
let right = createMatrixFromArray2D case.MatrixCase matrixB isZero
146136

147137
logger.debug (
148138
eventX "Left matrix is \n{matrix}"
@@ -154,12 +144,12 @@ let checkCorrectnessGeneric<'a when 'a : struct and 'a : equality>
154144
>> setField "matrix" right
155145
)
156146

157-
opencl {
158-
let! result = left.EWiseAdd right None semiring
159-
let! tuples = result.GetTuples()
160-
return! tuples.ToHost()
147+
graphblas {
148+
let! result = Matrix.eWiseAdd semiring None left right
149+
let! tuples = Matrix.tuples result
150+
return! EvalGB.liftCl <| tuples.ToHost()
161151
}
162-
|> oclContext.RunSync
152+
|> EvalGB.runWithClContext oclContext
163153

164154
finally
165155
oclContext.Provider.CloseAllBuffers()
@@ -196,8 +186,9 @@ let checkCorrectnessGeneric<'a when 'a : struct and 'a : equality>
196186
let config = {
197187
FsCheckConfig.defaultConfig with
198188
arbitrary = [typeof<PairOfSparseMatricesOfEqualSize>]
189+
maxTest = 50
199190
startSize = 0
200-
maxTest = 10
191+
endSize = 1_000_000
201192
}
202193

203194
// https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/language-specification/types#value-types

0 commit comments

Comments
 (0)