From d517fff65edb876969e691b365d413755f53068e Mon Sep 17 00:00:00 2001 From: Dmitriy Panfilyonok Date: Wed, 23 Dec 2020 01:29:08 +0300 Subject: [PATCH 1/4] Change assignment and extraction in interfaces --- src/GraphBLAS-sharp/Abstracts.fs | 58 +++++++++----- src/GraphBLAS-sharp/Algorithms/BFS.fs | 6 +- src/GraphBLAS-sharp/Algorithms/SSSP.fs | 2 +- src/GraphBLAS-sharp/Implementations.fs | 101 ++++++++++--------------- src/GraphBLAS-sharp/Matrix.fs | 15 +++- src/GraphBLAS-sharp/Vector.fs | 15 +++- 6 files changed, 109 insertions(+), 88 deletions(-) diff --git a/src/GraphBLAS-sharp/Abstracts.fs b/src/GraphBLAS-sharp/Abstracts.fs index 4dd52049..1aaa6c4b 100644 --- a/src/GraphBLAS-sharp/Abstracts.fs +++ b/src/GraphBLAS-sharp/Abstracts.fs @@ -1,5 +1,7 @@ namespace GraphBLAS.FSharp +open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation + [] type Matrix<'a when 'a : struct and 'a : equality>(nrow: int, ncol: int) = abstract RowCount: int @@ -7,26 +9,38 @@ type Matrix<'a when 'a : struct and 'a : equality>(nrow: int, ncol: int) = default this.RowCount = nrow default this.ColumnCount = ncol - abstract Mask: Mask2D option - abstract Complemented: Mask2D option - - abstract Item: Mask2D option -> Matrix<'a> with get, set - abstract Item: Mask1D option * int -> Vector<'a> with get, set - abstract Item: int * Mask1D option -> Vector<'a> with get, set - abstract Item: int * int -> Scalar<'a> with get, set - abstract Fill: Mask2D option -> Scalar<'a> with set - abstract Fill: Mask1D option * int -> Scalar<'a> with set - abstract Fill: int * Mask1D option -> Scalar<'a> with set + abstract Extract: Mask2D option -> Matrix<'a> + abstract Extract: (Mask1D option * int) -> Vector<'a> + abstract Extract: (int * Mask1D option) -> Vector<'a> + abstract Extract: (int * int) -> Scalar<'a> + // Размерности должны совпадать + abstract Assign: Mask2D option * Matrix<'a> -> unit + abstract Assign: (Mask1D option * int) * Vector<'a> -> unit + abstract Assign: (int * Mask1D option) * Vector<'a> -> unit + abstract Assign: (int * int) * Scalar<'a> -> unit + abstract Assign: Mask2D option * Scalar<'a> -> unit + abstract Assign: (Mask1D option * int) * Scalar<'a> -> unit + abstract Assign: (int * Mask1D option) * Scalar<'a> -> unit + // abstract Resize + // abstract Dup + // abstract Clear + // abstract NNZ + // abstract Tuples: OpenCLEvaluation<{| Rows: int[]; Columns: int[]; Values: 'a[] |}> abstract Mxm: Matrix<'a> -> Mask2D option -> Semiring<'a> -> Matrix<'a> abstract Mxv: Vector<'a> -> Mask1D option -> Semiring<'a> -> Vector<'a> abstract EWiseAdd: Matrix<'a> -> Mask2D option -> Monoid<'a> -> Matrix<'a> abstract EWiseMult: Matrix<'a> -> Mask2D option -> Monoid<'a> -> Matrix<'a> - abstract Apply: Mask1D option -> UnaryOp<'a, 'b> -> Matrix<'b> + abstract Apply: Mask2D option -> UnaryOp<'a, 'b> -> Matrix<'b> + abstract Prune: Mask2D option -> UnaryOp<'a, bool> -> Matrix<'a> abstract ReduceIn: Mask1D option -> Monoid<'a> -> Vector<'a> abstract ReduceOut: Mask1D option -> Monoid<'a> -> Vector<'a> abstract Reduce: Monoid<'a> -> Scalar<'a> abstract T: Matrix<'a> + // abstract Kronecker + + abstract Mask: Mask2D option + abstract Complemented: Mask2D option static member inline (+) (x: Matrix<'a>, y: Matrix<'a>) = x.EWiseAdd y static member inline (*) (x: Matrix<'a>, y: Matrix<'a>) = x.EWiseMult y @@ -37,22 +51,28 @@ and [] Vector<'a when 'a : struct and 'a : equality>(length: int) abstract Length: int default this.Length = length - abstract AsArray: 'a[] abstract Clear: unit -> unit - - abstract Mask: Mask1D option - abstract Complemented: Mask1D option - - abstract Item: Mask1D option -> Vector<'a> with get, set - abstract Item: int -> Scalar<'a> with get, set - abstract Fill: Mask1D option -> Scalar<'a> with set + abstract Extract: Mask1D option -> Vector<'a> + abstract Extract: int -> Scalar<'a> + abstract Assign: Mask1D option * Vector<'a> -> unit + abstract Assign: int * Scalar<'a> -> unit + abstract Assign: Mask1D option * Scalar<'a> -> unit + // abstract Dup + // abstract Resize + // abstrct Clear + // abstract NNZ + // abstract Tuples: {| Indices: int[]; Values: 'a[] |} abstract Vxm: Matrix<'a> -> Mask1D option -> Semiring<'a> -> Vector<'a> abstract EWiseAdd: Vector<'a> -> Mask1D option -> Monoid<'a> -> Vector<'a> abstract EWiseMult: Vector<'a> -> Mask1D option -> Monoid<'a> -> Vector<'a> abstract Apply: Mask1D option -> UnaryOp<'a, 'b> -> Vector<'b> + abstract Prune: Mask1D option -> UnaryOp<'a, bool> -> Vector<'a> abstract Reduce: Monoid<'a> -> Scalar<'a> + abstract Mask: Mask1D option + abstract Complemented: Mask1D option + static member inline (+) (x: Vector<'a>, y: Vector<'a>) = x.EWiseAdd y static member inline (*) (x: Vector<'a>, y: Vector<'a>) = x.EWiseMult y static member inline (@.) (x: Vector<'a>, y: Matrix<'a>) = x.Vxm y diff --git a/src/GraphBLAS-sharp/Algorithms/BFS.fs b/src/GraphBLAS-sharp/Algorithms/BFS.fs index 07ec3eb5..a3e7e5ac 100644 --- a/src/GraphBLAS-sharp/Algorithms/BFS.fs +++ b/src/GraphBLAS-sharp/Algorithms/BFS.fs @@ -11,12 +11,12 @@ module BFS = let levels = DenseVector(Array.zeroCreate vertexCount, IntegerMonoid.add) let frontier = SparseVector(vertexCount, [source, true]) - let mutable currentLevel = 1 + while !> (frontier.Reduce BooleanMonoid.any) && currentLevel < vertexCount do - levels.Fill(frontier.Mask) <- Scalar currentLevel + levels.Assign(frontier.Mask, Scalar currentLevel) frontier.Clear() - frontier.[levels.Complemented] <- (frontier @. matrix) levels.Complemented BooleanSemiring.anyAll + frontier.Assign(levels.Complemented, (frontier @. matrix) levels.Complemented BooleanSemiring.anyAll) currentLevel <- currentLevel + 1 upcast levels diff --git a/src/GraphBLAS-sharp/Algorithms/SSSP.fs b/src/GraphBLAS-sharp/Algorithms/SSSP.fs index 24a42148..4f249cf0 100644 --- a/src/GraphBLAS-sharp/Algorithms/SSSP.fs +++ b/src/GraphBLAS-sharp/Algorithms/SSSP.fs @@ -10,6 +10,6 @@ module SSSP = let distance = SparseVector(vertexCount, [source, 0.]) for _ in 1 .. vertexCount - 1 do - distance.[None] <- (distance @. matrix) None FloatSemiring.minAdd + distance.Assign(None, (distance @. matrix) None FloatSemiring.minAdd) upcast distance diff --git a/src/GraphBLAS-sharp/Implementations.fs b/src/GraphBLAS-sharp/Implementations.fs index 37e82fe7..bfa19eba 100644 --- a/src/GraphBLAS-sharp/Implementations.fs +++ b/src/GraphBLAS-sharp/Implementations.fs @@ -29,7 +29,7 @@ type CSRMatrix<'a when 'a : struct and 'a : equality>(csrTuples: CSRFormat<'a>) let rowCount = base.RowCount let columnCount = base.ColumnCount - let spMV (vector: Vector<'a>) (mask: Mask1D) (semiring: Semiring<'a>) : Vector<'a> = + let spMV (vector: DenseVector<'a>) (mask: Mask1D) (semiring: Semiring<'a>) : Vector<'a> = let csrMatrixRowCount = rowCount let csrMatrixColumnCount = columnCount let vectorLength = vector.Length @@ -67,7 +67,7 @@ type CSRMatrix<'a when 'a : struct and 'a : equality>(csrTuples: CSRFormat<'a>) csrTuples.Values csrTuples.Columns csrTuples.RowPointers - vector.AsArray + vector.Values let eval = opencl { do! RunCommand command binder @@ -76,81 +76,77 @@ type CSRMatrix<'a when 'a : struct and 'a : equality>(csrTuples: CSRFormat<'a>) upcast DenseVector(oclContext.RunSync eval, semiring.PlusMonoid) + new(rows: int[], columns: int[], values: 'a[]) = CSRMatrix(CSRFormat.CreateEmpty()) + member this.Values = csrTuples.Values member this.Columns = csrTuples.Columns member this.RowPointers = csrTuples.RowPointers - override this.Mask = failwith "Not implemented" - override this.Complemented = failwith "Not implemented" - - override this.Item - with get (mask: Mask2D option) : Matrix<'a> = failwith "Not Implemented" - and set (mask: Mask2D option) (value: Matrix<'a>) = failwith "Not Implemented" - override this.Item - with get (vectorMask: Mask1D option, colIdx: int) : Vector<'a> = failwith "Not Implemented" - and set (vectorMask: Mask1D option, colIdx: int) (value: Vector<'a>) = failwith "Not Implemented" - override this.Item - with get (rowIdx: int, vectorMask: Mask1D option) : Vector<'a> = failwith "Not Implemented" - and set (rowIdx: int, vectorMask: Mask1D option) (value: Vector<'a>) = failwith "Not Implemented" - override this.Item - with get (rowIdx: int, colIdx: int) : Scalar<'a> = failwith "Not Implemented" - and set (rowIdx: int, colIdx: int) (value: Scalar<'a>) = failwith "Not Implemented" - override this.Fill - with set (mask: Mask2D option) (value: Scalar<'a>) = failwith "Not Implemented" - override this.Fill - with set (vectorMask: Mask1D option, colIdx: int) (value: Scalar<'a>) = failwith "Not Implemented" - override this.Fill - with set (rowIdx: int, vectorMask: Mask1D option) (value: Scalar<'a>) = failwith "Not Implemented" + override this.Extract (mask: Mask2D option) : Matrix<'a> = failwith "Not Implemented" + override this.Extract (colMask: Mask1D option * int) : Vector<'a> = failwith "Not Implemented" + override this.Extract (rowMask: int * Mask1D option) : Vector<'a> = failwith "Not Implemented" + override this.Extract (idx: int * int) : Scalar<'a> = failwith "Not Implemented" + override this.Assign (mask: Mask2D option, value: Matrix<'a>) : unit = failwith "Not Implemented" + override this.Assign (colMask: Mask1D option * int, value: Vector<'a>) : unit = failwith "Not Implemented" + override this.Assign (rowMask: int * Mask1D option, value: Vector<'a>) : unit = failwith "Not Implemented" + override this.Assign (idx: int * int, value: Scalar<'a>) : unit = failwith "Not Implemented" + override this.Assign (mask: Mask2D option, value: Scalar<'a>) : unit = failwith "Not Implemented" + override this.Assign (colMask: Mask1D option * int, value: Scalar<'a>) : unit = failwith "Not Implemented" + override this.Assign (rowMask: int * Mask1D option, value: Scalar<'a>) : unit = failwith "Not Implemented" override this.Mxm a b c = failwith "Not Implemented" override this.Mxv a b c = failwith "Not Implemented" override this.EWiseAdd a b c = failwith "Not Implemented" override this.EWiseMult a b c = failwith "Not Implemented" override this.Apply a b = failwith "Not Implemented" + override this.Prune a b = failwith "Not Implemented" override this.ReduceIn a b = failwith "Not Implemented" override this.ReduceOut a b = failwith "Not Implemented" override this.Reduce a = failwith "Not Implemented" override this.T = failwith "Not Implemented" + override this.Mask = failwith "Not implemented" + override this.Complemented = failwith "Not implemented" + and SparseVector<'a when 'a : struct and 'a : equality>(size: int, listOfNonzeroes: (int * 'a) list) = inherit Vector<'a>(size) - member this.AsList: (int * 'a) list = listOfNonzeroes - - override this.AsArray = failwith "Not Implemented" override this.Clear() = failwith "Not Implemented" - - override this.Mask = failwith "Not implemented" - override this.Complemented = failwith "Not implemented" - - override this.Item - with get (mask: Mask1D option) : Vector<'a> = failwith "Not Implemented" - and set (mask: Mask1D option) (value: Vector<'a>) = failwith "Not Implemented" - override this.Item - with get (idx: int) : Scalar<'a> = failwith "Not Implemented" - and set (idx: int) (value: Scalar<'a>) = failwith "Not Implemented" - override this.Fill - with set (mask: Mask1D option) (value: Scalar<'a>) = failwith "Not Implemented" + override this.Extract (mask: Mask1D option) : Vector<'a> = failwith "Not Implemented" + override this.Extract (idx: int) : Scalar<'a> = failwith "Not Implemented" + override this.Assign(mask: Mask1D option, vector: Vector<'a>) : unit = failwith "Not Implemented" + override this.Assign(idx: int, Scalar (value: 'a)) : unit = failwith "Not Implemented" + override this.Assign(mask: Mask1D option, Scalar (value: 'a)) : unit = failwith "Not Implemented" override this.Vxm (matrix: Matrix<'a>) (mask: Mask1D option) (semiring: Semiring<'a>) : Vector<'a> = failwith "Not Implemented" override this.EWiseAdd a b c = failwith "Not Implemented" override this.EWiseMult a b c = failwith "Not Implemented" override this.Apply a b = failwith "Not Implemented" + override this.Prune a b = failwith "Not Implemented" override this.Reduce (monoid: Monoid<'a>) = failwith "Not Implemented" + override this.Mask = failwith "Not implemented" + override this.Complemented = failwith "Not implemented" + and DenseVector<'a when 'a : struct and 'a : equality>(vector: 'a[], monoid: Monoid<'a>) = inherit Vector<'a>(vector.Length) - // Not Implemented - new(monoid: Monoid<'a>) = DenseVector(Array.zeroCreate<'a> 0, monoid) - // Not Implemented - new(listOfIndices: int list, monoid: Monoid<'a>) = DenseVector(Array.zeroCreate<'a> 0, monoid) - member this.Monoid = monoid - member this.Values = vector + member this.Values: 'a[] = vector - override this.AsArray = failwith "Not Implemented" override this.Clear() = failwith "Not Implemented" + override this.Extract (mask: Mask1D option) : Vector<'a> = failwith "Not Implemented" + override this.Extract (idx: int) : Scalar<'a> = failwith "Not Implemented" + override this.Assign(mask: Mask1D option, vector: Vector<'a>) : unit = failwith "Not Implemented" + override this.Assign(idx: int, Scalar (value: 'a)) : unit = failwith "Not Implemented" + override this.Assign(mask: Mask1D option, Scalar (value: 'a)) : unit = failwith "Not Implemented" + + override this.Vxm a b c = failwith "Not Implemented" + override this.EWiseAdd a b c = failwith "Not Implemented" + override this.EWiseMult a b c = failwith "Not Implemented" + override this.Apply a b = failwith "Not Implemented" + override this.Prune a b = failwith "Not Implemented" + override this.Reduce (monoid: Monoid<'a>) = failwith "Not Implemented" override this.Mask = let indices = @@ -163,18 +159,3 @@ and DenseVector<'a when 'a : struct and 'a : equality>(vector: 'a[], monoid: Mon [| for i in 0 .. this.Length - 1 do if this.Values.[i] <> this.Monoid.Zero then yield i |] Some <| Mask1D(indices, this.Length, true) - - override this.Item - with get (mask: Mask1D option) : Vector<'a> = failwith "Not Implemented" - and set (mask: Mask1D option) (value: Vector<'a>) = failwith "Not Implemented" - override this.Item - with get (idx: int) : Scalar<'a> = failwith "Not Implemented" - and set (idx: int) (value: Scalar<'a>) = failwith "Not Implemented" - override this.Fill - with set (mask: Mask1D option) (value: Scalar<'a>) = failwith "Not Implemented" - - override this.Vxm a b c = failwith "Not Implemented" - override this.EWiseAdd a b c = failwith "Not Implemented" - override this.EWiseMult a b c = failwith "Not Implemented" - override this.Apply a b = failwith "Not Implemented" - override this.Reduce (monoid: Monoid<'a>) = failwith "Not Implemented" diff --git a/src/GraphBLAS-sharp/Matrix.fs b/src/GraphBLAS-sharp/Matrix.fs index a85848b8..dc2a29c9 100644 --- a/src/GraphBLAS-sharp/Matrix.fs +++ b/src/GraphBLAS-sharp/Matrix.fs @@ -1,14 +1,21 @@ namespace GraphBLAS.FSharp module MatrixBackend = - // можно убрать перегрузку и добавить возможность partitial application type Matrix<'a when 'a : struct and 'a : equality> with static member Build(denseMatrix: 'T[,], zero: 'T, matrixType: MatrixBackendFormat) : Matrix<'T> = failwith "Not Implemented" + + static member Build(rows: int[], columns: int[], values: 'T[], matrixType: MatrixBackendFormat) : Matrix<'T> = + match matrixType with + | CSR -> upcast CSRMatrix(rows, columns, values) + | _ -> failwith "Not Implemented" + static member Build(pathToMatrix: string, matrixType: MatrixBackendFormat) : Matrix<'T> = failwith "Not Implemented" + static member Build(rowCount: int, columnCount: int, initializer: int -> int -> 'T, matrixType: MatrixBackendFormat) : Matrix<'T> = failwith "Not Implemented" + static member ZeroCreate(rowCount: int, columnCount: int, matrixType: MatrixBackendFormat) : Matrix<'T> = failwith "Not Implemented" @@ -18,10 +25,16 @@ module MatrixExtensions = type Matrix<'a when 'a : struct and 'a : equality> with static member Build(denseMatrix: 'T[,], zero: 'T) : Matrix<'T> = Matrix.Build(denseMatrix, zero, matrixBackendFormat) + + static member Build(rows: int[], columns: int[], values: 'T[]) : Matrix<'T> = + Matrix.Build(rows, columns, values) + static member Build(pathToMatrix: string) : Matrix<'T> = Matrix.Build(pathToMatrix, matrixBackendFormat) + static member Build(rowCount: int, columnCount: int, initializer: int -> int -> 'T) : Matrix<'T> = Matrix.Build(rowCount, columnCount, initializer, matrixBackendFormat) + static member ZeroCreate(rowCount: int, columnCount: int) : Matrix<'T> = Matrix.ZeroCreate(rowCount, columnCount) diff --git a/src/GraphBLAS-sharp/Vector.fs b/src/GraphBLAS-sharp/Vector.fs index 7c35c247..b4e6a92b 100644 --- a/src/GraphBLAS-sharp/Vector.fs +++ b/src/GraphBLAS-sharp/Vector.fs @@ -5,17 +5,24 @@ module VectorExtensions = type Vector<'a when 'a : struct and 'a : equality> with static member Sparse(denseVector: 'T[], zero: 'T) : Vector<'T> = failwith "Not Implemented" + static member Sparse(length: int, initializer: int -> 'T) : Vector<'T> = + // upcast SparseVector(length, List.init) failwith "Not Implemented" + static member ZeroSparse(length: int) : Vector<'T> = - failwith "Not Implemented" + upcast SparseVector(length, List.empty) + static member Dense(denseVector: 'T[], monoid: Monoid<'T>) : Vector<'T> = - failwith "Not Implemented" + upcast DenseVector(denseVector, monoid) + static member Dense(length: int, initializer: int -> 'T, monoid: Monoid<'T>) : Vector<'T> = - failwith "Not Implemented" + upcast DenseVector(Array.init length initializer, monoid) + static member ZeroDense(length: int, monoid: Monoid<'T>) : Vector<'T> = - failwith "Not Implemented" + upcast DenseVector(Array.create length monoid.Zero, monoid) + [] module Vector = From 65f2d222a3e128b2ade82b5935355d47b611e4f0 Mon Sep 17 00:00:00 2001 From: Dmitriy Panfilyonok Date: Fri, 15 Jan 2021 17:27:11 +0300 Subject: [PATCH 2/4] Update interface with OpenCLEvaluation. Disable fody --- Directory.Build.props | 1 + src/GraphBLAS-sharp/Abstracts.fs | 152 +++++++++++------- src/GraphBLAS-sharp/Algorithms/BFS.fs | 64 ++++++-- src/GraphBLAS-sharp/FodyWeavers.xml | 3 - src/GraphBLAS-sharp/FodyWeavers.xsd | 26 --- src/GraphBLAS-sharp/Implementations.fs | 97 +++++------ src/GraphBLAS-sharp/Vector.fs | 3 + tests/GraphBLAS-sharp.Tests/FodyWeavers.xml | 3 - tests/GraphBLAS-sharp.Tests/FodyWeavers.xsd | 26 --- .../OperationsTests/VxmTests.fs | 5 +- 10 files changed, 205 insertions(+), 175 deletions(-) delete mode 100644 src/GraphBLAS-sharp/FodyWeavers.xml delete mode 100644 src/GraphBLAS-sharp/FodyWeavers.xsd delete mode 100644 tests/GraphBLAS-sharp.Tests/FodyWeavers.xml delete mode 100644 tests/GraphBLAS-sharp.Tests/FodyWeavers.xsd diff --git a/Directory.Build.props b/Directory.Build.props index 448bd2c6..dc1d21e5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,5 +9,6 @@ YaccConstructor https://github.com/YaccConstructor/GraphBLAS-sharp + true diff --git a/src/GraphBLAS-sharp/Abstracts.fs b/src/GraphBLAS-sharp/Abstracts.fs index 1aaa6c4b..426f7ba6 100644 --- a/src/GraphBLAS-sharp/Abstracts.fs +++ b/src/GraphBLAS-sharp/Abstracts.fs @@ -2,6 +2,41 @@ namespace GraphBLAS.FSharp open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation +(* + везде вместо того, чтобы возвращать unit, можно возвращать измененный объект, + но нужно подумать, насколько создание нового объекта лучше/хуже изменения существующего + копирование большмх матриц явно хуже и зачем, а вот Clear сделать не inplace мб имеет смысл + + везде методы, тк проперти не соответсвуют концепции отсутствия вычислений, + хотя выглядеть будет оч плохо + + можно все операции, в которых не меняется структура объекта, сделать inplace + (хотя, если операция затрагивает весь объект, то все равно читать и писать, + единственно, что памяти единовременно в 2 раза больше потребуется) + + теперь есть единственный метод GetMask (без GetComplemented) + тк это теперь не свойство, то требует аргумента, а значит можно передавать isComplemented + + методы Extract и Assign, которые возвращают/присваивают подграф, семантически отличаются от тех, что в C + здесь возвращаемый подграф (подматрица) всегда того же размера, что и изначальная матрица + (т.е в матрице смежности вершины графа не удалаются, а только ребра) + поэтому перед операцией нужно сравнивать размерности матрицы и маски, по которой мы получаем подграф + чтобы удалить еще и вершины, можно потом сделать resize + + у вектора размерность теперь называется size, а не length, потому что идейно вектор -- набор вершин + + в C API тоже size + + метод Prune можно переименовать в Select или Filter + + нужно выяснить, как Partitial Aplication методы интеропятся с C# + + возможно, стоит отказаться от перегрузок Extract и Assign, чтобы сделать их PA, + тем самым, избавившись от скобок при вызове + + можно все методы сделать как методы C# (без PA), а рядом положить модуль с PA функциями + это нужно, для более гибкого интерфейся и лучшего интеропа с C# +*) + [] type Matrix<'a when 'a : struct and 'a : equality>(nrow: int, ncol: int) = abstract RowCount: int @@ -9,74 +44,72 @@ type Matrix<'a when 'a : struct and 'a : equality>(nrow: int, ncol: int) = default this.RowCount = nrow default this.ColumnCount = ncol - abstract Extract: Mask2D option -> Matrix<'a> - abstract Extract: (Mask1D option * int) -> Vector<'a> - abstract Extract: (int * Mask1D option) -> Vector<'a> - abstract Extract: (int * int) -> Scalar<'a> - // Размерности должны совпадать - abstract Assign: Mask2D option * Matrix<'a> -> unit - abstract Assign: (Mask1D option * int) * Vector<'a> -> unit - abstract Assign: (int * Mask1D option) * Vector<'a> -> unit - abstract Assign: (int * int) * Scalar<'a> -> unit - abstract Assign: Mask2D option * Scalar<'a> -> unit - abstract Assign: (Mask1D option * int) * Scalar<'a> -> unit - abstract Assign: (int * Mask1D option) * Scalar<'a> -> unit - // abstract Resize - // abstract Dup - // abstract Clear - // abstract NNZ - // abstract Tuples: OpenCLEvaluation<{| Rows: int[]; Columns: int[]; Values: 'a[] |}> - - abstract Mxm: Matrix<'a> -> Mask2D option -> Semiring<'a> -> Matrix<'a> - abstract Mxv: Vector<'a> -> Mask1D option -> Semiring<'a> -> Vector<'a> - abstract EWiseAdd: Matrix<'a> -> Mask2D option -> Monoid<'a> -> Matrix<'a> - abstract EWiseMult: Matrix<'a> -> Mask2D option -> Monoid<'a> -> Matrix<'a> - abstract Apply: Mask2D option -> UnaryOp<'a, 'b> -> Matrix<'b> - abstract Prune: Mask2D option -> UnaryOp<'a, bool> -> Matrix<'a> - abstract ReduceIn: Mask1D option -> Monoid<'a> -> Vector<'a> - abstract ReduceOut: Mask1D option -> Monoid<'a> -> Vector<'a> - abstract Reduce: Monoid<'a> -> Scalar<'a> - abstract T: Matrix<'a> - // abstract Kronecker - - abstract Mask: Mask2D option - abstract Complemented: Mask2D option + abstract Clear: unit -> OpenCLEvaluation + abstract Copy: unit -> OpenCLEvaluation> + abstract Resize: int -> int -> OpenCLEvaluation> + abstract GetNNZ: unit -> OpenCLEvaluation + abstract GetTuples: unit -> OpenCLEvaluation<{| Rows: int[]; Columns: int[]; Values: 'a[] |}> + abstract GetMask: bool -> OpenCLEvaluation + + abstract Extract: Mask2D option -> OpenCLEvaluation> + abstract Extract: (Mask1D option * int) -> OpenCLEvaluation> + abstract Extract: (int * Mask1D option) -> OpenCLEvaluation> + abstract Extract: (int * int) -> OpenCLEvaluation> + abstract Assign: Mask2D option * Matrix<'a> -> OpenCLEvaluation + abstract Assign: (Mask1D option * int) * Vector<'a> -> OpenCLEvaluation + abstract Assign: (int * Mask1D option) * Vector<'a> -> OpenCLEvaluation + abstract Assign: (int * int) * Scalar<'a> -> OpenCLEvaluation + abstract Assign: Mask2D option * Scalar<'a> -> OpenCLEvaluation + abstract Assign: (Mask1D option * int) * Scalar<'a> -> OpenCLEvaluation + abstract Assign: (int * Mask1D option) * Scalar<'a> -> OpenCLEvaluation + + abstract Mxm: Matrix<'a> -> Mask2D option -> Semiring<'a> -> OpenCLEvaluation> + abstract Mxv: Vector<'a> -> Mask1D option -> Semiring<'a> -> OpenCLEvaluation> + abstract EWiseAdd: Matrix<'a> -> Mask2D option -> Semiring<'a> -> OpenCLEvaluation> + abstract EWiseMult: Matrix<'a> -> Mask2D option -> Semiring<'a> -> OpenCLEvaluation> + abstract Apply: Mask2D option -> UnaryOp<'a, 'b> -> OpenCLEvaluation> + abstract Prune: Mask2D option -> UnaryOp<'a, bool> -> OpenCLEvaluation> + abstract ReduceIn: Mask1D option -> Monoid<'a> -> OpenCLEvaluation> + abstract ReduceOut: Mask1D option -> Monoid<'a> -> OpenCLEvaluation> + abstract Reduce: Monoid<'a> -> OpenCLEvaluation> + abstract Transpose: unit -> OpenCLEvaluation> + abstract Kronecker: Matrix<'a> -> Mask2D option -> Semiring<'a> -> OpenCLEvaluation> static member inline (+) (x: Matrix<'a>, y: Matrix<'a>) = x.EWiseAdd y static member inline (*) (x: Matrix<'a>, y: Matrix<'a>) = x.EWiseMult y static member inline (@.) (x: Matrix<'a>, y: Matrix<'a>) = x.Mxm y static member inline (@.) (x: Matrix<'a>, y: Vector<'a>) = x.Mxv y -and [] Vector<'a when 'a : struct and 'a : equality>(length: int) = - abstract Length: int - default this.Length = length - - abstract Clear: unit -> unit - abstract Extract: Mask1D option -> Vector<'a> - abstract Extract: int -> Scalar<'a> - abstract Assign: Mask1D option * Vector<'a> -> unit - abstract Assign: int * Scalar<'a> -> unit - abstract Assign: Mask1D option * Scalar<'a> -> unit - // abstract Dup - // abstract Resize - // abstrct Clear - // abstract NNZ - // abstract Tuples: {| Indices: int[]; Values: 'a[] |} - - abstract Vxm: Matrix<'a> -> Mask1D option -> Semiring<'a> -> Vector<'a> - abstract EWiseAdd: Vector<'a> -> Mask1D option -> Monoid<'a> -> Vector<'a> - abstract EWiseMult: Vector<'a> -> Mask1D option -> Monoid<'a> -> Vector<'a> - abstract Apply: Mask1D option -> UnaryOp<'a, 'b> -> Vector<'b> - abstract Prune: Mask1D option -> UnaryOp<'a, bool> -> Vector<'a> - abstract Reduce: Monoid<'a> -> Scalar<'a> - - abstract Mask: Mask1D option - abstract Complemented: Mask1D option + +and [] Vector<'a when 'a : struct and 'a : equality>(size: int) = + abstract Size: int + default this.Size = size + + abstract Clear: unit -> OpenCLEvaluation + abstract Copy: unit -> OpenCLEvaluation> + abstract Resize: int -> OpenCLEvaluation> + abstract GetNNZ: unit -> OpenCLEvaluation + abstract GetTuples: unit -> OpenCLEvaluation<{| Indices: int[]; Values: 'a[] |}> + abstract GetMask: bool -> OpenCLEvaluation + + abstract Extract: Mask1D option -> OpenCLEvaluation> + abstract Extract: int -> OpenCLEvaluation> + abstract Assign: Mask1D option * Vector<'a> -> OpenCLEvaluation + abstract Assign: int * Scalar<'a> -> OpenCLEvaluation + abstract Assign: Mask1D option * Scalar<'a> -> OpenCLEvaluation + + abstract Vxm: Matrix<'a> -> Mask1D option -> Semiring<'a> -> OpenCLEvaluation> + abstract EWiseAdd: Vector<'a> -> Mask1D option -> Semiring<'a> -> OpenCLEvaluation> + abstract EWiseMult: Vector<'a> -> Mask1D option -> Semiring<'a> -> OpenCLEvaluation> + abstract Apply: Mask1D option -> UnaryOp<'a, 'b> -> OpenCLEvaluation> + abstract Prune: Mask1D option -> UnaryOp<'a, bool> -> OpenCLEvaluation> + abstract Reduce: Monoid<'a> -> OpenCLEvaluation> static member inline (+) (x: Vector<'a>, y: Vector<'a>) = x.EWiseAdd y static member inline (*) (x: Vector<'a>, y: Vector<'a>) = x.EWiseMult y static member inline (@.) (x: Vector<'a>, y: Matrix<'a>) = x.Vxm y + and Mask1D(indices: int[], length: int, isComplemented: bool) = member this.Indices = indices member this.Length = length @@ -85,9 +118,10 @@ and Mask1D(indices: int[], length: int, isComplemented: bool) = member this.Item with get (idx: int) : bool = this.Indices - |> Array.exists ((=) idx) + |> Array.contains idx |> (<>) this.IsComplemented + and Mask2D(indices: (int * int)[], rowCount: int, columnCount: int, isComplemented: bool) = member this.Rows = indices |> Array.unzip |> fst member this.Columns = indices |> Array.unzip |> snd @@ -99,5 +133,5 @@ and Mask2D(indices: (int * int)[], rowCount: int, columnCount: int, isComplement with get (rowIdx: int, colIdx: int) : bool = (this.Rows, this.Columns) ||> Array.zip - |> Array.exists ((=) (rowIdx, colIdx)) + |> Array.contains (rowIdx, colIdx) |> (<>) this.IsComplemented diff --git a/src/GraphBLAS-sharp/Algorithms/BFS.fs b/src/GraphBLAS-sharp/Algorithms/BFS.fs index a3e7e5ac..94d6afef 100644 --- a/src/GraphBLAS-sharp/Algorithms/BFS.fs +++ b/src/GraphBLAS-sharp/Algorithms/BFS.fs @@ -3,23 +3,69 @@ namespace GraphBLAS.FSharp.Algorithms open GraphBLAS.FSharp.Predefined open GraphBLAS.FSharp.Helpers open GraphBLAS.FSharp +open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic +open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation + +[] +module Ext = + type OpenCLEvaluationBuilder with + member this.While(guard, body) = + if not <| guard () + then this.Zero() + else this.Bind(body, fun () -> this.While(guard, body)) + + member this.Delay(f) = f () + + member this.Zero() = this.Return() + + member this.Combine(a, b) = this.Bind(a, fun () -> b) [] module BFS = - let levelBFS (matrix: Matrix) (source: int) : Vector = + let levelBFS (matrix: Matrix) (source: int) : OpenCLEvaluation> = let vertexCount = matrix.RowCount - let levels = DenseVector(Array.zeroCreate vertexCount, IntegerMonoid.add) + let levels = Vector.Dense(Array.zeroCreate vertexCount, IntegerMonoid.add) - let frontier = SparseVector(vertexCount, [source, true]) + let frontier = Vector.Sparse(vertexCount, [source, true]) let mutable currentLevel = 1 - while !> (frontier.Reduce BooleanMonoid.any) && currentLevel < vertexCount do - levels.Assign(frontier.Mask, Scalar currentLevel) - frontier.Clear() - frontier.Assign(levels.Complemented, (frontier @. matrix) levels.Complemented BooleanSemiring.anyAll) - currentLevel <- currentLevel + 1 + // let inline ($) (a: Mask1D option -> 'a) (b: Mask1D option) = a <| b + let inline (?<-) (a: Vector<'a>) (b: Mask1D option) (c: Scalar<'a>) = a.Assign(b, c) + let inline (<@@>) (a: Vector<'a>) (b: Mask1D option) (c: Scalar<'a>) = () + + + + // let frontier = (@.) frontier + + // let a = levels.AssignE <| frontier.Mask + // let a = levels $ frontier.Mask <| Scalar currentLevel + let a = levels ? frontier.Mask <- Scalar currentLevel + + + + + // opencl { + // while currentLevel < vertexCount do + // do! levels.Assign(frontier.Mask, Scalar currentLevel) + // // let! frontier = frontier @. matrix <|| (levels.Complemented, BooleanSemiring.anyAll) + // let! frontier = frontier @. matrix <| {| Mask = levels.Complemented; SR = BooleanSemiring.anyAll |} + // currentLevel <- currentLevel + 1 + // // let! a = frontier.Reduce BooleanMonoid.any + // // let s = !> a + // let a = levels.Assign $ frontier.Mask + + // return levels + // } + + // while !> (frontier.Reduce BooleanMonoid.any) && currentLevel < vertexCount do + // levels.Assign(frontier.Mask, Scalar currentLevel) + // frontier.Clear() + // frontier.Assign(levels.Complemented, (frontier @. matrix) levels.Complemented BooleanSemiring.anyAll) + // currentLevel <- currentLevel + 1 + + // upcast levels + - upcast levels // let parentBFS (matrix: Matrix) (source: int) : Vector = // let vertexCount = matrix.RowCount diff --git a/src/GraphBLAS-sharp/FodyWeavers.xml b/src/GraphBLAS-sharp/FodyWeavers.xml deleted file mode 100644 index 20aae2eb..00000000 --- a/src/GraphBLAS-sharp/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/GraphBLAS-sharp/FodyWeavers.xsd b/src/GraphBLAS-sharp/FodyWeavers.xsd deleted file mode 100644 index 686bf548..00000000 --- a/src/GraphBLAS-sharp/FodyWeavers.xsd +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. - - - - - A comma-separated list of error codes that can be safely ignored in assembly verification. - - - - - 'false' to turn off automatic generation of the XML Schema file. - - - - - \ No newline at end of file diff --git a/src/GraphBLAS-sharp/Implementations.fs b/src/GraphBLAS-sharp/Implementations.fs index bfa19eba..8deaaf98 100644 --- a/src/GraphBLAS-sharp/Implementations.fs +++ b/src/GraphBLAS-sharp/Implementations.fs @@ -29,10 +29,10 @@ type CSRMatrix<'a when 'a : struct and 'a : equality>(csrTuples: CSRFormat<'a>) let rowCount = base.RowCount let columnCount = base.ColumnCount - let spMV (vector: DenseVector<'a>) (mask: Mask1D) (semiring: Semiring<'a>) : Vector<'a> = + let spMV (vector: DenseVector<'a>) (mask: Mask1D) (semiring: Semiring<'a>) : OpenCLEvaluation> = let csrMatrixRowCount = rowCount let csrMatrixColumnCount = columnCount - let vectorLength = vector.Length + let vectorLength = vector.Size if csrMatrixColumnCount <> vectorLength then invalidArg "vector" @@ -69,30 +69,36 @@ type CSRMatrix<'a when 'a : struct and 'a : equality>(csrTuples: CSRFormat<'a>) csrTuples.RowPointers vector.Values - let eval = opencl { + opencl { do! RunCommand command binder - return! ToHost resultVector + return upcast DenseVector(resultVector, semiring.PlusMonoid) } - upcast DenseVector(oclContext.RunSync eval, semiring.PlusMonoid) - + // Not Implemented new(rows: int[], columns: int[], values: 'a[]) = CSRMatrix(CSRFormat.CreateEmpty()) member this.Values = csrTuples.Values member this.Columns = csrTuples.Columns member this.RowPointers = csrTuples.RowPointers - override this.Extract (mask: Mask2D option) : Matrix<'a> = failwith "Not Implemented" - override this.Extract (colMask: Mask1D option * int) : Vector<'a> = failwith "Not Implemented" - override this.Extract (rowMask: int * Mask1D option) : Vector<'a> = failwith "Not Implemented" - override this.Extract (idx: int * int) : Scalar<'a> = failwith "Not Implemented" - override this.Assign (mask: Mask2D option, value: Matrix<'a>) : unit = failwith "Not Implemented" - override this.Assign (colMask: Mask1D option * int, value: Vector<'a>) : unit = failwith "Not Implemented" - override this.Assign (rowMask: int * Mask1D option, value: Vector<'a>) : unit = failwith "Not Implemented" - override this.Assign (idx: int * int, value: Scalar<'a>) : unit = failwith "Not Implemented" - override this.Assign (mask: Mask2D option, value: Scalar<'a>) : unit = failwith "Not Implemented" - override this.Assign (colMask: Mask1D option * int, value: Scalar<'a>) : unit = failwith "Not Implemented" - override this.Assign (rowMask: int * Mask1D option, value: Scalar<'a>) : unit = failwith "Not Implemented" + override this.Clear () = failwith "Not Implemented" + override this.Copy () = failwith "Not Implemented" + override this.Resize a b = failwith "Not Implemented" + override this.GetNNZ () = failwith "Not Implemented" + override this.GetTuples () = failwith "Not Implemented" + override this.GetMask a = failwith "Not Implemented" + + override this.Extract (mask: Mask2D option) : OpenCLEvaluation> = failwith "Not Implemented" + override this.Extract (colMask: Mask1D option * int) : OpenCLEvaluation> = failwith "Not Implemented" + override this.Extract (rowMask: int * Mask1D option) : OpenCLEvaluation> = failwith "Not Implemented" + override this.Extract (idx: int * int) : OpenCLEvaluation> = failwith "Not Implemented" + override this.Assign (mask: Mask2D option, value: Matrix<'a>) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (colMask: Mask1D option * int, value: Vector<'a>) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (rowMask: int * Mask1D option, value: Vector<'a>) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (idx: int * int, value: Scalar<'a>) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (mask: Mask2D option, value: Scalar<'a>) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (colMask: Mask1D option * int, value: Scalar<'a>) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (rowMask: int * Mask1D option, value: Scalar<'a>) : OpenCLEvaluation = failwith "Not Implemented" override this.Mxm a b c = failwith "Not Implemented" override this.Mxv a b c = failwith "Not Implemented" @@ -103,30 +109,33 @@ type CSRMatrix<'a when 'a : struct and 'a : equality>(csrTuples: CSRFormat<'a>) override this.ReduceIn a b = failwith "Not Implemented" override this.ReduceOut a b = failwith "Not Implemented" override this.Reduce a = failwith "Not Implemented" - override this.T = failwith "Not Implemented" + override this.Transpose () = failwith "Not Implemented" + override this.Kronecker a b c = failwith "Not Implemented" - override this.Mask = failwith "Not implemented" - override this.Complemented = failwith "Not implemented" and SparseVector<'a when 'a : struct and 'a : equality>(size: int, listOfNonzeroes: (int * 'a) list) = inherit Vector<'a>(size) - override this.Clear() = failwith "Not Implemented" - override this.Extract (mask: Mask1D option) : Vector<'a> = failwith "Not Implemented" - override this.Extract (idx: int) : Scalar<'a> = failwith "Not Implemented" - override this.Assign(mask: Mask1D option, vector: Vector<'a>) : unit = failwith "Not Implemented" - override this.Assign(idx: int, Scalar (value: 'a)) : unit = failwith "Not Implemented" - override this.Assign(mask: Mask1D option, Scalar (value: 'a)) : unit = failwith "Not Implemented" + override this.Clear () = failwith "Not Implemented" + override this.Copy () = failwith "Not Implemented" + override this.Resize a = failwith "Not Implemented" + override this.GetNNZ () = failwith "Not Implemented" + override this.GetTuples () = failwith "Not Implemented" + override this.GetMask a = failwith "Not Implemented" + + override this.Extract (mask: Mask1D option) : OpenCLEvaluation> = failwith "Not Implemented" + override this.Extract (idx: int) : OpenCLEvaluation> = failwith "Not Implemented" + override this.Assign (mask: Mask1D option, vector: Vector<'a>) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (idx: int, Scalar (value: 'a)) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (mask: Mask1D option, Scalar (value: 'a)) : OpenCLEvaluation = failwith "Not Implemented" - override this.Vxm (matrix: Matrix<'a>) (mask: Mask1D option) (semiring: Semiring<'a>) : Vector<'a> = failwith "Not Implemented" + override this.Vxm (matrix: Matrix<'a>) (mask: Mask1D option) (semiring: Semiring<'a>) : OpenCLEvaluation> = failwith "Not Implemented" override this.EWiseAdd a b c = failwith "Not Implemented" override this.EWiseMult a b c = failwith "Not Implemented" override this.Apply a b = failwith "Not Implemented" override this.Prune a b = failwith "Not Implemented" override this.Reduce (monoid: Monoid<'a>) = failwith "Not Implemented" - override this.Mask = failwith "Not implemented" - override this.Complemented = failwith "Not implemented" and DenseVector<'a when 'a : struct and 'a : equality>(vector: 'a[], monoid: Monoid<'a>) = inherit Vector<'a>(vector.Length) @@ -134,12 +143,18 @@ and DenseVector<'a when 'a : struct and 'a : equality>(vector: 'a[], monoid: Mon member this.Monoid = monoid member this.Values: 'a[] = vector - override this.Clear() = failwith "Not Implemented" - override this.Extract (mask: Mask1D option) : Vector<'a> = failwith "Not Implemented" - override this.Extract (idx: int) : Scalar<'a> = failwith "Not Implemented" - override this.Assign(mask: Mask1D option, vector: Vector<'a>) : unit = failwith "Not Implemented" - override this.Assign(idx: int, Scalar (value: 'a)) : unit = failwith "Not Implemented" - override this.Assign(mask: Mask1D option, Scalar (value: 'a)) : unit = failwith "Not Implemented" + override this.Clear () = failwith "Not Implemented" + override this.Copy () = failwith "Not Implemented" + override this.Resize a = failwith "Not Implemented" + override this.GetNNZ () = failwith "Not Implemented" + override this.GetTuples () = failwith "Not Implemented" + override this.GetMask a = failwith "Not Implemented" + + override this.Extract (mask: Mask1D option) : OpenCLEvaluation> = failwith "Not Implemented" + override this.Extract (idx: int) : OpenCLEvaluation> = failwith "Not Implemented" + override this.Assign (mask: Mask1D option, vector: Vector<'a>) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (idx: int, Scalar (value: 'a)) : OpenCLEvaluation = failwith "Not Implemented" + override this.Assign (mask: Mask1D option, Scalar (value: 'a)) : OpenCLEvaluation = failwith "Not Implemented" override this.Vxm a b c = failwith "Not Implemented" override this.EWiseAdd a b c = failwith "Not Implemented" @@ -147,15 +162,3 @@ and DenseVector<'a when 'a : struct and 'a : equality>(vector: 'a[], monoid: Mon override this.Apply a b = failwith "Not Implemented" override this.Prune a b = failwith "Not Implemented" override this.Reduce (monoid: Monoid<'a>) = failwith "Not Implemented" - - override this.Mask = - let indices = - [| for i in 0 .. this.Length - 1 do - if this.Values.[i] <> this.Monoid.Zero then yield i |] - Some <| Mask1D(indices, this.Length, false) - - override this.Complemented = - let indices = - [| for i in 0 .. this.Length - 1 do - if this.Values.[i] <> this.Monoid.Zero then yield i |] - Some <| Mask1D(indices, this.Length, true) diff --git a/src/GraphBLAS-sharp/Vector.fs b/src/GraphBLAS-sharp/Vector.fs index b4e6a92b..ee458e42 100644 --- a/src/GraphBLAS-sharp/Vector.fs +++ b/src/GraphBLAS-sharp/Vector.fs @@ -6,6 +6,9 @@ module VectorExtensions = static member Sparse(denseVector: 'T[], zero: 'T) : Vector<'T> = failwith "Not Implemented" + static member Sparse(length: int, values: (int * 'T) list) : Vector<'T> = + failwith "Not Implemented" + static member Sparse(length: int, initializer: int -> 'T) : Vector<'T> = // upcast SparseVector(length, List.init) failwith "Not Implemented" diff --git a/tests/GraphBLAS-sharp.Tests/FodyWeavers.xml b/tests/GraphBLAS-sharp.Tests/FodyWeavers.xml deleted file mode 100644 index 20aae2eb..00000000 --- a/tests/GraphBLAS-sharp.Tests/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/tests/GraphBLAS-sharp.Tests/FodyWeavers.xsd b/tests/GraphBLAS-sharp.Tests/FodyWeavers.xsd deleted file mode 100644 index 686bf548..00000000 --- a/tests/GraphBLAS-sharp.Tests/FodyWeavers.xsd +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. - - - - - A comma-separated list of error codes that can be safely ignored in assembly verification. - - - - - 'false' to turn off automatic generation of the XML Schema file. - - - - - \ No newline at end of file diff --git a/tests/GraphBLAS-sharp.Tests/OperationsTests/VxmTests.fs b/tests/GraphBLAS-sharp.Tests/OperationsTests/VxmTests.fs index 04320660..973ea69a 100644 --- a/tests/GraphBLAS-sharp.Tests/OperationsTests/VxmTests.fs +++ b/tests/GraphBLAS-sharp.Tests/OperationsTests/VxmTests.fs @@ -4,6 +4,7 @@ open Expecto open FsCheck open GraphBLAS.FSharp open MathNet.Numerics +open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic type OperationCase = { VectorCase: VectorType @@ -106,14 +107,14 @@ module VxmTests = let emptyVector = zeroVectorConstructor vectorSize Expect.throwsT - (fun () -> (emptyVector @. emptyMatrix) mask stdSemiring |> ignore) + (fun () -> opencl { return! (emptyVector @. emptyMatrix) mask stdSemiring } |> ignore) (sprintf "1x%i @ %ix%i\n case:\n %A" vectorSize matrixRowCount matrixColumnCount case) testPropertyWithConfig config "Operation should have correct semantic" <| fun (denseMatrix: float[,]) (denseVector: float[]) -> let matrix = Matrix.Build(denseMatrix, 0., matrixBackend) let vector = vectorConstructor denseVector - let result = (vector @. matrix) mask stdSemiring + let result = opencl { return! (vector @. matrix) mask stdSemiring } let a = LinearAlgebra.DenseMatrix.ofArray2 denseMatrix let b = LinearAlgebra.DenseVector.ofArray denseVector let c = b * a From 29ef704fd8f4ef86400c9da88f037a9af8d64e30 Mon Sep 17 00:00:00 2001 From: Dmitriy Panfilyonok Date: Fri, 15 Jan 2021 19:18:27 +0300 Subject: [PATCH 3/4] Update usage according to the modified interface. Change masks --- paket.dependencies | 2 +- paket.lock | 50 +++++++-------- src/GraphBLAS-sharp/Abstracts.fs | 36 ++++------- src/GraphBLAS-sharp/Algorithms/BFS.fs | 64 ++++--------------- src/GraphBLAS-sharp/Algorithms/SSSP.fs | 15 +++-- .../Algorithms/TriangleCounting.fs | 16 +++-- src/GraphBLAS-sharp/Implementations.fs | 14 ++-- src/GraphBLAS-sharp/Vector.fs | 3 +- .../OperationsTests/VxmTests.fs | 15 ++++- 9 files changed, 95 insertions(+), 120 deletions(-) diff --git a/paket.dependencies b/paket.dependencies index 954dc961..e8631d36 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -18,7 +18,7 @@ nuget System.CodeDom 4.7.0 nuget FSharp.Quotations.Evaluator 2.1.0 nuget FSharpx.Collections 2.1.3 nuget FSharpx.Text.StructuredFormat 2.3.0 -nuget Brahma.FSharp.OpenCL.WorkflowBuilder +nuget Brahma.FSharp.OpenCL.WorkflowBuilder 2.0.0-alpha4 nuget BenchmarkDotNet nuget MathNet.Numerics.FSharp diff --git a/paket.lock b/paket.lock index 43e9500e..7b2b9dd4 100644 --- a/paket.lock +++ b/paket.lock @@ -22,34 +22,34 @@ NUGET System.Threading.Tasks.Extensions (>= 4.5.2) - restriction: >= netstandard2.0 System.ValueTuple (>= 4.5) - restriction: >= netstandard2.0 BenchmarkDotNet.Annotations (0.12.1) - restriction: >= netstandard2.0 - Brahma.FSharp (2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.Printer (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.Translator (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp (2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.Printer (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.Translator (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) FSharp.Core (>= 4.3.4) - restriction: || (>= net461) (>= netstandard2.1) FSharp.Quotations.Evaluator (>= 2.1) - restriction: || (>= net461) (>= netstandard2.1) - YC.Brahma (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - YC.Brahma.OpenCL (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - YC.OpenCL.NET (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.AST (2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) + YC.Brahma (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + YC.Brahma.OpenCL (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + YC.OpenCL.NET (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.AST (2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) FSharp.Core (>= 4.3.4) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.Extensions (2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.Extensions (2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) FSharp.Core (>= 4.3.4) - restriction: || (>= net461) (>= netstandard2.1) - YC.Brahma.OpenCL (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - YC.OpenCL.NET (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.Printer (2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.AST (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.Translator (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) + YC.Brahma.OpenCL (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + YC.OpenCL.NET (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.Printer (2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.AST (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.Translator (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) FSharp.Core (>= 4.3.4) - restriction: || (>= net461) (>= netstandard2.1) FSharpx.Collections (>= 2.1.3) - restriction: || (>= net461) (>= netstandard2.1) FSharpx.Text.StructuredFormat (>= 2.3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.Translator (2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.AST (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.Extensions (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.Translator (2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.AST (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.Extensions (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) FSharp.Core (>= 4.3.4) - restriction: || (>= net461) (>= netstandard2.1) FSharpx.Collections (>= 2.1.3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.WorkflowBuilder (2.0.0-alpha3) - Brahma.FSharp (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - Brahma.FSharp.OpenCL.Extensions (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.WorkflowBuilder (2.0.0-alpha4) + Brahma.FSharp (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + Brahma.FSharp.OpenCL.Extensions (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) FSharp.Core (>= 4.3.4) - restriction: || (>= net461) (>= netstandard2.1) Chessie (0.6) - restriction: >= netcoreapp1.0 FSharp.Core (>= 4.0.1.7-alpha) - restriction: >= netstandard1.6 @@ -521,7 +521,6 @@ NUGET System.Runtime.InteropServices (>= 4.3) - restriction: && (< monoandroid) (< monotouch) (< net45) (>= netstandard1.1) (< netstandard2.0) (< win8) (< wpa81) (< xamarintvos) (< xamarinwatchos) System.Net.Http (4.3.4) - restriction: || (&& (< net45) (>= net46) (< netstandard1.4) (>= netstandard1.6)) (&& (< net45) (< netstandard1.2) (>= netstandard1.6) (< win8)) (&& (< net45) (< netstandard1.3) (>= netstandard1.6) (< win8) (< wpa81)) (&& (< net45) (< netstandard1.4) (>= netstandard1.6) (< win8) (< wpa81)) (&& (< net45) (< netstandard1.5) (>= netstandard1.6) (< win8) (< wpa81)) (&& (< net45) (>= netstandard1.6) (< netstandard2.0) (< win8) (< wpa81)) (&& (>= netcoreapp5.0) (< netstandard2.0)) (&& (< netstandard1.5) (>= netstandard1.6) (>= uap10.0)) Microsoft.NETCore.Platforms (>= 1.1.1) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.6) (< win8) (< wpa81)) (>= netcoreapp5.0) - Microsoft.Win32.Primitives (>= 4.3) - restriction: && (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.6) (< win8) (< wpa81) runtime.native.System (>= 4.3) - restriction: && (< monoandroid) (< monotouch) (< net45) (< netcoreapp5.0) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos) runtime.native.System.Net.Http (>= 4.3) - restriction: && (< monoandroid) (< monotouch) (< net45) (< netcoreapp5.0) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos) runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2) - restriction: && (< monoandroid) (< monotouch) (< net45) (< netcoreapp5.0) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos) @@ -532,7 +531,6 @@ NUGET System.Globalization (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.6) (< win8) (< wpa81)) (>= netcoreapp5.0) System.Globalization.Extensions (>= 4.3) - restriction: && (< monoandroid) (< monotouch) (< net45) (< netcoreapp5.0) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos) System.IO (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net45) (>= netstandard1.1) (< netstandard1.3) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.6) (< win8) (< wpa81)) (>= netcoreapp5.0) - System.IO.Compression (>= 4.3) - restriction: && (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.6) (< win8) (< wpa81) System.IO.FileSystem (>= 4.3) - restriction: && (< monoandroid) (< monotouch) (< net45) (< netcoreapp5.0) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos) System.Net.Primitives (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net45) (>= netstandard1.1) (< netstandard1.3) (< win8) (< wpa81)) (&& (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.6) (< win8) (< wpa81)) (>= netcoreapp5.0) System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.6) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.6) (< win8) (< wpa81)) (>= netcoreapp5.0) @@ -921,11 +919,11 @@ NUGET System.Threading (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.3) (< win8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (>= netcoreapp5.0) System.Xml.ReaderWriter (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.3) (< win8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net45) (>= netstandard1.0) (< netstandard1.3) (< win8) (< wp8) (< wpa81)) (>= netcoreapp5.0) System.Xml.XmlDocument (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.3) (< win8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (>= netcoreapp5.0) - YC.Brahma (2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - YC.Brahma.OpenCL (2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - YC.Brahma (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - YC.OpenCL.NET (>= 2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) - YC.OpenCL.NET (2.0.0-alpha3) - restriction: || (>= net461) (>= netstandard2.1) + YC.Brahma (2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + YC.Brahma.OpenCL (2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + YC.Brahma (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + YC.OpenCL.NET (>= 2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) + YC.OpenCL.NET (2.0.0-alpha4) - restriction: || (>= net461) (>= netstandard2.1) ExtraConstraints.Fody (>= 1.14) - restriction: >= netstandard2.0 Microsoft.Build.Framework (>= 16.6) - restriction: >= netstandard2.0 System.CodeDom (>= 4.7) - restriction: >= netstandard2.0 diff --git a/src/GraphBLAS-sharp/Abstracts.fs b/src/GraphBLAS-sharp/Abstracts.fs index 426f7ba6..5e1d9f0b 100644 --- a/src/GraphBLAS-sharp/Abstracts.fs +++ b/src/GraphBLAS-sharp/Abstracts.fs @@ -28,13 +28,16 @@ open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation метод Prune можно переименовать в Select или Filter - нужно выяснить, как Partitial Aplication методы интеропятся с C# + нужно выяснить, как curried методы интеропятся с C# - возможно, стоит отказаться от перегрузок Extract и Assign, чтобы сделать их PA, + возможно, стоит отказаться от перегрузок Extract и Assign, чтобы сделать их curried, тем самым, избавившись от скобок при вызове - можно все методы сделать как методы C# (без PA), а рядом положить модуль с PA функциями + можно все методы сделать как методы C# (без curried), а рядом положить модуль с curried функциями это нужно, для более гибкого интерфейся и лучшего интеропа с C# + + пара массивов лучше ложиться на opencl чем массив пар. Поэтому изменились аргументы Mask1D + стоит это учесть и в дугих местах. Например разреженный вектор должен принимать пару массивов вместо массива пар *) [] @@ -49,7 +52,7 @@ type Matrix<'a when 'a : struct and 'a : equality>(nrow: int, ncol: int) = abstract Resize: int -> int -> OpenCLEvaluation> abstract GetNNZ: unit -> OpenCLEvaluation abstract GetTuples: unit -> OpenCLEvaluation<{| Rows: int[]; Columns: int[]; Values: 'a[] |}> - abstract GetMask: bool -> OpenCLEvaluation + abstract GetMask: ?isComplemented: bool -> OpenCLEvaluation abstract Extract: Mask2D option -> OpenCLEvaluation> abstract Extract: (Mask1D option * int) -> OpenCLEvaluation> @@ -90,7 +93,7 @@ and [] Vector<'a when 'a : struct and 'a : equality>(size: int) = abstract Resize: int -> OpenCLEvaluation> abstract GetNNZ: unit -> OpenCLEvaluation abstract GetTuples: unit -> OpenCLEvaluation<{| Indices: int[]; Values: 'a[] |}> - abstract GetMask: bool -> OpenCLEvaluation + abstract GetMask: ?isComplemented: bool -> OpenCLEvaluation abstract Extract: Mask1D option -> OpenCLEvaluation> abstract Extract: int -> OpenCLEvaluation> @@ -110,28 +113,15 @@ and [] Vector<'a when 'a : struct and 'a : equality>(size: int) = static member inline (@.) (x: Vector<'a>, y: Matrix<'a>) = x.Vxm y -and Mask1D(indices: int[], length: int, isComplemented: bool) = +and Mask1D(indices: int[], size: int, isComplemented: bool) = member this.Indices = indices - member this.Length = length + member this.Size = size member this.IsComplemented = isComplemented - member this.Item - with get (idx: int) : bool = - this.Indices - |> Array.contains idx - |> (<>) this.IsComplemented - -and Mask2D(indices: (int * int)[], rowCount: int, columnCount: int, isComplemented: bool) = - member this.Rows = indices |> Array.unzip |> fst - member this.Columns = indices |> Array.unzip |> snd +and Mask2D(rowIndices: int[], columnIndices: int[], rowCount: int, columnCount: int, isComplemented: bool) = + member this.RowIndices = rowIndices + member this.ColumnIndices = columnIndices member this.RowCount = rowCount member this.ColumnCount = columnCount member this.IsComplemented = isComplemented - - member this.Item - with get (rowIdx: int, colIdx: int) : bool = - (this.Rows, this.Columns) - ||> Array.zip - |> Array.contains (rowIdx, colIdx) - |> (<>) this.IsComplemented diff --git a/src/GraphBLAS-sharp/Algorithms/BFS.fs b/src/GraphBLAS-sharp/Algorithms/BFS.fs index 94d6afef..09c5b705 100644 --- a/src/GraphBLAS-sharp/Algorithms/BFS.fs +++ b/src/GraphBLAS-sharp/Algorithms/BFS.fs @@ -6,66 +6,24 @@ open GraphBLAS.FSharp open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation -[] -module Ext = - type OpenCLEvaluationBuilder with - member this.While(guard, body) = - if not <| guard () - then this.Zero() - else this.Bind(body, fun () -> this.While(guard, body)) - - member this.Delay(f) = f () - - member this.Zero() = this.Return() - - member this.Combine(a, b) = this.Bind(a, fun () -> b) - [] module BFS = let levelBFS (matrix: Matrix) (source: int) : OpenCLEvaluation> = let vertexCount = matrix.RowCount let levels = Vector.Dense(Array.zeroCreate vertexCount, IntegerMonoid.add) - let frontier = Vector.Sparse(vertexCount, [source, true]) - let mutable currentLevel = 1 - - // let inline ($) (a: Mask1D option -> 'a) (b: Mask1D option) = a <| b - let inline (?<-) (a: Vector<'a>) (b: Mask1D option) (c: Scalar<'a>) = a.Assign(b, c) - let inline (<@@>) (a: Vector<'a>) (b: Mask1D option) (c: Scalar<'a>) = () - - - - // let frontier = (@.) frontier - - // let a = levels.AssignE <| frontier.Mask - // let a = levels $ frontier.Mask <| Scalar currentLevel - let a = levels ? frontier.Mask <- Scalar currentLevel - - - - - // opencl { - // while currentLevel < vertexCount do - // do! levels.Assign(frontier.Mask, Scalar currentLevel) - // // let! frontier = frontier @. matrix <|| (levels.Complemented, BooleanSemiring.anyAll) - // let! frontier = frontier @. matrix <| {| Mask = levels.Complemented; SR = BooleanSemiring.anyAll |} - // currentLevel <- currentLevel + 1 - // // let! a = frontier.Reduce BooleanMonoid.any - // // let s = !> a - // let a = levels.Assign $ frontier.Mask - - // return levels - // } - - // while !> (frontier.Reduce BooleanMonoid.any) && currentLevel < vertexCount do - // levels.Assign(frontier.Mask, Scalar currentLevel) - // frontier.Clear() - // frontier.Assign(levels.Complemented, (frontier @. matrix) levels.Complemented BooleanSemiring.anyAll) - // currentLevel <- currentLevel + 1 - - // upcast levels - + opencl { + let mutable currentLevel = 1 + while currentLevel < vertexCount do + let! frontierMask = frontier.GetMask() + do! levels.Assign(frontierMask, Scalar currentLevel) + let! levelsComplemented = levels.GetMask(isComplemented = true) + let! frontier = (frontier @. matrix) levelsComplemented BooleanSemiring.anyAll + currentLevel <- currentLevel + 1 + + return levels + } // let parentBFS (matrix: Matrix) (source: int) : Vector = // let vertexCount = matrix.RowCount diff --git a/src/GraphBLAS-sharp/Algorithms/SSSP.fs b/src/GraphBLAS-sharp/Algorithms/SSSP.fs index 4f249cf0..ec053e95 100644 --- a/src/GraphBLAS-sharp/Algorithms/SSSP.fs +++ b/src/GraphBLAS-sharp/Algorithms/SSSP.fs @@ -2,14 +2,19 @@ namespace GraphBLAS.FSharp.Algorithms open GraphBLAS.FSharp.Predefined open GraphBLAS.FSharp +open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic +open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation [] module SSSP = - let SSSP (matrix: Matrix) (source: int) : Vector = + let SSSP (matrix: Matrix) (source: int) : OpenCLEvaluation> = let vertexCount = matrix.RowCount - let distance = SparseVector(vertexCount, [source, 0.]) + let distance = Vector.Sparse(vertexCount, [source, 0.]) - for _ in 1 .. vertexCount - 1 do - distance.Assign(None, (distance @. matrix) None FloatSemiring.minAdd) + opencl { + for _ in 1 .. vertexCount - 1 do + let! step = (distance @. matrix) None FloatSemiring.minAdd + do! distance.Assign(None, step) - upcast distance + return distance + } diff --git a/src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs b/src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs index d1596751..b169a906 100644 --- a/src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs +++ b/src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs @@ -2,13 +2,21 @@ namespace GraphBLAS.FSharp.Algorithms open GraphBLAS.FSharp.Predefined open GraphBLAS.FSharp +open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic +open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation [] module TriangleCounting = - let sandiaTriangleCount (lowerTriangular: Matrix) = + // скорее всего, тут не скаляр возвращать нужно, а инт + let sandiaTriangleCount (lowerTriangular: Matrix) : OpenCLEvaluation> = let bool2int = function | true -> 1 | false -> 0 - let convertedMatrix = lowerTriangular.Apply None (UnaryOp <@ bool2int @>) - let result = (convertedMatrix @. convertedMatrix.T) lowerTriangular.Mask IntegerSemiring.addMult - result.Reduce IntegerMonoid.add + + opencl { + let! convertedMatrix = lowerTriangular.Apply None (UnaryOp <@ bool2int @>) + let! convertedTransposed = convertedMatrix.Transpose() + let! lowerTriangularMask = lowerTriangular.GetMask() + let! result = (convertedMatrix @. convertedTransposed) lowerTriangularMask IntegerSemiring.addMult + return! result.Reduce IntegerMonoid.add + } diff --git a/src/GraphBLAS-sharp/Implementations.fs b/src/GraphBLAS-sharp/Implementations.fs index 8deaaf98..0eee848a 100644 --- a/src/GraphBLAS-sharp/Implementations.fs +++ b/src/GraphBLAS-sharp/Implementations.fs @@ -86,7 +86,9 @@ type CSRMatrix<'a when 'a : struct and 'a : equality>(csrTuples: CSRFormat<'a>) override this.Resize a b = failwith "Not Implemented" override this.GetNNZ () = failwith "Not Implemented" override this.GetTuples () = failwith "Not Implemented" - override this.GetMask a = failwith "Not Implemented" + override this.GetMask(?isComplemented: bool) = + let isComplemented = defaultArg isComplemented false + failwith "Not Implemented" override this.Extract (mask: Mask2D option) : OpenCLEvaluation> = failwith "Not Implemented" override this.Extract (colMask: Mask1D option * int) : OpenCLEvaluation> = failwith "Not Implemented" @@ -113,7 +115,7 @@ type CSRMatrix<'a when 'a : struct and 'a : equality>(csrTuples: CSRFormat<'a>) override this.Kronecker a b c = failwith "Not Implemented" -and SparseVector<'a when 'a : struct and 'a : equality>(size: int, listOfNonzeroes: (int * 'a) list) = +and SparseVector<'a when 'a : struct and 'a : equality>(size: int, indices: int[], values: 'a[]) = inherit Vector<'a>(size) override this.Clear () = failwith "Not Implemented" @@ -121,7 +123,9 @@ and SparseVector<'a when 'a : struct and 'a : equality>(size: int, listOfNonzero override this.Resize a = failwith "Not Implemented" override this.GetNNZ () = failwith "Not Implemented" override this.GetTuples () = failwith "Not Implemented" - override this.GetMask a = failwith "Not Implemented" + override this.GetMask(?isComplemented: bool) = + let isComplemented = defaultArg isComplemented false + failwith "Not Implemented" override this.Extract (mask: Mask1D option) : OpenCLEvaluation> = failwith "Not Implemented" override this.Extract (idx: int) : OpenCLEvaluation> = failwith "Not Implemented" @@ -148,7 +152,9 @@ and DenseVector<'a when 'a : struct and 'a : equality>(vector: 'a[], monoid: Mon override this.Resize a = failwith "Not Implemented" override this.GetNNZ () = failwith "Not Implemented" override this.GetTuples () = failwith "Not Implemented" - override this.GetMask a = failwith "Not Implemented" + override this.GetMask(?isComplemented: bool) = + let isComplemented = defaultArg isComplemented false + failwith "Not Implemented" override this.Extract (mask: Mask1D option) : OpenCLEvaluation> = failwith "Not Implemented" override this.Extract (idx: int) : OpenCLEvaluation> = failwith "Not Implemented" diff --git a/src/GraphBLAS-sharp/Vector.fs b/src/GraphBLAS-sharp/Vector.fs index ee458e42..d4157037 100644 --- a/src/GraphBLAS-sharp/Vector.fs +++ b/src/GraphBLAS-sharp/Vector.fs @@ -10,11 +10,10 @@ module VectorExtensions = failwith "Not Implemented" static member Sparse(length: int, initializer: int -> 'T) : Vector<'T> = - // upcast SparseVector(length, List.init) failwith "Not Implemented" static member ZeroSparse(length: int) : Vector<'T> = - upcast SparseVector(length, List.empty) + upcast SparseVector(length, Array.zeroCreate 0, Array.zeroCreate<'T> 0) static member Dense(denseVector: 'T[], monoid: Monoid<'T>) : Vector<'T> = diff --git a/tests/GraphBLAS-sharp.Tests/OperationsTests/VxmTests.fs b/tests/GraphBLAS-sharp.Tests/OperationsTests/VxmTests.fs index 973ea69a..a5bf6215 100644 --- a/tests/GraphBLAS-sharp.Tests/OperationsTests/VxmTests.fs +++ b/tests/GraphBLAS-sharp.Tests/OperationsTests/VxmTests.fs @@ -5,6 +5,7 @@ open FsCheck open GraphBLAS.FSharp open MathNet.Numerics open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic +open GlobalContext type OperationCase = { VectorCase: VectorType @@ -107,14 +108,24 @@ module VxmTests = let emptyVector = zeroVectorConstructor vectorSize Expect.throwsT - (fun () -> opencl { return! (emptyVector @. emptyMatrix) mask stdSemiring } |> ignore) + (fun () -> + opencl { + return! (emptyVector @. emptyMatrix) mask stdSemiring + } + |> oclContext.RunSync + |> ignore + ) (sprintf "1x%i @ %ix%i\n case:\n %A" vectorSize matrixRowCount matrixColumnCount case) testPropertyWithConfig config "Operation should have correct semantic" <| fun (denseMatrix: float[,]) (denseVector: float[]) -> let matrix = Matrix.Build(denseMatrix, 0., matrixBackend) let vector = vectorConstructor denseVector - let result = opencl { return! (vector @. matrix) mask stdSemiring } + let result = + opencl { + return! (vector @. matrix) mask stdSemiring + } + |> oclContext.RunSync let a = LinearAlgebra.DenseMatrix.ofArray2 denseMatrix let b = LinearAlgebra.DenseVector.ofArray denseVector let c = b * a From 53a910486699b4cb51da846843f01973b80da7fa Mon Sep 17 00:00:00 2001 From: Dmitriy Panfilyonok Date: Fri, 15 Jan 2021 19:32:20 +0300 Subject: [PATCH 4/4] Remove comments from Abstracts.fs --- src/GraphBLAS-sharp/Abstracts.fs | 38 -------------------------------- 1 file changed, 38 deletions(-) diff --git a/src/GraphBLAS-sharp/Abstracts.fs b/src/GraphBLAS-sharp/Abstracts.fs index 5e1d9f0b..bafa0d2f 100644 --- a/src/GraphBLAS-sharp/Abstracts.fs +++ b/src/GraphBLAS-sharp/Abstracts.fs @@ -2,44 +2,6 @@ namespace GraphBLAS.FSharp open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation -(* - везде вместо того, чтобы возвращать unit, можно возвращать измененный объект, - но нужно подумать, насколько создание нового объекта лучше/хуже изменения существующего - копирование большмх матриц явно хуже и зачем, а вот Clear сделать не inplace мб имеет смысл - - везде методы, тк проперти не соответсвуют концепции отсутствия вычислений, - хотя выглядеть будет оч плохо - - можно все операции, в которых не меняется структура объекта, сделать inplace - (хотя, если операция затрагивает весь объект, то все равно читать и писать, - единственно, что памяти единовременно в 2 раза больше потребуется) - - теперь есть единственный метод GetMask (без GetComplemented) - тк это теперь не свойство, то требует аргумента, а значит можно передавать isComplemented - - методы Extract и Assign, которые возвращают/присваивают подграф, семантически отличаются от тех, что в C - здесь возвращаемый подграф (подматрица) всегда того же размера, что и изначальная матрица - (т.е в матрице смежности вершины графа не удалаются, а только ребра) - поэтому перед операцией нужно сравнивать размерности матрицы и маски, по которой мы получаем подграф - чтобы удалить еще и вершины, можно потом сделать resize - - у вектора размерность теперь называется size, а не length, потому что идейно вектор -- набор вершин - + в C API тоже size - - метод Prune можно переименовать в Select или Filter - - нужно выяснить, как curried методы интеропятся с C# - - возможно, стоит отказаться от перегрузок Extract и Assign, чтобы сделать их curried, - тем самым, избавившись от скобок при вызове - - можно все методы сделать как методы C# (без curried), а рядом положить модуль с curried функциями - это нужно, для более гибкого интерфейся и лучшего интеропа с C# - - пара массивов лучше ложиться на opencl чем массив пар. Поэтому изменились аргументы Mask1D - стоит это учесть и в дугих местах. Например разреженный вектор должен принимать пару массивов вместо массива пар -*) - [] type Matrix<'a when 'a : struct and 'a : equality>(nrow: int, ncol: int) = abstract RowCount: int