From 7e0d0603773c02bbccb2fe9b1710bc75c79fb3b7 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Thu, 13 Apr 2023 14:43:03 +0300 Subject: [PATCH 01/44] add: ClArray.chunk* --- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 83 +++++++++++++++++++ .../GraphBLAS-sharp.Backend.fsproj | 1 + src/GraphBLAS-sharp.Backend/Matrix/Split.fs | 22 +++++ 3 files changed, 106 insertions(+) create mode 100644 src/GraphBLAS-sharp.Backend/Matrix/Split.fs diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index aace2a48..64da52d9 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -1,5 +1,6 @@ namespace GraphBLAS.FSharp.Backend.Common +open System.Collections.Generic open Brahma.FSharp open Microsoft.FSharp.Quotations open GraphBLAS.FSharp.Backend.Objects.ClContext @@ -329,3 +330,85 @@ module ClArray = scatter processor positions values result result + + let getChunk (clContext: ClContext) workGroupSize = + + let kernel = + <@ fun (ndRange: Range1D) startIndex endIndex (sourceArray: ClArray<'a>) (targetChunk: ClArray<'a>) -> + + let gid = ndRange.GlobalID0 + let sourcePosition = gid + startIndex + + if sourcePosition < endIndex then + + targetChunk.[gid] <- sourceArray.[sourcePosition] @> + + let kernel = clContext.Compile kernel + + fun (processor: MailboxProcessor<_>) allocationMode (sourceArray: ClArray<'a>) startIndex endIndex -> + if startIndex < 0 then failwith "" + if startIndex >= endIndex then failwith "" // empty array + if endIndex > sourceArray.Length then failwith "" // TODO() + + let resultLength = endIndex - startIndex + + let result = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + let ndRange = + Range1D.CreateValid(resultLength, workGroupSize) + + let kernel = kernel.GetKernel() + + processor.Post( + Msg.MsgSetArguments + (fun () -> kernel.KernelFunc ndRange startIndex endIndex sourceArray result) + ) + + processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + + result + + /// + /// Lazy divides the input array into chunks of size at most chunkSize. + /// + /// Cl context. + /// Work group size. + /// + /// Since calculations are performed lazily, the array should not change. + /// + let lazyChunkBySize (clContext: ClContext) workGroupSize = + + let getChunk = + getChunk clContext workGroupSize + + // TODO(immutable array) + fun (processor: MailboxProcessor<_>) allocationMode chunkSize (sourceArray: ClArray<'a>) -> + if chunkSize <= 0 then failwith "" + + let chunkCount = (sourceArray.Length - 1) / chunkSize + 1 + + let getChunk = getChunk processor allocationMode sourceArray + + seq { + for i in 0 .. chunkCount do + let startIndex = i * chunkSize + let endIndex = max (startIndex + chunkSize) sourceArray.Length + + yield lazy ( getChunk startIndex endIndex ) + } + + /// + /// Divides the input array into chunks of size at most chunkSize. + /// + /// Cl context. + /// Work group size. + let chunkBySize (clContext: ClContext) workGroupSize = + + let chunkBySizeLazy = + lazyChunkBySize clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode chunkSize (sourceArray: ClArray<'a>) -> + chunkBySizeLazy processor allocationMode chunkSize sourceArray + |> Seq.map (fun lazyValue -> lazyValue.Value) + |> Seq.toArray diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index b8ca8ba0..85db1a0b 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -36,6 +36,7 @@ + diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Split.fs b/src/GraphBLAS-sharp.Backend/Matrix/Split.fs new file mode 100644 index 00000000..43ea1197 --- /dev/null +++ b/src/GraphBLAS-sharp.Backend/Matrix/Split.fs @@ -0,0 +1,22 @@ +module GraphBLAS.FSharp.Backend.Matrix + +open Brahma.FSharp +open GraphBLAS.FSharp.Backend.Common +open GraphBLAS.FSharp.Backend.Matrix +open GraphBLAS.FSharp.Backend.Quotes +open Microsoft.FSharp.Quotations +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Objects.ClMatrix +open GraphBLAS.FSharp.Backend.Objects.ClContext + +module Split = + let toCOO (clContext: ClContext) workGroupSize = + + let copy = ClArray.copy clContext workGroupSize + + let copyData = ClArray.copy clContext workGroupSize + + // endIndex exclusive (for csr matrix row pointers interop), startIndex inclusive + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) startIndex endIndex -> + + () From babe90e18d66f1b4fb19e73bc06ba18ab1b13895 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Thu, 13 Apr 2023 22:52:31 +0300 Subject: [PATCH 02/44] add: Split --- src/GraphBLAS-sharp.Backend/Matrix/Split.fs | 73 ++++++++++++++++++--- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Split.fs b/src/GraphBLAS-sharp.Backend/Matrix/Split.fs index 43ea1197..33761660 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Split.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Split.fs @@ -2,21 +2,74 @@ module GraphBLAS.FSharp.Backend.Matrix open Brahma.FSharp open GraphBLAS.FSharp.Backend.Common -open GraphBLAS.FSharp.Backend.Matrix -open GraphBLAS.FSharp.Backend.Quotes -open Microsoft.FSharp.Quotations open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClMatrix -open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions + +// type lazy matrix ??? module Split = - let toCOO (clContext: ClContext) workGroupSize = + module ByChunk = + let runCOOLazy (clContext: ClContext) workGroupSize = + + let chunkBySizeValues = ClArray.lazyChunkBySize clContext workGroupSize + + let chunkBySizeIndices = ClArray.lazyChunkBySize clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode chunkSize (matrix: ClMatrix.COO<'a>) -> + + let createSubMatrixLazy (values: Lazy<_>) (columns: Lazy<_>) (rows: Lazy<_>) = + lazy + { Context = clContext + RowCount = matrix.RowCount + ColumnCount = matrix.ColumnCount + Rows = rows.Value + Columns = columns.Value + Values = values.Value } + + let values = chunkBySizeValues processor allocationMode chunkSize matrix.Values + let columns = chunkBySizeIndices processor allocationMode chunkSize matrix.Columns + let rows = chunkBySizeIndices processor allocationMode chunkSize matrix.Rows + + Seq.map3 createSubMatrixLazy values columns rows + + let runCOO (clContext: ClContext) workGroupSize = + + let run = runCOOLazy clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode chunkSize (matrix: ClMatrix.COO<'a>) -> + run processor allocationMode chunkSize matrix + |> Seq.map (fun lazyMatrix -> lazyMatrix.Value) + |> Seq.toArray + + module ByRow = + let runCSRLazy (clContext: ClContext) workGroupSize = + + let getChunkValues = ClArray.getChunk clContext workGroupSize + + let getChunkIndices = ClArray.getChunk clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> + + let getChunkValues = getChunkValues processor allocationMode matrix.Values + let getChunkIndices = getChunkIndices processor allocationMode matrix.Columns + + matrix.RowPointers.ToHost processor + |> Seq.pairwise + |> Seq.map (fun (first, second) -> + lazy + if second - first > 0 then + let values = getChunkValues first second + let columns = getChunkIndices first second - let copy = ClArray.copy clContext workGroupSize + Some (values, columns) + else None) - let copyData = ClArray.copy clContext workGroupSize + let runCSR (clContext: ClContext) workGroupSize = - // endIndex exclusive (for csr matrix row pointers interop), startIndex inclusive - fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) startIndex endIndex -> + let runLazy = runCSRLazy clContext workGroupSize - () + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> + runLazy processor allocationMode matrix + |> Seq.map (fun lazyValue -> lazyValue.Value) + |> Seq.toArray From b30a9f897755c312f6463921925e075d1b4c76e2 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 14 Apr 2023 00:33:36 +0300 Subject: [PATCH 03/44] add: ClArray.chunk* tests --- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 15 +- .../GraphBLAS-sharp.Backend.fsproj | 2 +- src/GraphBLAS-sharp.Backend/Matrix/Split.fs | 65 ++++++- .../Common/ClArray/chunkBySize.fs | 107 ++++++++++ tests/GraphBLAS-sharp.Tests/Generators.fs | 57 ++++++ .../GraphBLAS-sharp.Tests.fsproj | 2 + tests/GraphBLAS-sharp.Tests/Helpers.fs | 7 + tests/GraphBLAS-sharp.Tests/Matrix/Split.fs | 4 + tests/GraphBLAS-sharp.Tests/Program.fs | 182 +++++++++--------- 9 files changed, 339 insertions(+), 102 deletions(-) create mode 100644 tests/GraphBLAS-sharp.Tests/Common/ClArray/chunkBySize.fs create mode 100644 tests/GraphBLAS-sharp.Tests/Matrix/Split.fs diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 64da52d9..4804d690 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -346,9 +346,9 @@ module ClArray = let kernel = clContext.Compile kernel fun (processor: MailboxProcessor<_>) allocationMode (sourceArray: ClArray<'a>) startIndex endIndex -> - if startIndex < 0 then failwith "" - if startIndex >= endIndex then failwith "" // empty array - if endIndex > sourceArray.Length then failwith "" // TODO() + if startIndex < 0 then failwith "startIndex is less than zero" + if startIndex >= endIndex then failwith "startIndex is greater than or equal to the endIndex" + if endIndex > sourceArray.Length then failwith "endIndex is larger than the size of the array" let resultLength = endIndex - startIndex @@ -382,20 +382,19 @@ module ClArray = let getChunk = getChunk clContext workGroupSize - // TODO(immutable array) fun (processor: MailboxProcessor<_>) allocationMode chunkSize (sourceArray: ClArray<'a>) -> - if chunkSize <= 0 then failwith "" + if chunkSize <= 0 then failwith "The size of the piece cannot be less than 1" - let chunkCount = (sourceArray.Length - 1) / chunkSize + 1 + let chunkCount = (sourceArray.Length - 1) / chunkSize let getChunk = getChunk processor allocationMode sourceArray seq { for i in 0 .. chunkCount do let startIndex = i * chunkSize - let endIndex = max (startIndex + chunkSize) sourceArray.Length + let endIndex = min (startIndex + chunkSize) sourceArray.Length - yield lazy ( getChunk startIndex endIndex ) + yield lazy getChunk startIndex endIndex } /// diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index 85db1a0b..580d2a5a 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -36,7 +36,6 @@ - @@ -46,6 +45,7 @@ + diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Split.fs b/src/GraphBLAS-sharp.Backend/Matrix/Split.fs index 33761660..61fcefd7 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Split.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Split.fs @@ -1,10 +1,11 @@ -module GraphBLAS.FSharp.Backend.Matrix +namespace GraphBLAS.FSharp.Backend.Matrix open Brahma.FSharp open GraphBLAS.FSharp.Backend.Common open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClMatrix open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +open GraphBLAS.FSharp.Backend.Objects.ClVector // type lazy matrix ??? @@ -42,7 +43,21 @@ module Split = |> Seq.map (fun lazyMatrix -> lazyMatrix.Value) |> Seq.toArray + // let run (clContext: ClContext) workGroupSize = + // + // let run = runCOOLazy clContext workGroupSize + // + // let runCOO = runCOO clContext workGroupSize + // + // let COOToCSR = COO.Matrix.toCSR clCOntext workGroupSize + // + // fun (processor: MailboxProcessor<_>) allocationMode chunkSize (matrix: ClMatrix<'a>) -> + // match matrix with + // | ClMatrix.COO matrix -> runCOO processor allocationMode chunkSize matrix + // | ClMatrix.COO matrix -> + // () module ByRow = + // MB We can split CSR to chunks without COO representation let runCSRLazy (clContext: ClContext) workGroupSize = let getChunkValues = ClArray.getChunk clContext workGroupSize @@ -54,6 +69,12 @@ module Split = let getChunkValues = getChunkValues processor allocationMode matrix.Values let getChunkIndices = getChunkIndices processor allocationMode matrix.Columns + let creatSparseVector values columns = + { Context = clContext + Indices = columns + Values = values + Size = matrix.ColumnCount } + matrix.RowPointers.ToHost processor |> Seq.pairwise |> Seq.map (fun (first, second) -> @@ -62,7 +83,7 @@ module Split = let values = getChunkValues first second let columns = getChunkIndices first second - Some (values, columns) + Some <| creatSparseVector values columns else None) let runCSR (clContext: ClContext) workGroupSize = @@ -73,3 +94,43 @@ module Split = runLazy processor allocationMode matrix |> Seq.map (fun lazyValue -> lazyValue.Value) |> Seq.toArray + + module ByColumn = + let runCSRLazy (clContext: ClContext) workGroupSize = + + let getChunkValues = ClArray.getChunk clContext workGroupSize + + let getChunkIndices = ClArray.getChunk clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSC<'a>) -> + + let getChunkValues = getChunkValues processor allocationMode matrix.Values + let getChunkIndices = getChunkIndices processor allocationMode matrix.Rows + + let creatSparseVector values columns = + { Context = clContext + Indices = columns + Values = values + Size = matrix.RowCount } + + matrix.ColumnPointers.ToHost processor + |> Seq.pairwise + |> Seq.map (fun (first, second) -> + lazy + if second - first > 0 then + let values = getChunkValues first second + let rows = getChunkIndices first second + + Some <| creatSparseVector values rows + else None) + + let runCSR (clContext: ClContext) workGroupSize = + + let runLazy = runCSRLazy clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSC<'a>) -> + runLazy processor allocationMode matrix + |> Seq.map (fun lazyValue -> lazyValue.Value) + |> Seq.toArray + + diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/chunkBySize.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/chunkBySize.fs new file mode 100644 index 00000000..92cc2514 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/chunkBySize.fs @@ -0,0 +1,107 @@ +module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.chunkBySize + +open Expecto +open Brahma.FSharp +open GraphBLAS.FSharp.Backend.Common +open GraphBLAS.FSharp.Test +open GraphBLAS.FSharp.Tests +open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions + +let context = Context.defaultContext.ClContext + +let processor = Context.defaultContext.Queue + +let config = { Utils.defaultConfig with arbitrary = [ typeof ] } + +let makeTestGetChunk<'a when 'a : equality> testFun (array: 'a [], startPosition: int, endPosition: int) = + + if array.Length > 0 then + + let clArray = context.CreateClArray array + + let (clActual: ClArray<'a>) = + testFun processor HostInterop clArray startPosition endPosition + + clArray.Free processor + let actual = clActual.ToHostAndFree processor + + "Results must be the same" + |> Expect.sequenceEqual actual array.[startPosition .. endPosition - 1] + +let creatTestGetChunk<'a when 'a : equality> = + ClArray.getChunk context Utils.defaultWorkGroupSize + |> makeTestGetChunk<'a> + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let getChunkTests = + [ creatTestGetChunk + + if Utils.isFloat64Available context.ClDevice then + creatTestGetChunk + + creatTestGetChunk + creatTestGetChunk + creatTestGetChunk ] + |> testList "getChunk" + +let makeTestChunkBySize<'a when 'a : equality> isEqual testFun (array: 'a [], chunkSize: uint) = + + let chunkSize = int chunkSize + + if chunkSize > 0 && array.Length > 0 then + + let clArray = context.CreateClArray array + + let clActual: ClArray<'a>[] = + (testFun processor HostInterop chunkSize clArray) + + clArray.Free processor + + let actual = + clActual + |> Array.map (fun clArray -> clArray.ToHostAndFree processor) + + let expected = + Array.chunkBySize chunkSize array + + "Results must be the same" + |> Utils.compareChunksArrays isEqual actual expected + +let creatTestChunkBySize<'a when 'a : equality> isEqual = + ClArray.chunkBySize context Utils.defaultWorkGroupSize + |> makeTestChunkBySize<'a> isEqual + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let chunkBySizeTests = + [ creatTestChunkBySize (=) + + if Utils.isFloat64Available context.ClDevice then + creatTestChunkBySize Utils.floatIsEqual + + creatTestChunkBySize Utils.float32IsEqual + creatTestChunkBySize (=) + creatTestChunkBySize (=) ] + |> testList "chanBySize" + +let creatTestChunkBySizeLazy<'a when 'a : equality> isEqual = + (fun processor allocationMode chunkSize array -> + ClArray.lazyChunkBySize context Utils.defaultWorkGroupSize processor allocationMode chunkSize array + |> Seq.map (fun lazyValue -> lazyValue.Value) + |> Seq.toArray) + |> makeTestChunkBySize<'a> isEqual + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let lazyChunkBySizeTests = + [ creatTestChunkBySizeLazy (=) + + if Utils.isFloat64Available context.ClDevice then + creatTestChunkBySizeLazy Utils.floatIsEqual + + creatTestChunkBySizeLazy Utils.float32IsEqual + creatTestChunkBySizeLazy (=) + creatTestChunkBySizeLazy (=) ] + |> testList "chunkBySize lazy" + +let allTests = + testList "chunk" [ getChunkTests; chunkBySizeTests; lazyChunkBySizeTests ] diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index 4182b57a..4e30171a 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -820,3 +820,60 @@ module Generators = static member BoolType() = pairOfVectorsOfEqualSize <| Arb.generate |> Arb.fromGen + + type ArrayAndChunkPositions() = + static let arrayAndChunkPosition (valuesGenerator: Gen<'a>) = + gen { + let! length = Gen.sized <| fun size -> Gen.choose (1, size) + + let! array = Gen.arrayOfLength length valuesGenerator + + let! endPosition = Gen.choose (1, length - 1) + let! startPosition = Gen.choose (0, endPosition - 1) + + return (array, startPosition, endPosition) + } + + static member IntType() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member FloatType() = + arrayAndChunkPosition + <| (Arb.Default.NormalFloat() + |> Arb.toGen + |> Gen.map float) + |> Arb.fromGen + + static member Float32Type() = + arrayAndChunkPosition + <| (normalFloat32Generator <| System.Random()) + |> Arb.fromGen + + static member SByteType() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member ByteType() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member Int16Type() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member UInt16Type() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member Int32Type() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member UInt32Type() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member BoolType() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index 234c76a1..ac1ace07 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -24,6 +24,7 @@ + @@ -49,6 +50,7 @@ + diff --git a/tests/GraphBLAS-sharp.Tests/Helpers.fs b/tests/GraphBLAS-sharp.Tests/Helpers.fs index c45a2674..19abea82 100644 --- a/tests/GraphBLAS-sharp.Tests/Helpers.fs +++ b/tests/GraphBLAS-sharp.Tests/Helpers.fs @@ -99,6 +99,13 @@ module Utils = Actual value is %A{actual.[i]}, expected %A{expected.[i]}, \n actual: %A{actual} \n expected: %A{expected}" |> failtestf "%s" + let compareChunksArrays areEqual (actual: 'a [][]) (expected: 'a [][]) message = + $"%s{message}. Lengths should be equal. Actual is %A{actual}, expected %A{expected}" + |> Expect.equal actual.Length expected.Length + + for i in 0 .. actual.Length - 1 do + compareArrays areEqual actual.[i] expected.[i] message + let compare2DArrays areEqual (actual: 'a [,]) (expected: 'a [,]) message = $"%s{message}. Lengths should be equal. Actual is %A{actual}, expected %A{expected}" |> Expect.equal actual.Length expected.Length diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Split.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Split.fs new file mode 100644 index 00000000..2c25c9c6 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Split.fs @@ -0,0 +1,4 @@ +module GraphBLAS.FSharp.Tests.Backend.Matrix.Split + +let makeTest testFun = + diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index 8532df05..00bdb716 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -1,96 +1,96 @@ open Expecto open GraphBLAS.FSharp.Tests.Backend -let matrixTests = - testList - "Matrix tests" - [ Matrix.Convert.tests - Matrix.Map2.addTests - Matrix.Map2.addAtLeastOneTests - Matrix.Map2.mulAtLeastOneTests - Matrix.Map2.addAtLeastOneToCOOTests - Matrix.Map.notTests - Matrix.Map.addTests - Matrix.Map.mulTests - Matrix.Mxm.tests - Matrix.Transpose.tests ] - |> testSequenced - -let commonTests = - let scanTests = - testList - "Scan" - [ Common.Scan.ByKey.sequentialSegmentsTests - Common.Scan.PrefixSum.tests ] - - let reduceTests = - testList - "Reduce" - [ Common.Reduce.ByKey.sequentialTest - Common.Reduce.ByKey.sequentialSegmentTests - Common.Reduce.ByKey.oneWorkGroupTest - Common.Reduce.Reduce.tests - Common.Reduce.Sum.tests ] - - let clArrayTests = - testList - "ClArray" - [ Common.ClArray.RemoveDuplicates.tests - Common.ClArray.Copy.tests - Common.ClArray.Replicate.tests - Common.ClArray.Exists.tests - Common.ClArray.Map.tests - Common.ClArray.Map2.addTests - Common.ClArray.Map2.mulTests - Common.ClArray.Choose.tests ] - - let sortTests = - testList - "Sort" - [ Common.Sort.Bitonic.tests - Common.Sort.Radix.testsByKeys - Common.Sort.Radix.testKeysOnly ] - - testList - "Common tests" - [ clArrayTests - sortTests - reduceTests - scanTests - Common.Scatter.tests ] - |> testSequenced - -let vectorTests = - testList - "Vector tests" - [ Vector.SpMV.tests - Vector.ZeroCreate.tests - Vector.OfList.tests - Vector.Copy.tests - Vector.Convert.tests - Vector.Map2.addTests - Vector.Map2.mulTests - Vector.Map2.addAtLeastOneTests - Vector.Map2.mulAtLeastOneTests - Vector.Map2.complementedGeneralTests - Vector.AssignByMask.tests - Vector.AssignByMask.complementedTests - Vector.Reduce.tests ] - |> testSequenced - -let algorithmsTests = - testList "Algorithms tests" [ Algorithms.BFS.tests ] - |> testSequenced - -[] -let allTests = - testList - "All tests" - [ matrixTests - commonTests - vectorTests - algorithmsTests ] - |> testSequenced +// let matrixTests = +// testList +// "Matrix tests" +// [ Matrix.Convert.tests +// Matrix.Map2.addTests +// Matrix.Map2.addAtLeastOneTests +// Matrix.Map2.mulAtLeastOneTests +// Matrix.Map2.addAtLeastOneToCOOTests +// Matrix.Map.notTests +// Matrix.Map.addTests +// Matrix.Map.mulTests +// Matrix.Mxm.tests +// Matrix.Transpose.tests ] +// |> testSequenced +// +// let commonTests = +// let scanTests = +// testList +// "Scan" +// [ Common.Scan.ByKey.sequentialSegmentsTests +// Common.Scan.PrefixSum.tests ] +// +// let reduceTests = +// testList +// "Reduce" +// [ Common.Reduce.ByKey.sequentialTest +// Common.Reduce.ByKey.sequentialSegmentTests +// Common.Reduce.ByKey.oneWorkGroupTest +// Common.Reduce.Reduce.tests +// Common.Reduce.Sum.tests ] +// +// let clArrayTests = +// testList +// "ClArray" +// [ Common.ClArray.RemoveDuplicates.tests +// Common.ClArray.Copy.tests +// Common.ClArray.Replicate.tests +// Common.ClArray.Exists.tests +// Common.ClArray.Map.tests +// Common.ClArray.Map2.addTests +// Common.ClArray.Map2.mulTests +// Common.ClArray.Choose.tests ] +// +// let sortTests = +// testList +// "Sort" +// [ Common.Sort.Bitonic.tests +// Common.Sort.Radix.testsByKeys +// Common.Sort.Radix.testKeysOnly ] +// +// testList +// "Common tests" +// [ clArrayTests +// sortTests +// reduceTests +// scanTests +// Common.Scatter.tests ] +// |> testSequenced +// +// let vectorTests = +// testList +// "Vector tests" +// [ Vector.SpMV.tests +// Vector.ZeroCreate.tests +// Vector.OfList.tests +// Vector.Copy.tests +// Vector.Convert.tests +// Vector.Map2.addTests +// Vector.Map2.mulTests +// Vector.Map2.addAtLeastOneTests +// Vector.Map2.mulAtLeastOneTests +// Vector.Map2.complementedGeneralTests +// Vector.AssignByMask.tests +// Vector.AssignByMask.complementedTests +// Vector.Reduce.tests ] +// |> testSequenced +// +// let algorithmsTests = +// testList "Algorithms tests" [ Algorithms.BFS.tests ] +// |> testSequenced +// +// [] +// let allTests = +// testList +// "All tests" +// [ matrixTests +// commonTests +// vectorTests +// algorithmsTests ] +// |> testSequenced [] -let main argv = allTests |> runTestsWithCLIArgs [] argv +let main argv = Common.ClArray.chunkBySize.allTests |> runTestsWithCLIArgs [] argv From 0cfe11281fa5f996d4953296f17a7d8c511d4042 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 14 Apr 2023 15:49:59 +0300 Subject: [PATCH 04/44] add: ClArray.append --- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 33 +++++ .../GraphBLAS-sharp.Backend.fsproj | 40 ++---- .../Matrix/{COOMatrix => COO}/Map.fs | 0 .../Matrix/{COOMatrix => COO}/Map2.fs | 0 .../{COOMatrix => COO}/Map2AtLeastOne.fs | 0 .../Matrix/{COOMatrix => COO}/Matrix.fs | 0 .../Matrix/{CSRMatrix => CSR}/GetTuples.fs | 0 .../Matrix/{CSRMatrix => CSR}/Map.fs | 0 .../Matrix/{CSRMatrix => CSR}/Map2.fs | 0 .../{CSRMatrix => CSR}/Map2AtLeastOne.fs | 0 .../Matrix/{CSRMatrix => CSR}/Matrix.fs | 39 +++++ .../Matrix/{CSRMatrix => CSR}/SpGEMM.fs | 0 .../Matrix/{CSRMatrix => CSR}/SpMSpV.fs | 0 .../Matrix/{CSRMatrix => CSR}/Transpose.fs | 0 src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 16 +++ .../Matrix/Rows/Matrix.fs | 16 +++ src/GraphBLAS-sharp.Backend/Matrix/Split.fs | 136 ------------------ src/GraphBLAS-sharp.Backend/Objects/Matrix.fs | 18 +++ .../Vector/SparseVector/SparseVector.fs | 11 ++ src/GraphBLAS-sharp.Backend/Vector/Vector.fs | 13 +- 20 files changed, 148 insertions(+), 174 deletions(-) rename src/GraphBLAS-sharp.Backend/Matrix/{COOMatrix => COO}/Map.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{COOMatrix => COO}/Map2.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{COOMatrix => COO}/Map2AtLeastOne.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{COOMatrix => COO}/Matrix.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{CSRMatrix => CSR}/GetTuples.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{CSRMatrix => CSR}/Map.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{CSRMatrix => CSR}/Map2.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{CSRMatrix => CSR}/Map2AtLeastOne.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{CSRMatrix => CSR}/Matrix.fs (77%) rename src/GraphBLAS-sharp.Backend/Matrix/{CSRMatrix => CSR}/SpGEMM.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{CSRMatrix => CSR}/SpMSpV.fs (100%) rename src/GraphBLAS-sharp.Backend/Matrix/{CSRMatrix => CSR}/Transpose.fs (100%) create mode 100644 src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs delete mode 100644 src/GraphBLAS-sharp.Backend/Matrix/Split.fs diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 4804d690..0cd0f0cc 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -411,3 +411,36 @@ module ClArray = chunkBySizeLazy processor allocationMode chunkSize sourceArray |> Seq.map (fun lazyValue -> lazyValue.Value) |> Seq.toArray + + let append<'a> (clContext: ClContext) workGroupSize = + + let set = + <@ fun (ndRange: Range1D) sourceArrayLength appendedArrayLength (inputArray: ClArray<'a>) (result: ClArray<'a>) -> + + let gid = ndRange.GlobalID0 + + let resultPosition = gid + sourceArrayLength + + if gid < appendedArrayLength then + + result.[resultPosition] <- inputArray.[gid] @> + + let kernel = clContext.Compile set + + fun (processor: MailboxProcessor<_>) allocationMode (sourceArray: ClArray<'a>) (appendedArray: ClArray<'a>) -> + + let resultLength = sourceArray.Length + appendedArray.Length + + let result = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + let ndRange = + Range1D.CreateValid(appendedArray.Length, workGroupSize) + + let kernel = kernel.GetKernel() + + processor.Post(Msg.MsgSetArguments(fun () -> kernel.KernelFunc ndRange sourceArray.Length appendedArray.Length appendedArray result)) + + processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + + result diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index 580d2a5a..59db4bac 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -34,19 +34,6 @@ - - - - - - - - - - - - - @@ -54,22 +41,19 @@ + + + + + + + + + + + + - - - - - diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COOMatrix/Map.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Map.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/COOMatrix/Map.fs rename to src/GraphBLAS-sharp.Backend/Matrix/COO/Map.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COOMatrix/Map2.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/COOMatrix/Map2.fs rename to src/GraphBLAS-sharp.Backend/Matrix/COO/Map2.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COOMatrix/Map2AtLeastOne.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2AtLeastOne.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/COOMatrix/Map2AtLeastOne.fs rename to src/GraphBLAS-sharp.Backend/Matrix/COO/Map2AtLeastOne.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COOMatrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/COOMatrix/Matrix.fs rename to src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/GetTuples.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/GetTuples.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/GetTuples.fs rename to src/GraphBLAS-sharp.Backend/Matrix/CSR/GetTuples.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Map.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Map.fs rename to src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Map2.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Map2.fs rename to src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Map2AtLeastOne.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Map2AtLeastOne.fs rename to src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs similarity index 77% rename from src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Matrix.fs rename to src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 5a606ad3..087415f5 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -8,6 +8,8 @@ open Microsoft.FSharp.Quotations open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClMatrix open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Backend.Objects.ClVector +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions module Matrix = let private expandRowPointers (clContext: ClContext) workGroupSize = @@ -140,6 +142,43 @@ module Matrix = |> transposeInplace queue |> toCSRInplace queue allocationMode + let byRowsLazy (clContext: ClContext) workGroupSize = + + let getChunkValues = ClArray.getChunk clContext workGroupSize + + let getChunkIndices = ClArray.getChunk clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> + + let getChunkValues = getChunkValues processor allocationMode matrix.Values + let getChunkIndices = getChunkIndices processor allocationMode matrix.Columns + + let creatSparseVector values columns = + { Context = clContext + Indices = columns + Values = values + Size = matrix.ColumnCount } + + matrix.RowPointers.ToHost processor + |> Seq.pairwise + |> Seq.map (fun (first, second) -> + lazy + if second - first > 0 then + let values = getChunkValues first second + let columns = getChunkIndices first second + + Some <| creatSparseVector values columns + else None) + + let byRows (clContext: ClContext) workGroupSize = + + let runLazy = byRowsLazy clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> + runLazy processor allocationMode matrix + |> Seq.map (fun lazyValue -> lazyValue.Value) + |> Seq.toArray + let spgemmCSC (clContext: ClContext) workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/SpGEMM.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/SpGEMM.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/SpGEMM.fs rename to src/GraphBLAS-sharp.Backend/Matrix/CSR/SpGEMM.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/SpMSpV.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/SpMSpV.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/SpMSpV.fs rename to src/GraphBLAS-sharp.Backend/Matrix/CSR/SpMSpV.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Transpose.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Transpose.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Matrix/CSRMatrix/Transpose.fs rename to src/GraphBLAS-sharp.Backend/Matrix/CSR/Transpose.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index 3fac746a..a25fb05d 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -6,13 +6,17 @@ open GraphBLAS.FSharp.Backend.Common open GraphBLAS.FSharp.Backend.Matrix open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClMatrix +open GraphBLAS.FSharp.Backend module Matrix = let copy (clContext: ClContext) workGroupSize = + let copy = ClArray.copy clContext workGroupSize let copyData = ClArray.copy clContext workGroupSize + let vectorCopy = Vector.Sparse.SparseVector.copy clContext workGroupSize + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.COO m -> @@ -39,6 +43,18 @@ module Matrix = Rows = copy processor allocationMode m.Rows ColumnPointers = copy processor allocationMode m.ColumnPointers Values = copyData processor allocationMode m.Values } + | ClMatrix.Rows matrix -> + matrix.Rows + |> Array.map (function + Some vector -> Some <| vectorCopy processor allocationMode vector + | None -> None) + |> fun rows -> + { Context = clContext + RowCount = matrix.RowCount + ColumnCount = matrix.ColumnCount + Rows = rows + NNZ = matrix.NNZ } + |> ClMatrix.Rows /// /// Creates a new matrix, represented in CSR format, that is equal to the given one. diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs new file mode 100644 index 00000000..0432ac5f --- /dev/null +++ b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs @@ -0,0 +1,16 @@ +namespace GraphBLAS.FSharp.Backend.Matrix.Rows + +open Brahma.FSharp +open Microsoft.FSharp.Quotations +open GraphBLAS.FSharp.Backend.Common +open GraphBLAS.FSharp.Backend.Matrix +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Objects.ClMatrix +open GraphBLAS.FSharp.Backend + +module Matrix = + let x = () + + let toCSR (clContext: ClContext) workGroupSize = + + () diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Split.fs b/src/GraphBLAS-sharp.Backend/Matrix/Split.fs deleted file mode 100644 index 61fcefd7..00000000 --- a/src/GraphBLAS-sharp.Backend/Matrix/Split.fs +++ /dev/null @@ -1,136 +0,0 @@ -namespace GraphBLAS.FSharp.Backend.Matrix - -open Brahma.FSharp -open GraphBLAS.FSharp.Backend.Common -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Objects.ClMatrix -open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions -open GraphBLAS.FSharp.Backend.Objects.ClVector - -// type lazy matrix ??? - -module Split = - module ByChunk = - let runCOOLazy (clContext: ClContext) workGroupSize = - - let chunkBySizeValues = ClArray.lazyChunkBySize clContext workGroupSize - - let chunkBySizeIndices = ClArray.lazyChunkBySize clContext workGroupSize - - fun (processor: MailboxProcessor<_>) allocationMode chunkSize (matrix: ClMatrix.COO<'a>) -> - - let createSubMatrixLazy (values: Lazy<_>) (columns: Lazy<_>) (rows: Lazy<_>) = - lazy - { Context = clContext - RowCount = matrix.RowCount - ColumnCount = matrix.ColumnCount - Rows = rows.Value - Columns = columns.Value - Values = values.Value } - - let values = chunkBySizeValues processor allocationMode chunkSize matrix.Values - let columns = chunkBySizeIndices processor allocationMode chunkSize matrix.Columns - let rows = chunkBySizeIndices processor allocationMode chunkSize matrix.Rows - - Seq.map3 createSubMatrixLazy values columns rows - - let runCOO (clContext: ClContext) workGroupSize = - - let run = runCOOLazy clContext workGroupSize - - fun (processor: MailboxProcessor<_>) allocationMode chunkSize (matrix: ClMatrix.COO<'a>) -> - run processor allocationMode chunkSize matrix - |> Seq.map (fun lazyMatrix -> lazyMatrix.Value) - |> Seq.toArray - - // let run (clContext: ClContext) workGroupSize = - // - // let run = runCOOLazy clContext workGroupSize - // - // let runCOO = runCOO clContext workGroupSize - // - // let COOToCSR = COO.Matrix.toCSR clCOntext workGroupSize - // - // fun (processor: MailboxProcessor<_>) allocationMode chunkSize (matrix: ClMatrix<'a>) -> - // match matrix with - // | ClMatrix.COO matrix -> runCOO processor allocationMode chunkSize matrix - // | ClMatrix.COO matrix -> - // () - module ByRow = - // MB We can split CSR to chunks without COO representation - let runCSRLazy (clContext: ClContext) workGroupSize = - - let getChunkValues = ClArray.getChunk clContext workGroupSize - - let getChunkIndices = ClArray.getChunk clContext workGroupSize - - fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> - - let getChunkValues = getChunkValues processor allocationMode matrix.Values - let getChunkIndices = getChunkIndices processor allocationMode matrix.Columns - - let creatSparseVector values columns = - { Context = clContext - Indices = columns - Values = values - Size = matrix.ColumnCount } - - matrix.RowPointers.ToHost processor - |> Seq.pairwise - |> Seq.map (fun (first, second) -> - lazy - if second - first > 0 then - let values = getChunkValues first second - let columns = getChunkIndices first second - - Some <| creatSparseVector values columns - else None) - - let runCSR (clContext: ClContext) workGroupSize = - - let runLazy = runCSRLazy clContext workGroupSize - - fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> - runLazy processor allocationMode matrix - |> Seq.map (fun lazyValue -> lazyValue.Value) - |> Seq.toArray - - module ByColumn = - let runCSRLazy (clContext: ClContext) workGroupSize = - - let getChunkValues = ClArray.getChunk clContext workGroupSize - - let getChunkIndices = ClArray.getChunk clContext workGroupSize - - fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSC<'a>) -> - - let getChunkValues = getChunkValues processor allocationMode matrix.Values - let getChunkIndices = getChunkIndices processor allocationMode matrix.Rows - - let creatSparseVector values columns = - { Context = clContext - Indices = columns - Values = values - Size = matrix.RowCount } - - matrix.ColumnPointers.ToHost processor - |> Seq.pairwise - |> Seq.map (fun (first, second) -> - lazy - if second - first > 0 then - let values = getChunkValues first second - let rows = getChunkIndices first second - - Some <| creatSparseVector values rows - else None) - - let runCSR (clContext: ClContext) workGroupSize = - - let runLazy = runCSRLazy clContext workGroupSize - - fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSC<'a>) -> - runLazy processor allocationMode matrix - |> Seq.map (fun lazyValue -> lazyValue.Value) - |> Seq.toArray - - diff --git a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs index 957c5fe3..58b5bd5a 100644 --- a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs @@ -75,6 +75,19 @@ module ClMatrix = member this.NNZ = this.Values.Length + type Rows<'elem when 'elem : struct> = + { Context: ClContext + RowCount: int + ColumnCount: int + Rows: ClVector.Sparse<'elem> option [] + NNZ: int } // TODO(empty vector) (or only some with row index ???) + + interface IDeviceMemObject with + member this.Dispose q = + this.Rows + |> Array.choose id + |> Array.iter (fun vector -> vector.Dispose q) + type Tuple<'elem when 'elem: struct> = { Context: ClContext RowIndices: ClArray @@ -95,27 +108,32 @@ type ClMatrix<'a when 'a: struct> = | CSR of ClMatrix.CSR<'a> | COO of ClMatrix.COO<'a> | CSC of ClMatrix.CSC<'a> + | Rows of ClMatrix.Rows<'a> member this.RowCount = match this with | ClMatrix.CSR matrix -> matrix.RowCount | ClMatrix.COO matrix -> matrix.RowCount | ClMatrix.CSC matrix -> matrix.RowCount + | ClMatrix.Rows matrix -> matrix.RowCount member this.ColumnCount = match this with | ClMatrix.CSR matrix -> matrix.ColumnCount | ClMatrix.COO matrix -> matrix.ColumnCount | ClMatrix.CSC matrix -> matrix.ColumnCount + | ClMatrix.Rows matrix -> matrix.ColumnCount member this.Dispose q = match this with | ClMatrix.CSR matrix -> (matrix :> IDeviceMemObject).Dispose q | ClMatrix.COO matrix -> (matrix :> IDeviceMemObject).Dispose q | ClMatrix.CSC matrix -> (matrix :> IDeviceMemObject).Dispose q + | ClMatrix.Rows matrix -> (matrix :> IDeviceMemObject).Dispose q member this.NNZ = match this with | ClMatrix.CSR matrix -> matrix.NNZ | ClMatrix.COO matrix -> matrix.NNZ | ClMatrix.CSC matrix -> matrix.NNZ + | ClMatrix.Rows matrix -> matrix.NNZ diff --git a/src/GraphBLAS-sharp.Backend/Vector/SparseVector/SparseVector.fs b/src/GraphBLAS-sharp.Backend/Vector/SparseVector/SparseVector.fs index 2e597e1f..bf0a9e1a 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/SparseVector/SparseVector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/SparseVector/SparseVector.fs @@ -9,6 +9,17 @@ open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClVector module SparseVector = + let copy (clContext: ClContext) workGroupSize = + let copy = ClArray.copy clContext workGroupSize + + let copyData = ClArray.copy clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (vector: Sparse<'a>) -> + { Context = clContext + Indices = copy processor allocationMode vector.Indices + Values = copyData processor allocationMode vector.Values + Size = vector.Size } + let map2 = Map2.run let map2AtLeastOne (clContext: ClContext) opAdd workGroupSize allocationMode = diff --git a/src/GraphBLAS-sharp.Backend/Vector/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Vector.fs index 0746d515..9ef48ab7 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Vector.fs @@ -79,26 +79,19 @@ module Vector = ClVector.Dense result let copy (clContext: ClContext) workGroupSize = - let copy = ClArray.copy clContext workGroupSize - - let copyData = ClArray.copy clContext workGroupSize + let sparseCopy = SparseVector.copy clContext workGroupSize let copyOptionData = ClArray.copy clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (vector: ClVector<'a>) -> match vector with | ClVector.Sparse vector -> - { Context = clContext - Indices = copy processor allocationMode vector.Indices - Values = copyData processor allocationMode vector.Values - Size = vector.Size } - |> ClVector.Sparse + ClVector.Sparse + <| sparseCopy processor allocationMode vector | ClVector.Dense vector -> ClVector.Dense <| copyOptionData processor allocationMode vector - let mask = copy - let toSparse (clContext: ClContext) workGroupSize = let toSparse = DenseVector.toSparse clContext workGroupSize From a79542d9ae4ebaa1d117867700239a77741f7c04 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 14 Apr 2023 20:39:42 +0300 Subject: [PATCH 05/44] add: Vector.map --- .../BenchmarksMxm.fs | 2 +- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 71 ++++++++++--- .../GraphBLAS-sharp.Backend.fsproj | 11 ++- .../Matrix/COO/Matrix.fs | 30 ++++++ src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 62 ++++++++---- .../Matrix/Rows/Matrix.fs | 75 +++++++++++++- .../{DenseVector => Dense}/DenseVector.fs | 0 .../Vector/{SparseVector => Sparse}/Common.fs | 0 .../Vector/Sparse/Map.fs | 99 +++++++++++++++++++ .../Vector/{SparseVector => Sparse}/Map2.fs | 0 .../Map2AtLeastOne.fs | 0 .../{SparseVector => Sparse}/SparseVector.fs | 21 ++++ 12 files changed, 327 insertions(+), 44 deletions(-) rename src/GraphBLAS-sharp.Backend/Vector/{DenseVector => Dense}/DenseVector.fs (100%) rename src/GraphBLAS-sharp.Backend/Vector/{SparseVector => Sparse}/Common.fs (100%) create mode 100644 src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs rename src/GraphBLAS-sharp.Backend/Vector/{SparseVector => Sparse}/Map2.fs (100%) rename src/GraphBLAS-sharp.Backend/Vector/{SparseVector => Sparse}/Map2AtLeastOne.fs (100%) rename src/GraphBLAS-sharp.Backend/Vector/{SparseVector => Sparse}/SparseVector.fs (76%) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs index a886736b..66e9f8ad 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs @@ -83,7 +83,7 @@ type MxmBenchmarks<'elem when 'elem : struct>( member this.FunCSC2CSR = match funCSC2CSR with | None -> - let x = Matrix.toCSRInplace this.OclContext this.WorkGroupSize + let x = Matrix.toCSRInPlace this.OclContext this.WorkGroupSize funCSC2CSR <- Some x x | Some x -> x diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 0cd0f0cc..d8349331 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -412,35 +412,82 @@ module ClArray = |> Seq.map (fun lazyValue -> lazyValue.Value) |> Seq.toArray - let append<'a> (clContext: ClContext) workGroupSize = + let assign<'a> (clContext: ClContext) workGroupSize = - let set = - <@ fun (ndRange: Range1D) sourceArrayLength appendedArrayLength (inputArray: ClArray<'a>) (result: ClArray<'a>) -> + let assign = + <@ fun (ndRange: Range1D) startPosition appendedArrayLength (inputArray: ClArray<'a>) (result: ClArray<'a>) -> let gid = ndRange.GlobalID0 - let resultPosition = gid + sourceArrayLength + let resultPosition = gid + startPosition if gid < appendedArrayLength then result.[resultPosition] <- inputArray.[gid] @> - let kernel = clContext.Compile set + let kernel = clContext.Compile assign - fun (processor: MailboxProcessor<_>) allocationMode (sourceArray: ClArray<'a>) (appendedArray: ClArray<'a>) -> - - let resultLength = sourceArray.Length + appendedArray.Length - - let result = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + fun (processor: MailboxProcessor<_>) allocationMode (targetArray: ClArray<'a>) startPosition (appendedArray: ClArray<'a>) -> + if startPosition < 0 then failwith "The starting position cannot be less than zero" + if startPosition + appendedArray.Length > targetArray.Length then + failwith "The array should fit completely" let ndRange = Range1D.CreateValid(appendedArray.Length, workGroupSize) let kernel = kernel.GetKernel() - processor.Post(Msg.MsgSetArguments(fun () -> kernel.KernelFunc ndRange sourceArray.Length appendedArray.Length appendedArray result)) + processor.Post(Msg.MsgSetArguments(fun () -> kernel.KernelFunc ndRange appendedArray.Length appendedArray.Length appendedArray targetArray)) processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + let concat (clContext: ClContext) workGroupSize = + + let assign = assign clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (sourceArrays: ClArray<'a> seq) -> + + let resultLength = + sourceArrays |> Seq.sumBy (fun array -> array.Length) + + let result = clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) + + let assign = assign processor allocationMode result + + // write each array to result + Seq.fold (fun previousLength array -> + assign previousLength array + previousLength + array.Length) 0 sourceArrays + |> ignore + result + + let fill (clContext: ClContext) workGroupSize = + + let fill = + <@ fun (ndRange: Range1D) firstPosition endPosition (value: ClCell<'a>) (targetArray: ClArray<'a>) -> + + let gid = ndRange.GlobalID0 + let writePosition = gid + firstPosition + + if writePosition < endPosition then + + targetArray.[writePosition] <- value.Value @> + + let kernel = clContext.Compile fill + + fun (processor: MailboxProcessor<_>) value firstPosition count (targetArray: ClArray<'a>) -> + if firstPosition + count > targetArray.Length then failwith "" + if firstPosition < 0 then failwith "" + if count <= 0 then failwith "" // TODO() + + let ndRange = + Range1D.CreateValid(count, workGroupSize) + + let kernel = kernel.GetKernel() + + processor.Post(Msg.MsgSetArguments(fun () -> kernel.KernelFunc ndRange firstPosition (firstPosition + count) value targetArray)) + + processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + + () diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index 59db4bac..e122b07a 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -34,11 +34,12 @@ - - - - - + + + + + + diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs index f6a389d6..61006763 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs @@ -155,3 +155,33 @@ module Matrix = Columns = copy queue allocationMode matrix.Columns Values = copyData queue allocationMode matrix.Values } |> transposeInplace queue + + let concat (clContext: ClContext) workGroupSize = + + let concatValues = ClArray.concat clContext workGroupSize + + let concatIndices = ClArray.concat clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode columnCount rowCount (matrices: ClMatrix.COO<'a> seq) -> + + let resultValues = + matrices + |> Seq.map (fun matrix -> matrix.Values) + |> concatValues processor allocationMode + + let resultColumns = + matrices + |> Seq.map (fun matrix -> matrix.Columns) + |> concatIndices processor allocationMode + + let resultRows = + matrices + |> Seq.map (fun matrix -> matrix.Rows) + |> concatIndices processor allocationMode + + { Context = clContext + RowCount = rowCount + ColumnCount = columnCount + Rows = resultRows + Columns = resultColumns + Values = resultValues } diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index a25fb05d..70a7ef66 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -45,9 +45,7 @@ module Matrix = Values = copyData processor allocationMode m.Values } | ClMatrix.Rows matrix -> matrix.Rows - |> Array.map (function - Some vector -> Some <| vectorCopy processor allocationMode vector - | None -> None) + |> Array.map (Option.bind <| (Some << (vectorCopy processor allocationMode))) |> fun rows -> { Context = clContext RowCount = matrix.RowCount @@ -69,6 +67,8 @@ module Matrix = let transpose = CSR.Matrix.transpose clContext workGroupSize + let rowsToCSR = Rows.Matrix.toCSR clContext workGroupSize + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.COO m -> toCSR processor allocationMode m |> ClMatrix.CSR @@ -77,6 +77,9 @@ module Matrix = m.ToCSR |> transpose processor allocationMode |> ClMatrix.CSR + | ClMatrix.Rows m -> + rowsToCSR processor allocationMode m + |> ClMatrix.CSR /// /// Returns the matrix, represented in CSR format, that is equal to the given one. @@ -84,23 +87,26 @@ module Matrix = /// ///OpenCL context. ///Should be a power of 2 and greater than 1. - let toCSRInplace (clContext: ClContext) workGroupSize = - let toCSRInplace = + let toCSRInPlace (clContext: ClContext) workGroupSize = + let toCSRInPlace = COO.Matrix.toCSRInplace clContext workGroupSize - let transposeInplace = + let transposeInPlace = CSR.Matrix.transposeInplace clContext workGroupSize + let rowsToCSR = Rows.Matrix.toCSR clContext workGroupSize + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.COO m -> - toCSRInplace processor allocationMode m + toCSRInPlace processor allocationMode m |> ClMatrix.CSR | ClMatrix.CSR _ -> matrix | ClMatrix.CSC m -> m.ToCSR - |> transposeInplace processor allocationMode + |> transposeInPlace processor allocationMode |> ClMatrix.CSR + | _ -> failwith "not yet supported" /// /// Creates a new matrix, represented in COO format, that is equal to the given one. @@ -115,6 +121,9 @@ module Matrix = let transposeInplace = COO.Matrix.transposeInplace clContext workGroupSize + let rowsToCOO = + Rows.Matrix.toCOO clContext workGroupSize + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.COO _ -> copy processor allocationMode matrix @@ -124,6 +133,9 @@ module Matrix = |> toCOO processor allocationMode |> transposeInplace processor |> ClMatrix.COO + | ClMatrix.Rows m -> + rowsToCOO processor allocationMode m + |> ClMatrix.COO /// /// Returns the matrix, represented in COO format, that is equal to the given one. @@ -131,24 +143,28 @@ module Matrix = /// ///OpenCL context. ///Should be a power of 2 and greater than 1. - let toCOOInplace (clContext: ClContext) workGroupSize = - let toCOOInplace = + let toCOOInPlace (clContext: ClContext) workGroupSize = + let toCOOInPlace = CSR.Matrix.toCOOInplace clContext workGroupSize - let transposeInplace = + let transposeInPlace = COO.Matrix.transposeInplace clContext workGroupSize + let rowsToCOO = + Rows.Matrix.toCOO clContext workGroupSize + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.COO _ -> matrix | ClMatrix.CSR m -> - toCOOInplace processor allocationMode m + toCOOInPlace processor allocationMode m |> ClMatrix.COO | ClMatrix.CSC m -> m.ToCSR - |> toCOOInplace processor allocationMode - |> transposeInplace processor + |> toCOOInPlace processor allocationMode + |> transposeInPlace processor |> ClMatrix.COO + | _ -> failwith "not yet supported" /// /// Creates a new matrix, represented in CSC format, that is equal to the given one. @@ -156,7 +172,7 @@ module Matrix = ///OpenCL context. ///Should be a power of 2 and greater than 1. let toCSC (clContext: ClContext) workGroupSize = - let toCSR = COO.Matrix.toCSR clContext workGroupSize + let COOtoCSR = COO.Matrix.toCSR clContext workGroupSize let copy = copy clContext workGroupSize @@ -174,9 +190,10 @@ module Matrix = |> ClMatrix.CSC | ClMatrix.COO m -> (transposeCOO processor allocationMode m - |> toCSR processor allocationMode) + |> COOtoCSR processor allocationMode) .ToCSC |> ClMatrix.CSC + | _ -> failwith "not yet supported" /// /// Returns the matrix, represented in CSC format, that is equal to the given one. @@ -206,6 +223,7 @@ module Matrix = |> toCSRInplace processor allocationMode) .ToCSC |> ClMatrix.CSC + | _ -> failwith "not yet supported" let map (clContext: ClContext) (opAdd: Expr<'a option -> 'b option>) workGroupSize = let mapCOO = @@ -271,7 +289,7 @@ module Matrix = let CSRElementwise = CSR.Matrix.map2AtLeastOneToCOO clContext opAdd workGroupSize - let transposeCOOInplace = + let transposeCOOInPlace = COO.Matrix.transposeInplace clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode matrix1 matrix2 -> @@ -284,7 +302,7 @@ module Matrix = |> ClMatrix.COO | ClMatrix.CSC m1, ClMatrix.CSC m2 -> CSRElementwise processor allocationMode m1.ToCSR m2.ToCSR - |> transposeCOOInplace processor + |> transposeCOOInPlace processor |> ClMatrix.COO | _ -> failwith "Matrix formats are not matching" @@ -301,15 +319,16 @@ module Matrix = /// ///OpenCL context. ///Should be a power of 2 and greater than 1. - let transposeInplace (clContext: ClContext) workGroupSize = - let COOtransposeInplace = + let transposeInPlace (clContext: ClContext) workGroupSize = + let COOTransposeInPlace = COO.Matrix.transposeInplace clContext workGroupSize fun (processor: MailboxProcessor<_>) matrix -> match matrix with - | ClMatrix.COO m -> COOtransposeInplace processor m |> ClMatrix.COO + | ClMatrix.COO m -> COOTransposeInPlace processor m |> ClMatrix.COO | ClMatrix.CSR m -> ClMatrix.CSC m.ToCSC | ClMatrix.CSC m -> ClMatrix.CSR m.ToCSR + | ClMatrix.Rows _ -> failwith "not yet supported" /// /// Transposes the given matrix and returns result as a new matrix. @@ -352,6 +371,7 @@ module Matrix = Columns = copy processor allocationMode m.Rows Values = copyData processor allocationMode m.Values } |> ClMatrix.CSR + | ClMatrix.Rows _ -> failwith "not yet supported" let mxm (opAdd: Expr<'c -> 'c -> 'c option>) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs index 0432ac5f..11f8f88e 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs @@ -1,16 +1,81 @@ namespace GraphBLAS.FSharp.Backend.Matrix.Rows open Brahma.FSharp -open Microsoft.FSharp.Quotations open GraphBLAS.FSharp.Backend.Common open GraphBLAS.FSharp.Backend.Matrix open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Objects.ClMatrix open GraphBLAS.FSharp.Backend +open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Backend.Objects.ClMatrix module Matrix = - let x = () - let toCSR (clContext: ClContext) workGroupSize = - () + let concatVectors = + Vector.Sparse.SparseVector.concat clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (matrix: Rows<'a>) -> + + // create row pointers + let rowPointers = + matrix.Rows + |> Array.Parallel.map (function None -> 0 | Some array -> array.Size) + |> Array.scan (+) 0 // mb device prefix sum ??? + + let rowPointers = clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, rowPointers) + + // compact columns and values + matrix.Rows + |> Array.Parallel.choose id + |> concatVectors processor allocationMode + |> fun vector -> + { Context = clContext + RowCount = matrix.RowCount + ColumnCount = matrix.ColumnCount + RowPointers = rowPointers + Columns = vector.Indices + Values = vector.Values } + + let toCOO (clContext: ClContext) workGroupSize = + + let create = ClArray.create clContext workGroupSize + + let concatMatrix = COO.Matrix.concat clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (matrix: Rows<'a>) -> + + let createMatrix (vector: ClVector.Sparse<_>) rows = + { Context = clContext + RowCount = matrix.RowCount + ColumnCount = matrix.ColumnCount + Rows = rows + Columns = vector.Indices + Values = vector.Values } + + let indices, rowsVectors = + matrix.Rows + |> Array.Parallel.mapi (fun index optionRow -> + (match optionRow with + | None -> None + | Some row -> Some (index, row))) + |> Array.Parallel.choose id + |> Array.unzip + + // creat rows pointers + let rowsIndices = + (rowsVectors, indices) + ||> Array.map2 (fun array -> create processor allocationMode array.Values.Length) + + Array.map2 createMatrix rowsVectors rowsIndices + |> concatMatrix processor allocationMode matrix.ColumnCount matrix.RowCount + + let map (clContext: ClContext) workGroupSize = + + let map2 = Vector.Sparse.Map2.run clContext workGroupSize + + let map = Vector // TODO() + + fun (processor: MailboxProcessor<'a>) -> + + () + diff --git a/src/GraphBLAS-sharp.Backend/Vector/DenseVector/DenseVector.fs b/src/GraphBLAS-sharp.Backend/Vector/Dense/DenseVector.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Vector/DenseVector/DenseVector.fs rename to src/GraphBLAS-sharp.Backend/Vector/Dense/DenseVector.fs diff --git a/src/GraphBLAS-sharp.Backend/Vector/SparseVector/Common.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Common.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Vector/SparseVector/Common.fs rename to src/GraphBLAS-sharp.Backend/Vector/Sparse/Common.fs diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs new file mode 100644 index 00000000..2819f293 --- /dev/null +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs @@ -0,0 +1,99 @@ +namespace GraphBLAS.FSharp.Backend.Vector.Sparse + +open Brahma.FSharp +open Microsoft.FSharp.Control +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Objects.ClVector +open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Backend.Quotes +open FSharp.Quotations +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions + +module internal Map = + let preparePositions<'a, 'b> (clContext: ClContext) workGroupSize opAdd = + // we can decrease memory requirements by two pass map (like choose) + let preparePositions (op: Expr<'a option -> 'b option>) = + <@ fun (ndRange: Range1D) dataLength vectorLength (values: ClArray<'a>) (indices: ClArray) (resultBitmap: ClArray) (resultValues: ClArray<'b>) (resultIndices: ClArray) -> + + let gid = ndRange.GlobalID0 + + if gid < vectorLength then + + let value = + (%Search.Bin.byKey) dataLength gid indices values + + match (%op) value with + | Some resultValue -> + resultValues.[gid] <- resultValue + resultIndices.[gid] <- gid + + resultBitmap.[gid] <- 1 + | None -> resultBitmap.[gid] <- 0 @> + + let kernel = + clContext.Compile <| preparePositions opAdd + + fun (processor: MailboxProcessor<_>) (vector: ClVector.Sparse<'a>) -> + + let resultBitmap = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, vector.Size) + + let resultIndices = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, vector.Size) + + let resultValues = + clContext.CreateClArrayWithSpecificAllocationMode<'b>(DeviceOnly, vector.Size) + + let ndRange = + Range1D.CreateValid(vector.Size, workGroupSize) + + let kernel = kernel.GetKernel() + + processor.Post( + Msg.MsgSetArguments + (fun () -> + kernel.KernelFunc + ndRange + vector.Values.Length + vector.Size + vector.Values + vector.Indices + resultBitmap + resultValues + resultIndices) + ) + + processor.Post(Msg.CreateRunMsg<_, _> kernel) + + resultBitmap, resultValues, resultIndices + + let run<'a, 'b when 'a: struct and 'b: struct and 'b: equality> + (clContext: ClContext) + (opAdd: Expr<'a option -> 'b option>) + workGroupSize + = + + let preparePositions = + preparePositions clContext workGroupSize opAdd + + let setPositions = + Common.setPositions<'b> clContext workGroupSize + + fun (queue: MailboxProcessor<_>) allocationMode (vector: ClVector.Sparse<'a>) -> + + let bitmap, values, indices = + preparePositions queue vector + + let resultValues, resultIndices = + setPositions queue allocationMode values indices bitmap + + bitmap.Free queue + values.Free queue + indices.Free queue + + { Context = clContext + Indices = resultIndices + Values = resultValues + Size = vector.Size } + + module AtLeastOne = diff --git a/src/GraphBLAS-sharp.Backend/Vector/SparseVector/Map2.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Vector/SparseVector/Map2.fs rename to src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2.fs diff --git a/src/GraphBLAS-sharp.Backend/Vector/SparseVector/Map2AtLeastOne.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2AtLeastOne.fs similarity index 100% rename from src/GraphBLAS-sharp.Backend/Vector/SparseVector/Map2AtLeastOne.fs rename to src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2AtLeastOne.fs diff --git a/src/GraphBLAS-sharp.Backend/Vector/SparseVector/SparseVector.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs similarity index 76% rename from src/GraphBLAS-sharp.Backend/Vector/SparseVector/SparseVector.fs rename to src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs index bf0a9e1a..64a1a7ea 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/SparseVector/SparseVector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs @@ -68,3 +68,24 @@ module SparseVector = Reduce.reduce clContext workGroupSize opAdd fun (processor: MailboxProcessor<_>) (vector: ClVector.Sparse<'a>) -> reduce processor vector.Values + + let concat<'a> (clContext: ClContext) workGroupSize = + + let concatValues = ClArray.concat clContext workGroupSize + + let concatIndices = ClArray.concat clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (vectors: ClVector.Sparse<'a> seq) -> + + let resultValues = + Seq.map (fun vector -> vector.Values) vectors + |> concatValues processor allocationMode + + let resultIndices = + Seq.map (fun vector -> vector.Indices) vectors + |> concatIndices processor allocationMode + + { Context = clContext + Indices = resultIndices + Values = resultValues + Size = resultValues.Length } // TODO(size) From d0133ecffc2c495120299553510008a1a93fac31 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 14 Apr 2023 20:47:08 +0300 Subject: [PATCH 06/44] wip: Vector.map2 --- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 2 -- src/GraphBLAS-sharp.Backend/Quotes/Map.fs | 6 ++++++ src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index d8349331..88fead0b 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -489,5 +489,3 @@ module ClArray = processor.Post(Msg.MsgSetArguments(fun () -> kernel.KernelFunc ndRange firstPosition (firstPosition + count) value targetArray)) processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - - () diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Map.fs b/src/GraphBLAS-sharp.Backend/Quotes/Map.fs index 58ad1026..c1808456 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Map.fs @@ -22,6 +22,12 @@ module Map = | Some _ -> 1 | None -> 0 @> + let choose2Bitmap<'a, 'b, 'c> (map: Expr<'a -> 'b -> 'c option>) = + <@ fun (leftItem: 'a) (rightItem: 'b) -> + match (%map) leftItem rightItem with + | Some _ -> 1 + | None -> 0 @> + let fst () = <@ fun fst _ -> fst @> let snd () = <@ fun _ snd -> snd @> diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs index 2819f293..8b174b51 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs @@ -8,6 +8,7 @@ open GraphBLAS.FSharp.Backend.Objects.ClContext open GraphBLAS.FSharp.Backend.Quotes open FSharp.Quotations open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +open GraphBLAS.FSharp.Backend.Common module internal Map = let preparePositions<'a, 'b> (clContext: ClContext) workGroupSize opAdd = @@ -97,3 +98,16 @@ module internal Map = Size = vector.Size } module AtLeastOne = + let run (clContext: ClContext) workGroupSize op = + + let getOptionBitmap = + ClArray.map2 clContext workGroupSize + <| Map.choose2Bitmap op + + let prefixSum = PrefixSum.standardExcludeInplace clContext workGroupSize + + let scatter = Scatter.runInplace clContext workGroupSize + + fun (processor: MailboxProcessor<_>) -> + + () From 4b7c3ed0974a82059b80194ed76cd921b79edc99 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sun, 16 Apr 2023 16:19:26 +0300 Subject: [PATCH 07/44] wip: expand refactor, tests in progress --- paket.dependencies | 2 +- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 32 ++- src/GraphBLAS-sharp.Backend/Common/Sum.fs | 152 ++++++++-- .../GraphBLAS-sharp.Backend.fsproj | 6 +- .../Matrix/CSR/Matrix.fs | 61 +--- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 10 +- .../Matrix/Rows/Matrix.fs | 12 +- .../Matrix/{CSR/SpGEMM => SpGeMM}/Expand.fs | 272 ++++++++---------- .../Matrix/{CSR/SpGEMM => SpGeMM}/Masked.fs | 2 +- src/GraphBLAS-sharp.Backend/Quotes/Convert.fs | 8 + .../Vector/Sparse/Map.fs | 23 +- src/GraphBLAS-sharp.Backend/paket.references | 2 +- .../Common/ClArray/Assign.fs | 51 ++++ .../{chunkBySize.fs => ChunkBySize.fs} | 0 .../Common/ClArray/Concat.fs | 48 ++++ .../GraphBLAS-sharp.Tests.fsproj | 4 +- 16 files changed, 442 insertions(+), 243 deletions(-) rename src/GraphBLAS-sharp.Backend/Matrix/{CSR/SpGEMM => SpGeMM}/Expand.fs (55%) rename src/GraphBLAS-sharp.Backend/Matrix/{CSR/SpGEMM => SpGeMM}/Masked.fs (99%) create mode 100644 tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs rename tests/GraphBLAS-sharp.Tests/Common/ClArray/{chunkBySize.fs => ChunkBySize.fs} (100%) create mode 100644 tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs diff --git a/paket.dependencies b/paket.dependencies index c1c5211c..a434e23e 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -59,4 +59,4 @@ group Docs group Analyzers source https://www.nuget.org/api/v2 source https://api.nuget.org/v3/index.json - nuget BinaryDefense.FSharp.Analyzers.Hashing 0.2.2 + nuget BinaryDefense.FSharp.Analyzers.Hashing 0.2.2 \ No newline at end of file diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index e683b135..a10698e8 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -335,7 +335,7 @@ module ClArray = let getUniqueBitmap2LastOccurrence clContext = getUniqueBitmap2General getUniqueBitmapLastOccurrence clContext - let private assignOption (clContext: ClContext) workGroupSize (op: Expr<'a -> 'b option>) = + let assignOption (clContext: ClContext) workGroupSize (op: Expr<'a -> 'b option>) = let assign = <@ fun (ndRange: Range1D) length (values: ClArray<'a>) (positions: ClArray) (result: ClArray<'b>) resultLength -> @@ -574,7 +574,7 @@ module ClArray = let kernel = clContext.Compile assign - fun (processor: MailboxProcessor<_>) allocationMode (targetArray: ClArray<'a>) startPosition (appendedArray: ClArray<'a>) -> + fun (processor: MailboxProcessor<_>) (targetArray: ClArray<'a>) startPosition (appendedArray: ClArray<'a>) -> if startPosition < 0 then failwith "The starting position cannot be less than zero" @@ -605,9 +605,9 @@ module ClArray = |> Seq.sumBy (fun array -> array.Length) let result = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - let assign = assign processor allocationMode result + let assign = assign processor result // write each array to result Seq.fold @@ -652,3 +652,27 @@ module ClArray = ) processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + + let pairwise (clContext: ClContext) workGroupSize = + + let idGather = + Gather.runInit Map.id clContext workGroupSize + + let incGather = + Gather.runInit Map.inc clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (values: ClArray<'a>) -> + + let resultLength = values.Length - 1 + + let firstItems = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + idGather processor values firstItems + + let secondItems = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + incGather processor values secondItems + + firstItems, secondItems diff --git a/src/GraphBLAS-sharp.Backend/Common/Sum.fs b/src/GraphBLAS-sharp.Backend/Common/Sum.fs index bdf1840d..40b8d8c9 100644 --- a/src/GraphBLAS-sharp.Backend/Common/Sum.fs +++ b/src/GraphBLAS-sharp.Backend/Common/Sum.fs @@ -315,7 +315,7 @@ module Reduce = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - reducedKeys, reducedValues + reducedValues, reducedKeys /// /// Reduces values by key. Each segment is reduced by one work item. @@ -381,7 +381,7 @@ module Reduce = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - reducedKeys, reducedValues + reducedValues, reducedKeys /// /// Reduces values by key. One work group participates in the reduction. @@ -470,8 +470,120 @@ module Reduce = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - reducedKeys, reducedValues + reducedValues, reducedKeys + /// + /// Reduces values by key. Each segment is reduced by one work item. + /// + /// ClContext. + /// Work group size. + /// Operation for reducing values. + /// + /// The length of the result must be calculated in advance. + /// + let segmentSequentialOption<'a> (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a option>) = + + let kernel = + <@ fun (ndRange: Range1D) uniqueKeyCount keysLength (offsets: ClArray) (keys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (firstReducedKeys: ClArray) (resultPositions: ClArray) -> + + let gid = ndRange.GlobalID0 + + if gid < uniqueKeyCount then + let startPosition = offsets.[gid] + + let firstSourceKey = keys.[startPosition] + + let mutable sum = Some values.[startPosition] + + let mutable currentPosition = startPosition + 1 + + while currentPosition < keysLength + && firstSourceKey = keys.[currentPosition] do + + match sum with + | Some value -> + let result = + ((%reduceOp) value values.[currentPosition]) // brahma error + + sum <- result + | None -> sum <- Some values.[currentPosition] + + currentPosition <- currentPosition + 1 + + match sum with + | Some value -> + reducedValues.[gid] <- value + resultPositions.[gid] <- 1 + | None -> resultPositions.[gid] <- 0 + + firstReducedKeys.[gid] <- firstSourceKey @> + + let kernel = clContext.Compile kernel + + let scatterData = + Scatter.lastOccurrence clContext workGroupSize + + let scatterIndices = + Scatter.lastOccurrence clContext workGroupSize + + let prefixSum = + PrefixSum.standardExcludeInplace clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (resultLength: int) (offsets: ClArray) (keys: ClArray) (values: ClArray<'a>) -> + + let reducedValues = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + let reducedKeys = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + let resultPositions = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) + + let ndRange = + Range1D.CreateValid(resultLength, workGroupSize) + + let kernel = kernel.GetKernel() + + processor.Post( + Msg.MsgSetArguments + (fun () -> + kernel.KernelFunc + ndRange + resultLength + keys.Length + offsets + keys + values + reducedValues + reducedKeys + resultPositions) + ) + + processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + + let resultLength = + (prefixSum processor resultPositions) + .ToHostAndFree processor + + if resultLength = 0 then None + else + let resultValues = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + scatterData processor resultPositions reducedValues resultValues + + reducedValues.Free processor + + let resultKeys = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + scatterIndices processor resultPositions reducedKeys resultKeys // TODO(mb error) + + reducedKeys.Free processor + resultPositions.Free processor + + Some (resultValues, reducedKeys) module ByKey2D = /// /// Reduce an array of values by 2D keys using a single work item. @@ -550,7 +662,7 @@ module Reduce = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - firstReducedKeys, secondReducedKeys, reducedValues + reducedValues, firstReducedKeys, secondReducedKeys /// /// Reduces values by key. Each segment is reduced by one work item. @@ -625,7 +737,7 @@ module Reduce = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - firstReducedKeys, secondReducedKeys, reducedValues + reducedValues, firstReducedKeys, secondReducedKeys /// /// Reduces values by key. Each segment is reduced by one work item. @@ -729,27 +841,29 @@ module Reduce = (prefixSum processor resultPositions) .ToHostAndFree processor - let resultValues = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + if resultLength = 0 then None + else + let resultValues = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - scatterData processor resultPositions reducedValues resultValues + scatterData processor resultPositions reducedValues resultValues - reducedValues.Free processor + reducedValues.Free processor - let resultFirstKeys = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + let resultFirstKeys = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - scatterIndices processor resultPositions firstReducedKeys resultFirstKeys + scatterIndices processor resultPositions firstReducedKeys resultFirstKeys - firstReducedKeys.Free processor + firstReducedKeys.Free processor - let resultSecondKeys = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + let resultSecondKeys = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - scatterIndices processor resultPositions secondReducedKeys resultSecondKeys + scatterIndices processor resultPositions secondReducedKeys resultSecondKeys - secondReducedKeys.Free processor + secondReducedKeys.Free processor - resultPositions.Free processor + resultPositions.Free processor - resultFirstKeys, resultSecondKeys, resultValues + Some (resultValues, resultFirstKeys, resultSecondKeys) diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index 6feb4ba4..d0e03da6 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -30,8 +30,8 @@ + - @@ -51,10 +51,10 @@ - - + + diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 48ecc06a..1f7eadd8 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -40,7 +40,7 @@ module Matrix = Columns = cols Values = values } - let toCOOInplace (clContext: ClContext) workGroupSize = + let toCOOInPlace (clContext: ClContext) workGroupSize = let prepare = Common.expandRowPointers clContext workGroupSize @@ -77,35 +77,35 @@ module Matrix = Map2AtLeastOne.run clContext (Convert.atLeastOneToOption opAdd) workGroupSize - let transposeInplace (clContext: ClContext) workGroupSize = + let transposeInPlace (clContext: ClContext) workGroupSize = - let toCOOInplace = toCOOInplace clContext workGroupSize + let toCOOInPlace = toCOOInPlace clContext workGroupSize - let transposeInplace = + let transposeInPlace = COO.Matrix.transposeInplace clContext workGroupSize - let toCSRInplace = + let toCSRInPlace = COO.Matrix.toCSRInplace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> - toCOOInplace queue allocationMode matrix - |> transposeInplace queue - |> toCSRInplace queue allocationMode + toCOOInPlace queue allocationMode matrix + |> transposeInPlace queue + |> toCSRInPlace queue allocationMode let transpose (clContext: ClContext) workGroupSize = let toCOO = toCOO clContext workGroupSize - let transposeInplace = + let transposeInPlace = COO.Matrix.transposeInplace clContext workGroupSize - let toCSRInplace = + let toCSRInPlace = COO.Matrix.toCSRInplace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> toCOO queue allocationMode matrix - |> transposeInplace queue - |> toCSRInplace queue allocationMode + |> transposeInPlace queue + |> toCSRInPlace queue allocationMode let byRowsLazy (clContext: ClContext) workGroupSize = @@ -148,40 +148,3 @@ module Matrix = runLazy processor allocationMode matrix |> Seq.map (fun lazyValue -> lazyValue.Value) |> Seq.toArray - - module SpGeMM = - let masked - (clContext: ClContext) - workGroupSize - (opAdd: Expr<'c -> 'c -> 'c option>) - (opMul: Expr<'a -> 'b -> 'c option>) - = - - let run = - SpGeMM.Masked.run clContext workGroupSize opAdd opMul - - fun (queue: MailboxProcessor<_>) (matrixLeft: ClMatrix.CSR<'a>) (matrixRight: ClMatrix.CSC<'b>) (mask: ClMatrix.COO<_>) -> - - run queue matrixLeft matrixRight mask - - let expand - (clContext: ClContext) - workGroupSize - (opAdd: Expr<'c -> 'c -> 'c option>) - (opMul: Expr<'a -> 'b -> 'c option>) - = - - let run = - SpGeMM.Expand.run clContext workGroupSize opAdd opMul - - fun (queue: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix.CSR<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> - - let values, columns, rows = - run queue allocationMode leftMatrix rightMatrix - - { COO.Context = clContext - ColumnCount = rightMatrix.ColumnCount - RowCount = leftMatrix.RowCount - Values = values - Columns = columns - Rows = rows } diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index ccf76ec7..2c15238d 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -97,7 +97,7 @@ module Matrix = COO.Matrix.toCSRInplace clContext workGroupSize let transposeInPlace = - CSR.Matrix.transposeInplace clContext workGroupSize + CSR.Matrix.transposeInPlace clContext workGroupSize let rowsToCSR = Rows.Matrix.toCSR clContext workGroupSize @@ -151,7 +151,7 @@ module Matrix = ///Should be a power of 2 and greater than 1. let toCOOInPlace (clContext: ClContext) workGroupSize = let toCOOInPlace = - CSR.Matrix.toCOOInplace clContext workGroupSize + CSR.Matrix.toCOOInPlace clContext workGroupSize let transposeInPlace = COO.Matrix.transposeInplace clContext workGroupSize @@ -212,7 +212,7 @@ module Matrix = COO.Matrix.toCSRInplace clContext workGroupSize let transposeCSRInplace = - CSR.Matrix.transposeInplace clContext workGroupSize + CSR.Matrix.transposeInPlace clContext workGroupSize let transposeCOOInplace = COO.Matrix.transposeInplace clContext workGroupSize @@ -388,7 +388,7 @@ module Matrix = = let runCSRnCSC = - CSR.Matrix.SpGeMM.masked clContext workGroupSize opAdd opMul + SpGeMM.Masked.run clContext workGroupSize opAdd opMul fun (queue: MailboxProcessor<_>) (matrix1: ClMatrix<'a>) (matrix2: ClMatrix<'b>) (mask: ClMatrix<_>) -> match matrix1, matrix2, mask with @@ -403,7 +403,7 @@ module Matrix = = let run = - CSR.Matrix.SpGeMM.expand clContext workGroupSize opAdd opMul + SpGeMM.Expand.run clContext workGroupSize opAdd opMul fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix<'a>) (rightMatrix: ClMatrix<'b>) -> match leftMatrix, rightMatrix with diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs index 2e1ab6e2..db3a986c 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs @@ -7,6 +7,8 @@ open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend open GraphBLAS.FSharp.Backend.Objects.ClContext open GraphBLAS.FSharp.Backend.Objects.ClMatrix +open GraphBLAS.FSharp.Backend.Quotes +open FSharp.Quotations.Evaluator module Matrix = let toCSR (clContext: ClContext) workGroupSize = @@ -74,13 +76,3 @@ module Matrix = Array.map2 createMatrix rowsVectors rowsIndices |> concatMatrix processor allocationMode matrix.ColumnCount matrix.RowCount - - // let map (clContext: ClContext) workGroupSize = - // - // let map2 = Vector.Sparse.Map2.run clContext workGroupSize - // - // let map = Vector // TODO() - // - // fun (processor: MailboxProcessor<'a>) -> - // - // () diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/SpGEMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs similarity index 55% rename from src/GraphBLAS-sharp.Backend/Matrix/CSR/SpGEMM/Expand.fs rename to src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index 489902f7..d4b8cda6 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/SpGEMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -1,4 +1,4 @@ -namespace GraphBLAS.FSharp.Backend.Matrix.CSR.SpGeMM +namespace GraphBLAS.FSharp.Backend.Matrix.SpGeMM open Brahma.FSharp open GraphBLAS.FSharp.Backend.Common @@ -10,58 +10,46 @@ open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClCell open FSharp.Quotations +open GraphBLAS.FSharp.Backend.Vector.Sparse +open GraphBLAS.FSharp.Backend.Objects.ClVector type Indices = ClArray type Values<'a> = ClArray<'a> module Expand = - let getSegmentPointers (clContext: ClContext) workGroupSize = - + let getRowsLength (clContext: ClContext) workGroupSize = let subtract = ClArray.map2 clContext workGroupSize Map.subtraction - let idGather = - Gather.runInit Map.id clContext workGroupSize - - let incGather = - Gather.runInit Map.inc clContext workGroupSize + let pairwise = ClArray.pairwise clContext workGroupSize - let gather = Gather.run clContext workGroupSize - - let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + fun (processor: MailboxProcessor<_>) (matrix: ClMatrix.CSR<'b>) -> - fun (processor: MailboxProcessor<_>) (leftMatrix: ClMatrix.CSR<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> + let firstPointers, secondPointers = + pairwise processor DeviceOnly matrix.RowPointers - let positionsLength = rightMatrix.RowPointers.Length - 1 + let rowsLength = subtract processor DeviceOnly secondPointers firstPointers - // extract first rightMatrix.RowPointers.Lengths - 1 indices from rightMatrix.RowPointers - // (right matrix row pointers without last item) - let firstPointers = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, positionsLength) + firstPointers.Free processor + secondPointers.Free processor - idGather processor rightMatrix.RowPointers firstPointers + rowsLength - // extract last rightMatrix.RowPointers.Lengths - 1 indices from rightMatrix.RowPointers - // (right matrix row pointers without first item) - let lastPointers = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, positionsLength) + let getSegmentPointers (clContext: ClContext) workGroupSize = - incGather processor rightMatrix.RowPointers lastPointers + let gather = Gather.run clContext workGroupSize - // subtract - let rightMatrixRowsLengths = - subtract processor DeviceOnly lastPointers firstPointers + let prefixSum = + PrefixSum.standardExcludeInplace clContext workGroupSize - firstPointers.Free processor - lastPointers.Free processor + fun (processor: MailboxProcessor<_>) (leftMatrixRow: ClVector.Sparse<'a>) (rightMatrixRowsLengths: ClArray) -> let segmentsLengths = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, leftMatrix.Columns.Length) + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, leftMatrixRow.Indices.Length) // extract needed lengths by left matrix nnz - gather processor leftMatrix.Columns rightMatrixRowsLengths segmentsLengths + gather processor leftMatrixRow.Indices rightMatrixRowsLengths segmentsLengths rightMatrixRowsLengths.Free processor @@ -72,46 +60,6 @@ module Expand = length, segmentsLengths - let multiply (clContext: ClContext) workGroupSize (predicate: Expr<'a -> 'b -> 'c option>) = - let getBitmap = - ClArray.map2<'a, 'b, int> clContext workGroupSize - <| Map.choose2Bitmap predicate - - let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize - - let assignValues = - ClArray.assignOption2 clContext workGroupSize predicate - - let scatter = - Scatter.lastOccurrence clContext workGroupSize - - fun (processor: MailboxProcessor<_>) (firstValues: ClArray<'a>) (secondValues: ClArray<'b>) (columns: Indices) (rows: Indices) -> - - let positions = - getBitmap processor DeviceOnly firstValues secondValues - - let resultLength = - (prefixSum processor positions) - .ToHostAndFree(processor) - - let resultColumns = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) - - scatter processor positions columns resultColumns - - let resultRows = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) - - scatter processor positions rows resultRows - - let resultValues = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) - - assignValues processor firstValues secondValues positions resultValues - - resultValues, resultColumns, resultRows - let expand (clContext: ClContext) workGroupSize = let idScatter = @@ -136,14 +84,11 @@ module Expand = let removeDuplicates = ClArray.removeDuplications clContext workGroupSize - let expandRowPointers = - Common.expandRowPointers clContext workGroupSize - let leftMatrixGather = Gather.run clContext workGroupSize let rightMatrixGather = Gather.run clContext workGroupSize - fun (processor: MailboxProcessor<_>) lengths (segmentsPointers: Indices) (leftMatrix: ClMatrix.CSR<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> + fun (processor: MailboxProcessor<_>) lengths (segmentsPointers: Indices) (leftMatrixRow: ClVector.Sparse<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> // Compute left matrix positions let leftMatrixPositions = zeroCreate processor DeviceOnly lengths @@ -157,9 +102,9 @@ module Expand = let rightMatrixPositions = create processor DeviceOnly lengths 1 let requiredRightMatrixPointers = - zeroCreate processor DeviceOnly leftMatrix.Columns.Length + zeroCreate processor DeviceOnly leftMatrixRow.Indices.Length - gather processor leftMatrix.Columns rightMatrix.RowPointers requiredRightMatrixPointers + gather processor leftMatrixRow.Indices rightMatrix.RowPointers requiredRightMatrixPointers scatter processor segmentsPointers requiredRightMatrixPointers rightMatrixPositions @@ -179,22 +124,11 @@ module Expand = gather processor rightMatrixPositions rightMatrix.Columns columns - // compute rows - let leftMatrixRows = - expandRowPointers processor DeviceOnly leftMatrix.RowPointers leftMatrix.NNZ leftMatrix.RowCount - - let rows = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, lengths) - - gather processor leftMatrixPositions leftMatrixRows rows - - leftMatrixRows.Free processor - // compute left matrix values let leftMatrixValues = clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, lengths) - leftMatrixGather processor leftMatrixPositions leftMatrix.Values leftMatrixValues + leftMatrixGather processor leftMatrixPositions leftMatrixRow.Values leftMatrixValues leftMatrixPositions.Free processor @@ -207,12 +141,46 @@ module Expand = rightMatrixPositions.Free processor // left, right matrix values, columns and rows indices - leftMatrixValues, rightMatrixValues, columns, rows + leftMatrixValues, rightMatrixValues, columns + + let multiply (clContext: ClContext) workGroupSize (predicate: Expr<'a -> 'b -> 'c option>) = + let getBitmap = + ClArray.map2<'a, 'b, int> clContext workGroupSize + <| Map.choose2Bitmap predicate - let sortByColumnsAndRows (clContext: ClContext) workGroupSize = + let prefixSum = + PrefixSum.standardExcludeInplace clContext workGroupSize - let sortByKeyIndices = - Radix.runByKeysStandard clContext workGroupSize + let assignValues = + ClArray.assignOption2 clContext workGroupSize predicate + + let scatter = + Scatter.lastOccurrence clContext workGroupSize + + fun (processor: MailboxProcessor<_>) (firstValues: ClArray<'a>) (secondValues: ClArray<'b>) (columns: Indices) -> + + let positions = + getBitmap processor DeviceOnly firstValues secondValues + + let resultLength = + (prefixSum processor positions) + .ToHostAndFree(processor) + + if resultLength = 0 then None + else + let resultIndices = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) + + scatter processor positions columns resultIndices + + let resultValues = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) + + assignValues processor firstValues secondValues positions resultValues + + Some (resultValues, resultIndices) + + let sortByColumns (clContext: ClContext) workGroupSize = let sortByKeyValues = Radix.runByKeysStandard clContext workGroupSize @@ -220,38 +188,22 @@ module Expand = let sortKeys = Radix.standardRunKeysOnly clContext workGroupSize - fun (processor: MailboxProcessor<_>) (values: ClArray<'a>) (columns: Indices) (rows: Indices) -> + fun (processor: MailboxProcessor<_>) (values: ClArray<'a>) (columns: Indices) -> // sort by columns - let valuesSortedByColumns = + let sortedValues = sortByKeyValues processor DeviceOnly columns values - let rowsSortedByColumns = - sortByKeyIndices processor DeviceOnly columns rows - let sortedColumns = sortKeys processor columns - // sort by rows - let valuesSortedByRows = - sortByKeyValues processor DeviceOnly rowsSortedByColumns valuesSortedByColumns - - let columnsSortedByRows = - sortByKeyIndices processor DeviceOnly rowsSortedByColumns sortedColumns - - let sortedRows = sortKeys processor rowsSortedByColumns - - valuesSortedByColumns.Free processor - rowsSortedByColumns.Free processor - sortedColumns.Free processor - - valuesSortedByRows, columnsSortedByRows, sortedRows + sortedValues, sortedColumns let reduce (clContext: ClContext) workGroupSize opAdd = let reduce = - Reduce.ByKey2D.segmentSequentialOption clContext workGroupSize opAdd + Reduce.ByKey.segmentSequentialOption clContext workGroupSize opAdd // TODO(tests) let getUniqueBitmap = - ClArray.getUniqueBitmap2LastOccurrence clContext workGroupSize + ClArray.getUniqueBitmapLastOccurrence clContext workGroupSize let prefixSum = PrefixSum.standardExcludeInplace clContext workGroupSize @@ -259,10 +211,10 @@ module Expand = let idScatter = Scatter.initFirsOccurrence Map.id clContext workGroupSize - fun (processor: MailboxProcessor<_>) allocationMode (values: ClArray<'a>) (columns: Indices) (rows: Indices) -> + fun (processor: MailboxProcessor<_>) allocationMode (values: ClArray<'a>) (columns: Indices) -> let bitmap = - getUniqueBitmap processor DeviceOnly columns rows + getUniqueBitmap processor DeviceOnly columns let uniqueKeysCount = (prefixSum processor bitmap) @@ -275,15 +227,14 @@ module Expand = bitmap.Free processor - let reducedColumns, reducedRows, reducedValues = // by size variance TODO() - reduce processor allocationMode uniqueKeysCount offsets columns rows values + let reduceResult = // by size variance TODO() + reduce processor allocationMode uniqueKeysCount offsets columns values offsets.Free processor - reducedValues, reducedColumns, reducedRows - - let run (clContext: ClContext) workGroupSize opAdd opMul = + reduceResult + let runRow (clContext: ClContext) workGroupSize opAdd opMul = let getSegmentPointers = getSegmentPointers clContext workGroupSize @@ -291,43 +242,74 @@ module Expand = let multiply = multiply clContext workGroupSize opMul - let sort = - sortByColumnsAndRows clContext workGroupSize + let sort = sortByColumns clContext workGroupSize let reduce = reduce clContext workGroupSize opAdd - fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix.CSR<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> - + // left matrix last --- for curring + fun (processor: MailboxProcessor<_>) allocationMode (rightMatrix: ClMatrix.CSR<'b>) (leftMatrixRowsLengths: Indices) (leftMatrixRow: ClVector.Sparse<'a>) -> + // TODO(sort in range) + // required right matrix lengths let length, segmentPointers = - getSegmentPointers processor leftMatrix rightMatrix + getSegmentPointers processor leftMatrixRow leftMatrixRowsLengths // expand - let leftMatrixValues, rightMatrixValues, columns, rows = - expand processor length segmentPointers leftMatrix rightMatrix + let leftMatrixValues, rightMatrixValues, columns = + expand processor length segmentPointers leftMatrixRow rightMatrix - // multiply - let resultValues, resultColumns, resultRows = - multiply processor leftMatrixValues rightMatrixValues columns rows + // multiplication + let mulResult = + multiply processor leftMatrixValues rightMatrixValues columns leftMatrixValues.Free processor rightMatrixValues.Free processor columns.Free processor - rows.Free processor - // sort - let sortedValues, sortedColumns, sortedRows = - sort processor resultValues resultColumns resultRows + // check multiplication result + mulResult + |> Option.bind (fun (resultValues, resultColumns) -> + // sort + let sortedValues, sortedColumns = + sort processor resultValues resultColumns + + resultValues.Free processor + resultColumns.Free processor + + let reduceResult = + reduce processor allocationMode sortedValues sortedColumns + + sortedValues.Free processor + sortedColumns.Free processor + + // create sparse vector (TODO(empty vector)) + reduceResult + |> Option.bind (fun (values, columns) -> + { Context = clContext + Indices = columns + Values = values + Size = rightMatrix.ColumnCount } + |> Some)) + + let run<'a, 'b, 'c when 'a : struct and 'b : struct and 'c : struct> + (clContext: ClContext) + workGroupSize + opAdd + (opMul: Expr<'a -> 'b -> 'c option>) = - resultValues.Free processor - resultColumns.Free processor - resultRows.Free processor + let getRowsLength = + getRowsLength clContext workGroupSize - // addition - let reducedValues, reducedColumns, reducedRows = - reduce processor allocationMode sortedValues sortedColumns sortedRows + let split = CSR.Matrix.byRowsLazy clContext workGroupSize + + let runRow = runRow clContext workGroupSize opAdd opMul + + fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix.CSR<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> + + let rightMatrixRowsLengths = + getRowsLength processor rightMatrix - sortedValues.Free processor - sortedColumns.Free processor - sortedRows.Free processor + let runRow = + runRow processor allocationMode rightMatrix rightMatrixRowsLengths - reducedValues, reducedColumns, reducedRows + split processor allocationMode leftMatrix + |> Seq.map (fun lazyRow -> Option.bind runRow lazyRow.Value) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/SpGEMM/Masked.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Masked.fs similarity index 99% rename from src/GraphBLAS-sharp.Backend/Matrix/CSR/SpGEMM/Masked.fs rename to src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Masked.fs index b4f3fcbd..c1b0d2a9 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/SpGEMM/Masked.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Masked.fs @@ -1,4 +1,4 @@ -namespace GraphBLAS.FSharp.Backend.Matrix.CSR.SpGeMM +namespace GraphBLAS.FSharp.Backend.Matrix.SpGeMM open GraphBLAS.FSharp.Backend.Common open Brahma.FSharp diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs b/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs index 774b41f2..561f8993 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs @@ -23,3 +23,11 @@ module Convert = match rightItem with | Some _ -> (%op) leftItem None | None -> (%op) leftItem (Some value) @> + + let map2ToMapLeftNone (op: Expr<'a option -> 'b option -> 'c option>) = + <@ fun rightItem -> (%op) None rightItem @> + + let map2ToMapRightNone (op: Expr<'a option -> 'b option -> 'c option>) = + <@ fun leftItem -> (%op) leftItem None @> + + let map2ToNoneNone (op: Expr<'a option -> 'b option -> 'c option>) = <@ (%op) None None @> diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs index 8405ec60..7cb77404 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs @@ -12,7 +12,7 @@ open GraphBLAS.FSharp.Backend.Objects.ClCell open GraphBLAS.FSharp.Backend.Common module internal Map = - let preparePositions<'a, 'b> (clContext: ClContext) workGroupSize opAdd = + let private preparePositions<'a, 'b> (clContext: ClContext) workGroupSize opAdd = // we can decrease memory requirements by two pass map (like choose) let preparePositions (op: Expr<'a option -> 'b option>) = <@ fun (ndRange: Range1D) dataLength vectorLength (values: ClArray<'a>) (indices: ClArray) (resultBitmap: ClArray) (resultValues: ClArray<'b>) (resultIndices: ClArray) -> @@ -71,8 +71,8 @@ module internal Map = let run<'a, 'b when 'a: struct and 'b: struct and 'b: equality> (clContext: ClContext) - (opAdd: Expr<'a option -> 'b option>) workGroupSize + (opAdd: Expr<'a option -> 'b option>) = let preparePositions = @@ -97,7 +97,7 @@ module internal Map = Values = resultValues Size = vector.Size } - module AtLeastOne = + module OnlySome = let run (clContext: ClContext) workGroupSize op = let getOptionBitmap = @@ -110,6 +110,8 @@ module internal Map = let scatter = Scatter.lastOccurrence clContext workGroupSize + let setOption = ClArray.assignOption clContext workGroupSize op + fun (processor: MailboxProcessor<_>) allocationMode (vector: ClVector.Sparse<'a>) -> let bitmap = @@ -119,4 +121,17 @@ module internal Map = (prefixSum processor bitmap) .ToHostAndFree processor - () + let resultValues = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + setOption processor vector.Values bitmap resultValues + + let resultIndices = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + + scatter processor vector.Indices bitmap resultIndices + + { Context = clContext + Indices = resultIndices + Values = resultValues + Size = vector.Size } diff --git a/src/GraphBLAS-sharp.Backend/paket.references b/src/GraphBLAS-sharp.Backend/paket.references index 6f164f37..6051b92a 100644 --- a/src/GraphBLAS-sharp.Backend/paket.references +++ b/src/GraphBLAS-sharp.Backend/paket.references @@ -1,4 +1,4 @@ FSharp.Core Microsoft.SourceLink.GitHub - Brahma.FSharp +FSharp.Quotations.Evaluator \ No newline at end of file diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs new file mode 100644 index 00000000..12e868de --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs @@ -0,0 +1,51 @@ +module GraphBLAS.FSharp.Tests.Backned.Common.ClArray.Assign + +open Expecto +open Brahma.FSharp +open GraphBLAS.FSharp.Backend.Common +open GraphBLAS.FSharp.Test +open GraphBLAS.FSharp.Tests +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions + +let context = Context.defaultContext.ClContext + +let processor = Context.defaultContext.Queue + +let config = + { Utils.defaultConfig with + arbitrary = [ typeof ] } + +let makeTest<'a> isEqual testFun (source: 'a []) (target: 'a []) = + + if source.Length > 0 + && target.Length > 0 then + + let clSource = context.CreateClArray source + let clTarget = context.CreateClArray target + let targetPosition = 0 + + testFun processor clSource targetPosition clTarget + + let actual = clSource.ToHostAndFree processor + clTarget.Free processor + + // write to target --- target expected + Array.blit source 0 target targetPosition source.Length + + "Results should be the same" + |> Utils.compareArrays isEqual actual target + +let createTest<'a when 'a : equality> isEqual = + ClArray.assign context Utils.defaultWorkGroupSize + |> makeTest isEqual + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let tests = + [ createTest (=) + + if Utils.isFloat64Available context.ClDevice then + createTest (=) + + createTest (=) + createTest (=) ] + |> testList "Assign" diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/chunkBySize.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/chunkBySize.fs rename to tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs new file mode 100644 index 00000000..fd44df09 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs @@ -0,0 +1,48 @@ +module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.Concat + +open Expecto +open Brahma.FSharp +open GraphBLAS.FSharp.Backend.Common +open GraphBLAS.FSharp.Test +open GraphBLAS.FSharp.Tests +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +open GraphBLAS.FSharp.Backend.Objects.ClContext + +let context = Context.defaultContext.ClContext + +let processor = Context.defaultContext.Queue + +let config = + { Utils.defaultConfig with + arbitrary = [ typeof ] } + +let makeTest<'a> isEqual testFun (arrays: 'a [] seq) = + + if Seq.length arrays > 0 then + + let clArrays = arrays |> Seq.map context.CreateClArray + + let clActual: ClArray<'a> = testFun processor HostInterop clArrays + + // release + let actual = clActual.ToHostAndFree processor + clArrays |> Seq.iter (fun array -> array.Free processor) + + let expected = Seq.concat arrays |> Seq.toArray + + "Results must be the same" + |> Utils.compareArrays isEqual actual expected + +let createTest<'a> isEqual = + ClArray.concat context Utils.defaultWorkGroupSize + |> makeTest isEqual + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let tests = + [ createTest (=) + + if Utils.isFloat64Available context.ClDevice then + createTest (=) + + createTest (=) + createTest (=) ] diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index 258d8e67..50905bde 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -25,7 +25,9 @@ - + + + From 7d1ee0e3c2b1211dee490fb05185281eb32662c3 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sun, 16 Apr 2023 18:13:03 +0300 Subject: [PATCH 08/44] add: Reduce.ByKey.Option.sequintialSegments --- src/GraphBLAS-sharp.Backend/Common/Sum.fs | 349 ++++++------ src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 45 +- .../Matrix/SpGeMM/Expand.fs | 2 +- .../Objects/MatrixExtensions.fs | 1 + .../Common/ClArray/Fill.fs | 49 ++ .../Common/ClArray/Pairwise.fs | 52 ++ .../Common/Reduce/ReduceByKey.fs | 139 ++++- tests/GraphBLAS-sharp.Tests/Generators.fs | 77 +++ .../GraphBLAS-sharp.Tests.fsproj | 2 + tests/GraphBLAS-sharp.Tests/Helpers.fs | 2 +- .../Matrix/SpGeMM/Expand.fs | 532 +++++++++--------- tests/GraphBLAS-sharp.Tests/Program.fs | 2 +- 12 files changed, 757 insertions(+), 495 deletions(-) create mode 100644 tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs create mode 100644 tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs diff --git a/src/GraphBLAS-sharp.Backend/Common/Sum.fs b/src/GraphBLAS-sharp.Backend/Common/Sum.fs index 40b8d8c9..df2b3c1b 100644 --- a/src/GraphBLAS-sharp.Backend/Common/Sum.fs +++ b/src/GraphBLAS-sharp.Backend/Common/Sum.fs @@ -472,118 +472,121 @@ module Reduce = reducedValues, reducedKeys - /// - /// Reduces values by key. Each segment is reduced by one work item. - /// - /// ClContext. - /// Work group size. - /// Operation for reducing values. - /// - /// The length of the result must be calculated in advance. - /// - let segmentSequentialOption<'a> (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a option>) = + module Option = + /// + /// Reduces values by key. Each segment is reduced by one work item. + /// + /// ClContext. + /// Work group size. + /// Operation for reducing values. + /// + /// The length of the result must be calculated in advance. + /// + let segmentSequential<'a> (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a option>) = - let kernel = - <@ fun (ndRange: Range1D) uniqueKeyCount keysLength (offsets: ClArray) (keys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (firstReducedKeys: ClArray) (resultPositions: ClArray) -> + let kernel = + <@ fun (ndRange: Range1D) uniqueKeyCount keysLength (offsets: ClArray) (keys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (firstReducedKeys: ClArray) (resultPositions: ClArray) -> - let gid = ndRange.GlobalID0 + let gid = ndRange.GlobalID0 - if gid < uniqueKeyCount then - let startPosition = offsets.[gid] + if gid < uniqueKeyCount then + let startPosition = offsets.[gid] - let firstSourceKey = keys.[startPosition] + let firstSourceKey = keys.[startPosition] - let mutable sum = Some values.[startPosition] + let mutable sum = Some values.[startPosition] - let mutable currentPosition = startPosition + 1 + let mutable currentPosition = startPosition + 1 - while currentPosition < keysLength - && firstSourceKey = keys.[currentPosition] do + while currentPosition < keysLength + && firstSourceKey = keys.[currentPosition] do - match sum with - | Some value -> - let result = - ((%reduceOp) value values.[currentPosition]) // brahma error + match sum with + | Some value -> + let result = + ((%reduceOp) value values.[currentPosition]) // brahma error - sum <- result - | None -> sum <- Some values.[currentPosition] + sum <- result + | None -> sum <- Some values.[currentPosition] - currentPosition <- currentPosition + 1 + currentPosition <- currentPosition + 1 - match sum with - | Some value -> - reducedValues.[gid] <- value - resultPositions.[gid] <- 1 - | None -> resultPositions.[gid] <- 0 + match sum with + | Some value -> + reducedValues.[gid] <- value + resultPositions.[gid] <- 1 + | None -> resultPositions.[gid] <- 0 - firstReducedKeys.[gid] <- firstSourceKey @> + firstReducedKeys.[gid] <- firstSourceKey @> - let kernel = clContext.Compile kernel + let kernel = clContext.Compile kernel - let scatterData = - Scatter.lastOccurrence clContext workGroupSize + let scatterData = + Scatter.lastOccurrence clContext workGroupSize - let scatterIndices = - Scatter.lastOccurrence clContext workGroupSize + let scatterIndices = + Scatter.lastOccurrence clContext workGroupSize - let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + let prefixSum = + PrefixSum.standardExcludeInplace clContext workGroupSize - fun (processor: MailboxProcessor<_>) allocationMode (resultLength: int) (offsets: ClArray) (keys: ClArray) (values: ClArray<'a>) -> + fun (processor: MailboxProcessor<_>) allocationMode (resultLength: int) (offsets: ClArray) (keys: ClArray) (values: ClArray<'a>) -> - let reducedValues = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + let reducedValues = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) - let reducedKeys = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + let reducedKeys = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) - let resultPositions = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) + let resultPositions = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) - let ndRange = - Range1D.CreateValid(resultLength, workGroupSize) + let ndRange = + Range1D.CreateValid(resultLength, workGroupSize) - let kernel = kernel.GetKernel() + let kernel = kernel.GetKernel() - processor.Post( - Msg.MsgSetArguments - (fun () -> - kernel.KernelFunc - ndRange - resultLength - keys.Length - offsets - keys - values - reducedValues - reducedKeys - resultPositions) - ) + processor.Post( + Msg.MsgSetArguments + (fun () -> + kernel.KernelFunc + ndRange + resultLength + keys.Length + offsets + keys + values + reducedValues + reducedKeys + resultPositions) + ) - processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - let resultLength = - (prefixSum processor resultPositions) - .ToHostAndFree processor + let resultLength = + (prefixSum processor resultPositions) + .ToHostAndFree processor - if resultLength = 0 then None - else - let resultValues = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + if resultLength = 0 then None + else + // write values + let resultValues = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - scatterData processor resultPositions reducedValues resultValues + scatterData processor resultPositions reducedValues resultValues - reducedValues.Free processor + reducedValues.Free processor - let resultKeys = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + // write keys + let resultKeys = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - scatterIndices processor resultPositions reducedKeys resultKeys // TODO(mb error) + scatterIndices processor resultPositions reducedKeys resultKeys - reducedKeys.Free processor - resultPositions.Free processor + reducedKeys.Free processor + resultPositions.Free processor - Some (resultValues, reducedKeys) + Some (resultValues, resultKeys) module ByKey2D = /// /// Reduce an array of values by 2D keys using a single work item. @@ -739,131 +742,135 @@ module Reduce = reducedValues, firstReducedKeys, secondReducedKeys - /// - /// Reduces values by key. Each segment is reduced by one work item. - /// - /// ClContext. - /// Work group size. - /// Operation for reducing values. - /// - /// The length of the result must be calculated in advance. - /// - let segmentSequentialOption<'a> (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a option>) = + module Option = + /// + /// Reduces values by key. Each segment is reduced by one work item. + /// + /// ClContext. + /// Work group size. + /// Operation for reducing values. + /// + /// The length of the result must be calculated in advance. + /// + let segmentSequential<'a> (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a option>) = - let kernel = - <@ fun (ndRange: Range1D) uniqueKeyCount keysLength (offsets: ClArray) (firstKeys: ClArray) (secondKeys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (firstReducedKeys: ClArray) (secondReducedKeys: ClArray) (resultPositions: ClArray) -> + let kernel = + <@ fun (ndRange: Range1D) uniqueKeyCount keysLength (offsets: ClArray) (firstKeys: ClArray) (secondKeys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (firstReducedKeys: ClArray) (secondReducedKeys: ClArray) (resultPositions: ClArray) -> - let gid = ndRange.GlobalID0 + let gid = ndRange.GlobalID0 - if gid < uniqueKeyCount then - let startPosition = offsets.[gid] + if gid < uniqueKeyCount then + let startPosition = offsets.[gid] - let firstSourceKey = firstKeys.[startPosition] - let secondSourceKey = secondKeys.[startPosition] + let firstSourceKey = firstKeys.[startPosition] + let secondSourceKey = secondKeys.[startPosition] - let mutable sum = Some values.[startPosition] + let mutable sum = Some values.[startPosition] - let mutable currentPosition = startPosition + 1 + let mutable currentPosition = startPosition + 1 - while currentPosition < keysLength - && firstSourceKey = firstKeys.[currentPosition] - && secondSourceKey = secondKeys.[currentPosition] do + while currentPosition < keysLength + && firstSourceKey = firstKeys.[currentPosition] + && secondSourceKey = secondKeys.[currentPosition] do - match sum with - | Some value -> - let result = - ((%reduceOp) value values.[currentPosition]) // brahma error + match sum with + | Some value -> + let result = + ((%reduceOp) value values.[currentPosition]) // brahma error - sum <- result - | None -> sum <- Some values.[currentPosition] + sum <- result + | None -> sum <- Some values.[currentPosition] - currentPosition <- currentPosition + 1 + currentPosition <- currentPosition + 1 - match sum with - | Some value -> - reducedValues.[gid] <- value - resultPositions.[gid] <- 1 - | None -> resultPositions.[gid] <- 0 + match sum with + | Some value -> + reducedValues.[gid] <- value + resultPositions.[gid] <- 1 + | None -> resultPositions.[gid] <- 0 - firstReducedKeys.[gid] <- firstSourceKey - secondReducedKeys.[gid] <- secondSourceKey @> + firstReducedKeys.[gid] <- firstSourceKey + secondReducedKeys.[gid] <- secondSourceKey @> - let kernel = clContext.Compile kernel + let kernel = clContext.Compile kernel - let scatterData = - Scatter.lastOccurrence clContext workGroupSize + let scatterData = + Scatter.lastOccurrence clContext workGroupSize - let scatterIndices = - Scatter.lastOccurrence clContext workGroupSize + let scatterIndices = + Scatter.lastOccurrence clContext workGroupSize - let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + let prefixSum = + PrefixSum.standardExcludeInplace clContext workGroupSize - fun (processor: MailboxProcessor<_>) allocationMode (resultLength: int) (offsets: ClArray) (firstKeys: ClArray) (secondKeys: ClArray) (values: ClArray<'a>) -> + fun (processor: MailboxProcessor<_>) allocationMode (resultLength: int) (offsets: ClArray) (firstKeys: ClArray) (secondKeys: ClArray) (values: ClArray<'a>) -> - let reducedValues = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + let reducedValues = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - let firstReducedKeys = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + let firstReducedKeys = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - let secondReducedKeys = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + let secondReducedKeys = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - let resultPositions = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) + let resultPositions = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) - let ndRange = - Range1D.CreateValid(resultLength, workGroupSize) + let ndRange = + Range1D.CreateValid(resultLength, workGroupSize) - let kernel = kernel.GetKernel() + let kernel = kernel.GetKernel() - processor.Post( - Msg.MsgSetArguments - (fun () -> - kernel.KernelFunc - ndRange - resultLength - firstKeys.Length - offsets - firstKeys - secondKeys - values - reducedValues - firstReducedKeys - secondReducedKeys - resultPositions) - ) + processor.Post( + Msg.MsgSetArguments + (fun () -> + kernel.KernelFunc + ndRange + resultLength + firstKeys.Length + offsets + firstKeys + secondKeys + values + reducedValues + firstReducedKeys + secondReducedKeys + resultPositions) + ) - processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - let resultLength = - (prefixSum processor resultPositions) - .ToHostAndFree processor + let resultLength = + (prefixSum processor resultPositions) + .ToHostAndFree processor - if resultLength = 0 then None - else - let resultValues = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + if resultLength = 0 then None + else + // write value + let resultValues = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - scatterData processor resultPositions reducedValues resultValues + scatterData processor resultPositions reducedValues resultValues - reducedValues.Free processor + reducedValues.Free processor - let resultFirstKeys = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + // write first keys + let resultFirstKeys = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - scatterIndices processor resultPositions firstReducedKeys resultFirstKeys + scatterIndices processor resultPositions firstReducedKeys resultFirstKeys - firstReducedKeys.Free processor + firstReducedKeys.Free processor - let resultSecondKeys = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + // write second keys + let resultSecondKeys = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - scatterIndices processor resultPositions secondReducedKeys resultSecondKeys + scatterIndices processor resultPositions secondReducedKeys resultSecondKeys - secondReducedKeys.Free processor + secondReducedKeys.Free processor - resultPositions.Free processor + resultPositions.Free processor - Some (resultValues, resultFirstKeys, resultSecondKeys) + Some (resultValues, resultFirstKeys, resultSecondKeys) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index 2c15238d..baf88f47 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -99,9 +99,6 @@ module Matrix = let transposeInPlace = CSR.Matrix.transposeInPlace clContext workGroupSize - let rowsToCSR = - Rows.Matrix.toCSR clContext workGroupSize - fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.COO m -> @@ -112,7 +109,7 @@ module Matrix = m.ToCSR |> transposeInPlace processor allocationMode |> ClMatrix.CSR - | _ -> failwith "not yet supported" + | _ -> failwith "Not yet implemented" /// /// Creates a new matrix, represented in COO format, that is equal to the given one. @@ -156,9 +153,6 @@ module Matrix = let transposeInPlace = COO.Matrix.transposeInplace clContext workGroupSize - let rowsToCOO = - Rows.Matrix.toCOO clContext workGroupSize - fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.COO _ -> matrix @@ -170,7 +164,7 @@ module Matrix = |> toCOOInPlace processor allocationMode |> transposeInPlace processor |> ClMatrix.COO - | _ -> failwith "not yet supported" + | _ -> failwith "Not yet implemented" /// /// Creates a new matrix, represented in CSC format, that is equal to the given one. @@ -199,7 +193,7 @@ module Matrix = |> COOtoCSR processor allocationMode) .ToCSC |> ClMatrix.CSC - | _ -> failwith "not yet supported" + | _ -> failwith "Not yet implemented" /// /// Returns the matrix, represented in CSC format, that is equal to the given one. @@ -245,6 +239,7 @@ module Matrix = | ClMatrix.CSC m -> (mapCSR processor allocationMode m.ToCSR).ToCSC |> ClMatrix.CSC + | _ -> failwith "Not yet implemented" let map2 (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) workGroupSize = // TODO() let map2COO = @@ -395,19 +390,19 @@ module Matrix = | ClMatrix.CSR m1, ClMatrix.CSC m2, ClMatrix.COO mask -> runCSRnCSC queue m1 m2 mask |> ClMatrix.COO | _ -> failwith "Matrix formats are not matching" - let expand - (clContext: ClContext) - workGroupSize - (opAdd: Expr<'c -> 'c -> 'c option>) - (opMul: Expr<'a -> 'b -> 'c option>) - = - - let run = - SpGeMM.Expand.run clContext workGroupSize opAdd opMul - - fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix<'a>) (rightMatrix: ClMatrix<'b>) -> - match leftMatrix, rightMatrix with - | ClMatrix.CSR leftMatrix, ClMatrix.CSR rightMatrix -> - run processor allocationMode leftMatrix rightMatrix - |> ClMatrix.COO - | _ -> failwith "Matrix formats are not matching" + // let expand // TODO() + // (clContext: ClContext) + // workGroupSize + // (opAdd: Expr<'c -> 'c -> 'c option>) + // (opMul: Expr<'a -> 'b -> 'c option>) + // = + // + // let run = + // SpGeMM.Expand.run clContext workGroupSize opAdd opMul + // + // fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix<'a>) (rightMatrix: ClMatrix<'b>) -> + // match leftMatrix, rightMatrix with + // | ClMatrix.CSR leftMatrix, ClMatrix.CSR rightMatrix -> + // run processor allocationMode leftMatrix rightMatrix + // |> ClMatrix.COO + // | _ -> failwith "Matrix formats are not matching" diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index d4b8cda6..194461eb 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -200,7 +200,7 @@ module Expand = let reduce (clContext: ClContext) workGroupSize opAdd = let reduce = - Reduce.ByKey.segmentSequentialOption clContext workGroupSize opAdd // TODO(tests) + Reduce.ByKey.Option.segmentSequential clContext workGroupSize opAdd let getUniqueBitmap = ClArray.getUniqueBitmapLastOccurrence clContext workGroupSize diff --git a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs index b30ff16e..f3019cce 100644 --- a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs +++ b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs @@ -68,3 +68,4 @@ module MatrixExtensions = Values = values } Matrix.CSC result + | _ -> failwith "Not yet implemented" diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs new file mode 100644 index 00000000..34c8b991 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs @@ -0,0 +1,49 @@ +module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.Fill + +open Expecto +open Brahma.FSharp +open GraphBLAS.FSharp.Backend.Common +open GraphBLAS.FSharp.Test +open GraphBLAS.FSharp.Tests +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +open GraphBLAS.FSharp.Backend.Objects.ClContext + +let context = Context.defaultContext.ClContext + +let processor = Context.defaultContext.Queue + +let config = + { Utils.defaultConfig with + arbitrary = [ typeof ] } + +let makeTest<'a> isEqual testFun (value: 'a, targetIndex, count, target: 'a [] ) = + + if target.Length > 0 then + + let clTarget = context.CreateClArray target + let clValue = context.CreateClCell value + + testFun processor clValue 0 0 clTarget + + // release + let actual = clTarget.ToHostAndFree processor + + // write to target + Array.fill target targetIndex count value + + "Results must be the same" + |> Utils.compareArrays isEqual actual target + +let createTest<'a> isEqual = + ClArray.fill context Utils.defaultWorkGroupSize + |> makeTest isEqual + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let tests = + [ createTest (=) + + if Utils.isFloat64Available context.ClDevice then + createTest (=) + + createTest (=) + createTest (=) ] diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs new file mode 100644 index 00000000..5d35eae6 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs @@ -0,0 +1,52 @@ +module GraphBLAS.FSharp.Tests.Common.Backend.ClArray.Pairwise + +open Expecto +open Brahma.FSharp +open GraphBLAS.FSharp.Backend.Common +open GraphBLAS.FSharp.Test +open GraphBLAS.FSharp.Tests +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +open GraphBLAS.FSharp.Backend.Objects.ClContext + +let context = Context.defaultContext.ClContext + +let processor = Context.defaultContext.Queue + +let config = + { Utils.defaultConfig with + arbitrary = [ typeof ] } + +let makeTest<'a> isEqual testFun (array: 'a [] ) = + if array.Length > 0 then + + let clArray = context.CreateClArray array + + let (clFirstActual: ClArray<_>), (clSecondActual: ClArray<_>) + = testFun processor HostInterop clArray + + let firstActual = clFirstActual.ToHostAndFree processor + let secondActual = clSecondActual.ToHostAndFree processor + + let firstExpected, secondExpected = + Array.pairwise array + |> Array.unzip + + "First results must be the same" + |> Utils.compareArrays isEqual firstActual firstExpected + + "Second results must be the same" + |> Utils.compareArrays isEqual secondActual secondExpected + +let createTest<'a> isEqual = + ClArray.pairwise context Utils.defaultWorkGroupSize + |> makeTest isEqual + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let tests = + [ createTest (=) + + if Utils.isFloat64Available context.ClDevice then + createTest (=) + + createTest (=) + createTest (=) ] diff --git a/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs b/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs index 09e0b21a..9226fd9b 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs @@ -49,7 +49,7 @@ let makeTest isEqual reduce reduceOp (arrayAndKeys: (int * 'a) []) = let resultLength = Array.length <| Array.distinct keys - let clActualKeys, clActualValues: ClArray * ClArray<'a> = + let clActualValues, clActualKeys: ClArray<'a> * ClArray = reduce processor HostInterop resultLength clKeys clValues clValues.Free processor @@ -155,7 +155,7 @@ let makeTestSequentialSegments isEqual reduce reduceOp (valuesAndKeys: (int * 'a let clValues = context.CreateClArrayWithSpecificAllocationMode(DeviceOnly, values) - let clReducedKeys, clReducedValues: ClArray * ClArray<'a> = + let clReducedValues, clReducedKeys: ClArray<'a> * ClArray = reduce processor DeviceOnly resultLength clOffsets clKeys clValues let reducedKeys = clReducedKeys.ToHostAndFree processor @@ -232,7 +232,7 @@ let makeTest2D isEqual reduce reduceOp (array: (int * int * 'a) []) = Array.length <| Array.distinctBy (fun (fst, snd, _) -> (fst, snd)) array - let clFirstActualKeys, clSecondActualKeys, clActualValues: ClArray * ClArray * ClArray<'a> = + let clActualValues, clFirstActualKeys, clSecondActualKeys: ClArray<'a> * ClArray * ClArray = reduce processor HostInterop resultLength clFirstKeys clSecondKeys clValues clValues.Free processor @@ -257,7 +257,7 @@ let createTestSequential2D<'a> (isEqual: 'a -> 'a -> bool) reduceOp reduceOpQ = makeTest2D isEqual reduce reduceOp |> testPropertyWithConfig { config with - arbitrary = [ typeof ] + arbitrary = [ typeof ] endSize = 10 } $"test on {typeof<'a>}" @@ -316,7 +316,7 @@ let makeTestSequentialSegments2D isEqual reduce reduceOp (array: (int * int * 'a let clValues = context.CreateClArrayWithSpecificAllocationMode(DeviceOnly, values) - let clFirstActualKeys, clSecondActualKeys, clReducedValues: ClArray * ClArray * ClArray<'a> = + let clReducedValues, clFirstActualKeys, clSecondActualKeys: ClArray<'a> * ClArray * ClArray = reduce processor DeviceOnly resultLength clOffsets clFirstKeys clSecondKeys clValues let reducedFirsKeys = @@ -336,7 +336,7 @@ let createTestSequentialSegments2D<'a> (isEqual: 'a -> 'a -> bool) reduceOp redu makeTestSequentialSegments2D isEqual reduce reduceOp |> testPropertyWithConfig { config with - arbitrary = [ typeof ] } + arbitrary = [ typeof ] } $"test on {typeof<'a>}" let sequentialSegment2DTests = @@ -366,15 +366,92 @@ let sequentialSegment2DTests = testList "Sequential segments 2D" [ addTests; mulTests ] -let checkResult2DOption isEqual firstActualKeys secondActualKeys actualValues firstKeys secondKeys values reduceOp = - - let reduceOp left right = +// segments sequential Option +let createReduceOp reduceOp left right = match left, right with | Some left, Some right -> reduceOp left right | Some value, None | None, Some value -> Some value | _ -> None +let checkResultOption isEqual keys values reduceOp actual = + + let reduceOp = createReduceOp reduceOp + + let expectedKeys, expectedValues = + Array.zip keys values + |> Array.groupBy fst + |> Array.map (fun (key, array) -> key, Array.map snd array) + |> Array.map + (fun (key, array) -> + Array.map Some array + |> Array.reduce reduceOp + |> fun result -> key, result) + |> Array.choose + (fun (key, value) -> + match value with + | Some value -> Some(key, value) + | _ -> None) + |> Array.unzip + + match actual with + | Some (actualValues, actualKeys) -> + "First keys must be the same" + |> Utils.compareArrays (=) actualKeys expectedKeys + + "Values must the same" + |> Utils.compareArrays isEqual actualValues expectedValues + | None -> + Expect.isTrue (expectedValues.Length = 0) "Result should be Some _" + +let testOption<'a> isEqual reduceOp testFun (array: (int * 'a) []) = + if array.Length > 0 then + let array = Array.sortBy fst array + + let offsets = getOffsets array + + let keys, values = Array.unzip array + + let clOffsets = + context.CreateClArrayWithSpecificAllocationMode(HostInterop, offsets) + + let clKeys = + context.CreateClArrayWithSpecificAllocationMode(DeviceOnly, keys) + + let clValues = + context.CreateClArrayWithSpecificAllocationMode(DeviceOnly, values) + + testFun processor HostInterop offsets.Length clOffsets clKeys clValues + |> Option.bind (fun ((clActualValues, clActualKeys): ClArray<_> * ClArray<_>) -> + let actualValues = clActualValues.ToHostAndFree processor + let actualKeys = clActualKeys.ToHostAndFree processor + + Some (actualValues, actualKeys)) + |> checkResultOption isEqual keys values reduceOp + +let createTestOption (isEqual: 'a -> 'a -> bool) (reduceOpQ, reduceOp) = + Reduce.ByKey.Option.segmentSequential context Utils.defaultWorkGroupSize reduceOpQ + |> testOption<'a> isEqual reduceOp + |> testPropertyWithConfig + { config with + arbitrary = [ typeof ] } + $"test on {typeof<'a>}" + +let testsSegmentsSequentialOption = + [ createTestOption (=) ArithmeticOperations.intAdd + + if Utils.isFloat64Available context.ClDevice then + createTestOption Utils.floatIsEqual ArithmeticOperations.floatAdd + + createTestOption Utils.float32IsEqual ArithmeticOperations.float32Add + createTestOption (=) ArithmeticOperations.boolAdd ] + |> testList "option" + + +// segments sequential Option 2D +let checkResult2DOption isEqual firstKeys secondKeys values reduceOp actual = + let reduceOp = createReduceOp reduceOp + let expectedFirstKeys, expectedSecondKeys, expectedValues = let keys = Array.zip firstKeys secondKeys @@ -393,16 +470,19 @@ let checkResult2DOption isEqual firstActualKeys secondActualKeys actualValues fi | _ -> None) |> Array.unzip3 - "First keys must be the same" - |> Utils.compareArrays (=) firstActualKeys expectedFirstKeys + match actual with + | Some (actualValues, firstActualKeys, secondActualKeys) -> + "First keys must be the same" + |> Utils.compareArrays (=) firstActualKeys expectedFirstKeys - "Second keys must be the same" - |> Utils.compareArrays (=) secondActualKeys expectedSecondKeys + "Second keys must be the same" + |> Utils.compareArrays (=) secondActualKeys expectedSecondKeys - "Values must the same" - |> Utils.compareArrays isEqual actualValues expectedValues + "Values must the same" + |> Utils.compareArrays isEqual actualValues expectedValues + | None -> Expect.isTrue (expectedValues.Length = 0) "Result should be Some _" -let test2DOption<'a> isEqual reduce reduceOp (array: (int * int * 'a) []) = +let test2DOption<'a> isEqual reduceOp reduce (array: (int * int * 'a) []) = if array.Length > 0 then let array = Array.sortBy (fun (fst, snd, _) -> fst, snd) array @@ -423,27 +503,25 @@ let test2DOption<'a> isEqual reduce reduceOp (array: (int * int * 'a) []) = let clValues = context.CreateClArrayWithSpecificAllocationMode(DeviceOnly, values) - let clFirstActualKeys, clSecondActualKeys, clReducedValues: ClArray * ClArray * ClArray<'a> = - reduce processor DeviceOnly offsets.Length clOffsets clFirstKeys clSecondKeys clValues + reduce processor DeviceOnly offsets.Length clOffsets clFirstKeys clSecondKeys clValues + |> Option.bind (fun ((clReducedValues, clFirstActualKeys, clSecondActualKeys): ClArray<'a> * ClArray * ClArray) -> + let reducedFirstKeys = + clFirstActualKeys.ToHostAndFree processor - let reducedFirsKeys = - clFirstActualKeys.ToHostAndFree processor + let reducedSecondKeys = + clSecondActualKeys.ToHostAndFree processor - let reducesSecondKeys = - clSecondActualKeys.ToHostAndFree processor - - let reducedValues = clReducedValues.ToHostAndFree processor + let reducedValues = clReducedValues.ToHostAndFree processor - checkResult2DOption isEqual reducedFirsKeys reducesSecondKeys reducedValues firstKeys secondKeys values reduceOp + Some (reducedValues, reducedFirstKeys, reducedSecondKeys)) + |> checkResult2DOption isEqual firstKeys secondKeys values reduceOp let createTest2DOption (isEqual: 'a -> 'a -> bool) (reduceOpQ, reduceOp) = - let reduce = - Reduce.ByKey2D.segmentSequentialOption context Utils.defaultWorkGroupSize reduceOpQ - - test2DOption<'a> isEqual reduce reduceOp + Reduce.ByKey2D.Option.segmentSequential context Utils.defaultWorkGroupSize reduceOpQ + |> test2DOption<'a> isEqual reduceOp |> testPropertyWithConfig { config with - arbitrary = [ typeof ] } + arbitrary = [ typeof ] } $"test on {typeof<'a>}" let testsSegmentsSequential2DOption = @@ -464,4 +542,5 @@ let allTests = sequentialSegmentTests sequential2DTest sequentialSegment2DTests + testsSegmentsSequentialOption testsSegmentsSequential2DOption ] diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index c45a6f6c..37ec7d81 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -511,6 +511,83 @@ module Generators = |> Arb.fromGen type ArrayOfDistinctKeys() = + static let arrayOfDistinctKeysGenerator (keysGenerator: Gen<'n>) (valuesGenerator: Gen<'a>) = + let tuplesGenerator = + Gen.zip + <| keysGenerator + <| valuesGenerator + + gen { + let! length = Gen.sized <| fun size -> Gen.choose (1, size) + + let! array = Gen.arrayOfLength <| length <| tuplesGenerator + + return Array.distinctBy fst array + } + + static member IntType() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| Arb.generate + |> Arb.fromGen + + static member FloatType() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| (Arb.Default.NormalFloat() + |> Arb.toGen + |> Gen.map float) + |> Arb.fromGen + + static member Float32Type() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| (normalFloat32Generator <| System.Random()) + |> Arb.fromGen + + static member SByteType() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| Arb.generate + |> Arb.fromGen + + static member ByteType() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| Arb.generate + |> Arb.fromGen + + static member Int16Type() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| Arb.generate + |> Arb.fromGen + + static member UInt16Type() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| Arb.generate + |> Arb.fromGen + + static member Int32Type() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| Arb.generate + |> Arb.fromGen + + static member UInt32Type() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| Arb.generate + |> Arb.fromGen + + static member BoolType() = + arrayOfDistinctKeysGenerator + <| Arb.generate + <| Arb.generate + |> Arb.fromGen + + type ArrayOfDistinctKeys2D() = static let arrayOfDistinctKeysGenerator (keysGenerator: Gen<'n>) (valuesGenerator: Gen<'a>) = let tuplesGenerator = Gen.zip3 diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index 50905bde..5493767f 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -28,6 +28,8 @@ + + diff --git a/tests/GraphBLAS-sharp.Tests/Helpers.fs b/tests/GraphBLAS-sharp.Tests/Helpers.fs index 829d9e65..d39742c7 100644 --- a/tests/GraphBLAS-sharp.Tests/Helpers.fs +++ b/tests/GraphBLAS-sharp.Tests/Helpers.fs @@ -26,7 +26,7 @@ module Utils = typeof typeof typeof - typeof + typeof typeof typeof typeof diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs index 00ce048d..38d70b6c 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs @@ -1,266 +1,266 @@ -module GraphBLAS.FSharp.Tests.Matrix.SpGeMM.Expand - -open Expecto -open GraphBLAS.FSharp.Backend.Matrix.CSR.SpGeMM -open GraphBLAS.FSharp.Backend.Quotes -open GraphBLAS.FSharp.Test -open Microsoft.FSharp.Collections -open GraphBLAS.FSharp.Backend -open GraphBLAS.FSharp.Backend.Matrix -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Tests -open GraphBLAS.FSharp.Tests.Backend -open GraphBLAS.FSharp.Objects -open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions -open Brahma.FSharp -open GraphBLAS.FSharp.Backend.Objects.ClContext -open GraphBLAS.FSharp.Objects.MatrixExtensions - -let context = Context.defaultContext.ClContext - -let processor = Context.defaultContext.Queue - -let config = - { Utils.defaultConfig with - arbitrary = [ typeof ] - endSize = 100 - maxTest = 100 } - -let createCSRMatrix array isZero = - Utils.createMatrixFromArray2D CSR array isZero - |> Utils.castMatrixToCSR - -let getSegmentsPointers (leftMatrix: Matrix.CSR<'a>) (rightMatrix: Matrix.CSR<'b>) = - Array.map - (fun item -> - rightMatrix.RowPointers.[item + 1] - - rightMatrix.RowPointers.[item]) - leftMatrix.ColumnIndices - |> HostPrimitives.prefixSumExclude 0 (+) - -let makeTest isZero testFun (leftArray: 'a [,], rightArray: 'a [,]) = - - let leftMatrix = createCSRMatrix leftArray isZero - - let rightMatrix = createCSRMatrix rightArray isZero - - if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then - - let clLeftMatrix = leftMatrix.ToDevice context - - let clRightMatrix = rightMatrix.ToDevice context - - let actualLength, (clActual: ClArray) = - testFun processor clLeftMatrix clRightMatrix - - clLeftMatrix.Dispose processor - clRightMatrix.Dispose processor - - let actualPointers = clActual.ToHostAndFree processor - - let expectedPointers, expectedLength = - getSegmentsPointers leftMatrix rightMatrix - - "Results lengths must be the same" - |> Expect.equal actualLength expectedLength - - "Result pointers must be the same" - |> Expect.sequenceEqual actualPointers expectedPointers - -let createTest<'a when 'a: struct> (isZero: 'a -> bool) = - - let testFun = - Expand.getSegmentPointers context Utils.defaultWorkGroupSize - - makeTest isZero testFun - |> testPropertyWithConfig config $"test on {typeof<'a>}" - -let getSegmentsTests = - [ createTest ((=) 0) - - if Utils.isFloat64Available context.ClDevice then - createTest ((=) 0.0) - - createTest ((=) 0f) - createTest ((=) false) - createTest ((=) 0uy) ] - |> testList "get segment pointers" - -let expand length segmentPointers (leftMatrix: Matrix.CSR<'a>) (rightMatrix: Matrix.CSR<'b>) = - let extendPointers pointers = - Array.pairwise pointers - |> Array.map (fun (fst, snd) -> snd - fst) - |> Array.mapi (fun index length -> Array.create length index) - |> Array.concat - - let segmentsLengths = - Array.append segmentPointers [| length |] - |> Array.pairwise - |> Array.map (fun (fst, snd) -> snd - fst) - - let leftMatrixValues, expectedRows = - let tripleFst (fst, _, _) = fst - - Array.zip3 segmentsLengths leftMatrix.Values - <| extendPointers leftMatrix.RowPointers - // select items each segment length not zero - |> Array.filter (tripleFst >> ((=) 0) >> not) - |> Array.collect (fun (length, value, rowIndex) -> Array.create length (value, rowIndex)) - |> Array.unzip - - let rightMatrixValues, expectedColumns = - let valuesAndColumns = - Array.zip rightMatrix.Values rightMatrix.ColumnIndices - - Array.map2 - (fun column length -> - let rowStart = rightMatrix.RowPointers.[column] - Array.take length valuesAndColumns.[rowStart..]) - leftMatrix.ColumnIndices - segmentsLengths - |> Array.concat - |> Array.unzip - - leftMatrixValues, rightMatrixValues, expectedColumns, expectedRows - -let makeExpandTest isEqual zero testFun (leftArray: 'a [,], rightArray: 'a [,]) = - - let leftMatrix = - createCSRMatrix leftArray <| isEqual zero - - let rightMatrix = - createCSRMatrix rightArray <| isEqual zero - - if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then - - let segmentPointers, length = - getSegmentsPointers leftMatrix rightMatrix - - let clLeftMatrix = leftMatrix.ToDevice context - let clRightMatrix = rightMatrix.ToDevice context - let clSegmentPointers = context.CreateClArray segmentPointers - - let ((clActualLeftValues: ClArray<'a>), - (clActualRightValues: ClArray<'a>), - (clActualColumns: ClArray), - (clActualRows: ClArray)) = - testFun processor length clSegmentPointers clLeftMatrix clRightMatrix - - clLeftMatrix.Dispose processor - clRightMatrix.Dispose processor - clSegmentPointers.Free processor - - let actualLeftValues = - clActualLeftValues.ToHostAndFree processor - - let actualRightValues = - clActualRightValues.ToHostAndFree processor - - let actualColumns = clActualColumns.ToHostAndFree processor - let actualRows = clActualRows.ToHostAndFree processor - - let expectedLeftMatrixValues, expectedRightMatrixValues, expectedColumns, expectedRows = - expand length segmentPointers leftMatrix rightMatrix - - "Left values must be the same" - |> Utils.compareArrays isEqual actualLeftValues expectedLeftMatrixValues - - "Right values must be the same" - |> Utils.compareArrays isEqual actualRightValues expectedRightMatrixValues - - "Columns must be the same" - |> Utils.compareArrays (=) actualColumns expectedColumns - - "Rows must be the same" - |> Utils.compareArrays (=) actualRows expectedRows - -let createExpandTest isEqual (zero: 'a) testFun = - - let testFun = - testFun context Utils.defaultWorkGroupSize - - makeExpandTest isEqual zero testFun - |> testPropertyWithConfig config $"test on %A{typeof<'a>}" - -// expand phase tests -let expandTests = - [ createExpandTest (=) 0 Expand.expand - - if Utils.isFloat64Available context.ClDevice then - createExpandTest Utils.floatIsEqual 0.0 Expand.expand - - createExpandTest Utils.float32IsEqual 0f Expand.expand - createExpandTest (=) false Expand.expand - createExpandTest (=) 0uy Expand.expand ] - |> testList "Expand.expand" - -let checkGeneralResult zero isEqual (actualMatrix: Matrix<'a>) mul add (leftArray: 'a [,]) (rightArray: 'a [,]) = - - let expected = - HostPrimitives.array2DMultiplication zero mul add leftArray rightArray - |> fun array -> Utils.createMatrixFromArray2D COO array (isEqual zero) - - match actualMatrix, expected with - | Matrix.COO actualMatrix, Matrix.COO expected -> - - "Values must be the same" - |> Utils.compareArrays isEqual actualMatrix.Values expected.Values - - "Columns must be the same" - |> Utils.compareArrays (=) actualMatrix.Columns expected.Columns - - "Rows must be the same" - |> Utils.compareArrays (=) actualMatrix.Rows expected.Rows - | _ -> failwith "Matrix format are not matching" - -let makeGeneralTest zero isEqual opMul opAdd testFun (leftArray: 'a [,], rightArray: 'a [,]) = - - let leftMatrix = - Utils.createMatrixFromArray2D CSR leftArray (isEqual zero) - - let rightMatrix = - Utils.createMatrixFromArray2D CSR rightArray (isEqual zero) - - if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then - try - let clLeftMatrix = leftMatrix.ToDevice context - let clRightMatrix = rightMatrix.ToDevice context - - let (clMatrixActual: ClMatrix<_>) = - testFun processor HostInterop clLeftMatrix clRightMatrix - - let matrixActual = clMatrixActual.ToHost processor - clMatrixActual.Dispose processor - - checkGeneralResult zero isEqual matrixActual opMul opAdd leftArray rightArray - with - | ex when ex.Message = "InvalidBufferSize" -> () - | _ -> reraise () - -let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = - - let testFun = - testFun context Utils.defaultWorkGroupSize opAddQ opMulQ - - makeGeneralTest zero isEqual opMul opAdd testFun - |> testPropertyWithConfig config $"test on %A{typeof<'a>}" - -let generalTests = - [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand - - if Utils.isFloat64Available context.ClDevice then - createGeneralTest - 0.0 - Utils.floatIsEqual - ArithmeticOperations.floatAdd - ArithmeticOperations.floatMul - Matrix.SpGeMM.expand - - createGeneralTest - 0.0f - Utils.float32IsEqual - ArithmeticOperations.float32Add - ArithmeticOperations.float32Mul - Matrix.SpGeMM.expand - createGeneralTest false (=) ArithmeticOperations.boolAdd ArithmeticOperations.boolMul Matrix.SpGeMM.expand ] - |> testList "general" + module GraphBLAS.FSharp.Tests.Matrix.SpGeMM.Expand +// TODO() +// open Expecto +// open GraphBLAS.FSharp.Backend.Matrix.CSR.SpGeMM +// open GraphBLAS.FSharp.Backend.Quotes +// open GraphBLAS.FSharp.Test +// open Microsoft.FSharp.Collections +// open GraphBLAS.FSharp.Backend +// open GraphBLAS.FSharp.Backend.Matrix +// open GraphBLAS.FSharp.Backend.Objects +// open GraphBLAS.FSharp.Tests +// open GraphBLAS.FSharp.Tests.Backend +// open GraphBLAS.FSharp.Objects +// open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +// open Brahma.FSharp +// open GraphBLAS.FSharp.Backend.Objects.ClContext +// open GraphBLAS.FSharp.Objects.MatrixExtensions +// +// let context = Context.defaultContext.ClContext +// +// let processor = Context.defaultContext.Queue +// +// let config = +// { Utils.defaultConfig with +// arbitrary = [ typeof ] +// endSize = 100 +// maxTest = 100 } +// +// let createCSRMatrix array isZero = +// Utils.createMatrixFromArray2D CSR array isZero +// |> Utils.castMatrixToCSR +// +// let getSegmentsPointers (leftMatrix: Matrix.CSR<'a>) (rightMatrix: Matrix.CSR<'b>) = +// Array.map +// (fun item -> +// rightMatrix.RowPointers.[item + 1] +// - rightMatrix.RowPointers.[item]) +// leftMatrix.ColumnIndices +// |> HostPrimitives.prefixSumExclude 0 (+) +// +// let makeTest isZero testFun (leftArray: 'a [,], rightArray: 'a [,]) = +// +// let leftMatrix = createCSRMatrix leftArray isZero +// +// let rightMatrix = createCSRMatrix rightArray isZero +// +// if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then +// +// let clLeftMatrix = leftMatrix.ToDevice context +// +// let clRightMatrix = rightMatrix.ToDevice context +// +// let actualLength, (clActual: ClArray) = +// testFun processor clLeftMatrix clRightMatrix +// +// clLeftMatrix.Dispose processor +// clRightMatrix.Dispose processor +// +// let actualPointers = clActual.ToHostAndFree processor +// +// let expectedPointers, expectedLength = +// getSegmentsPointers leftMatrix rightMatrix +// +// "Results lengths must be the same" +// |> Expect.equal actualLength expectedLength +// +// "Result pointers must be the same" +// |> Expect.sequenceEqual actualPointers expectedPointers +// +// let createTest<'a when 'a: struct> (isZero: 'a -> bool) = +// +// let testFun = +// Expand.getSegmentPointers context Utils.defaultWorkGroupSize +// +// makeTest isZero testFun +// |> testPropertyWithConfig config $"test on {typeof<'a>}" +// +// let getSegmentsTests = +// [ createTest ((=) 0) +// +// if Utils.isFloat64Available context.ClDevice then +// createTest ((=) 0.0) +// +// createTest ((=) 0f) +// createTest ((=) false) +// createTest ((=) 0uy) ] +// |> testList "get segment pointers" +// +// let expand length segmentPointers (leftMatrix: Matrix.CSR<'a>) (rightMatrix: Matrix.CSR<'b>) = +// let extendPointers pointers = +// Array.pairwise pointers +// |> Array.map (fun (fst, snd) -> snd - fst) +// |> Array.mapi (fun index length -> Array.create length index) +// |> Array.concat +// +// let segmentsLengths = +// Array.append segmentPointers [| length |] +// |> Array.pairwise +// |> Array.map (fun (fst, snd) -> snd - fst) +// +// let leftMatrixValues, expectedRows = +// let tripleFst (fst, _, _) = fst +// +// Array.zip3 segmentsLengths leftMatrix.Values +// <| extendPointers leftMatrix.RowPointers +// // select items each segment length not zero +// |> Array.filter (tripleFst >> ((=) 0) >> not) +// |> Array.collect (fun (length, value, rowIndex) -> Array.create length (value, rowIndex)) +// |> Array.unzip +// +// let rightMatrixValues, expectedColumns = +// let valuesAndColumns = +// Array.zip rightMatrix.Values rightMatrix.ColumnIndices +// +// Array.map2 +// (fun column length -> +// let rowStart = rightMatrix.RowPointers.[column] +// Array.take length valuesAndColumns.[rowStart..]) +// leftMatrix.ColumnIndices +// segmentsLengths +// |> Array.concat +// |> Array.unzip +// +// leftMatrixValues, rightMatrixValues, expectedColumns, expectedRows +// +// let makeExpandTest isEqual zero testFun (leftArray: 'a [,], rightArray: 'a [,]) = +// +// let leftMatrix = +// createCSRMatrix leftArray <| isEqual zero +// +// let rightMatrix = +// createCSRMatrix rightArray <| isEqual zero +// +// if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then +// +// let segmentPointers, length = +// getSegmentsPointers leftMatrix rightMatrix +// +// let clLeftMatrix = leftMatrix.ToDevice context +// let clRightMatrix = rightMatrix.ToDevice context +// let clSegmentPointers = context.CreateClArray segmentPointers +// +// let ((clActualLeftValues: ClArray<'a>), +// (clActualRightValues: ClArray<'a>), +// (clActualColumns: ClArray), +// (clActualRows: ClArray)) = +// testFun processor length clSegmentPointers clLeftMatrix clRightMatrix +// +// clLeftMatrix.Dispose processor +// clRightMatrix.Dispose processor +// clSegmentPointers.Free processor +// +// let actualLeftValues = +// clActualLeftValues.ToHostAndFree processor +// +// let actualRightValues = +// clActualRightValues.ToHostAndFree processor +// +// let actualColumns = clActualColumns.ToHostAndFree processor +// let actualRows = clActualRows.ToHostAndFree processor +// +// let expectedLeftMatrixValues, expectedRightMatrixValues, expectedColumns, expectedRows = +// expand length segmentPointers leftMatrix rightMatrix +// +// "Left values must be the same" +// |> Utils.compareArrays isEqual actualLeftValues expectedLeftMatrixValues +// +// "Right values must be the same" +// |> Utils.compareArrays isEqual actualRightValues expectedRightMatrixValues +// +// "Columns must be the same" +// |> Utils.compareArrays (=) actualColumns expectedColumns +// +// "Rows must be the same" +// |> Utils.compareArrays (=) actualRows expectedRows +// +// let createExpandTest isEqual (zero: 'a) testFun = +// +// let testFun = +// testFun context Utils.defaultWorkGroupSize +// +// makeExpandTest isEqual zero testFun +// |> testPropertyWithConfig config $"test on %A{typeof<'a>}" +// +// // expand phase tests +// let expandTests = +// [ createExpandTest (=) 0 Expand.expand +// +// if Utils.isFloat64Available context.ClDevice then +// createExpandTest Utils.floatIsEqual 0.0 Expand.expand +// +// createExpandTest Utils.float32IsEqual 0f Expand.expand +// createExpandTest (=) false Expand.expand +// createExpandTest (=) 0uy Expand.expand ] +// |> testList "Expand.expand" +// +// let checkGeneralResult zero isEqual (actualMatrix: Matrix<'a>) mul add (leftArray: 'a [,]) (rightArray: 'a [,]) = +// +// let expected = +// HostPrimitives.array2DMultiplication zero mul add leftArray rightArray +// |> fun array -> Utils.createMatrixFromArray2D COO array (isEqual zero) +// +// match actualMatrix, expected with +// | Matrix.COO actualMatrix, Matrix.COO expected -> +// +// "Values must be the same" +// |> Utils.compareArrays isEqual actualMatrix.Values expected.Values +// +// "Columns must be the same" +// |> Utils.compareArrays (=) actualMatrix.Columns expected.Columns +// +// "Rows must be the same" +// |> Utils.compareArrays (=) actualMatrix.Rows expected.Rows +// | _ -> failwith "Matrix format are not matching" +// +// let makeGeneralTest zero isEqual opMul opAdd testFun (leftArray: 'a [,], rightArray: 'a [,]) = +// +// let leftMatrix = +// Utils.createMatrixFromArray2D CSR leftArray (isEqual zero) +// +// let rightMatrix = +// Utils.createMatrixFromArray2D CSR rightArray (isEqual zero) +// +// if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then +// try +// let clLeftMatrix = leftMatrix.ToDevice context +// let clRightMatrix = rightMatrix.ToDevice context +// +// let (clMatrixActual: ClMatrix<_>) = +// testFun processor HostInterop clLeftMatrix clRightMatrix +// +// let matrixActual = clMatrixActual.ToHost processor +// clMatrixActual.Dispose processor +// +// checkGeneralResult zero isEqual matrixActual opMul opAdd leftArray rightArray +// with +// | ex when ex.Message = "InvalidBufferSize" -> () +// | _ -> reraise () +// +// let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = +// +// let testFun = +// testFun context Utils.defaultWorkGroupSize opAddQ opMulQ +// +// makeGeneralTest zero isEqual opMul opAdd testFun +// |> testPropertyWithConfig config $"test on %A{typeof<'a>}" +// +// let generalTests = +// [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand +// +// if Utils.isFloat64Available context.ClDevice then +// createGeneralTest +// 0.0 +// Utils.floatIsEqual +// ArithmeticOperations.floatAdd +// ArithmeticOperations.floatMul +// Matrix.SpGeMM.expand +// +// createGeneralTest +// 0.0f +// Utils.float32IsEqual +// ArithmeticOperations.float32Add +// ArithmeticOperations.float32Mul +// Matrix.SpGeMM.expand +// createGeneralTest false (=) ArithmeticOperations.boolAdd ArithmeticOperations.boolMul Matrix.SpGeMM.expand ] +// |> testList "general" diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index bd0e20fc..aba6d04c 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -95,5 +95,5 @@ open GraphBLAS.FSharp.Tests [] let main argv = - Common.ClArray.chunkBySize.allTests + testList "lol" [ Common.Reduce.ByKey.testsSegmentsSequentialOption ] |> runTestsWithCLIArgs [] argv From 98d41dd61efa358bdf12002278f897d87aede53e Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sun, 16 Apr 2023 18:48:03 +0300 Subject: [PATCH 09/44] add: ClArray.assign tests --- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 18 +++--- .../Common/ClArray/Assign.fs | 17 +++--- .../Common/ClArray/ChunkBySize.fs | 2 +- tests/GraphBLAS-sharp.Tests/Generators.fs | 60 +++++++++++++++++++ tests/GraphBLAS-sharp.Tests/Program.fs | 2 +- 5 files changed, 79 insertions(+), 20 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index a10698e8..4008e720 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -562,34 +562,34 @@ module ClArray = let assign<'a> (clContext: ClContext) workGroupSize = let assign = - <@ fun (ndRange: Range1D) startPosition appendedArrayLength (inputArray: ClArray<'a>) (result: ClArray<'a>) -> + <@ fun (ndRange: Range1D) targetPosition sourceArrayLength (sourceArray: ClArray<'a>) (targetArray: ClArray<'a>) -> let gid = ndRange.GlobalID0 - let resultPosition = gid + startPosition + let resultPosition = gid + targetPosition - if gid < appendedArrayLength then + if gid < sourceArrayLength then - result.[resultPosition] <- inputArray.[gid] @> + targetArray.[resultPosition] <- sourceArray.[gid] @> let kernel = clContext.Compile assign - fun (processor: MailboxProcessor<_>) (targetArray: ClArray<'a>) startPosition (appendedArray: ClArray<'a>) -> - if startPosition < 0 then + fun (processor: MailboxProcessor<_>) (sourceArray: ClArray<'a>) targetPosition (targetArray: ClArray<'a>) -> + if targetPosition < 0 then failwith "The starting position cannot be less than zero" - if startPosition + appendedArray.Length > targetArray.Length then + if targetPosition + sourceArray.Length > targetArray.Length then failwith "The array should fit completely" let ndRange = - Range1D.CreateValid(appendedArray.Length, workGroupSize) + Range1D.CreateValid(targetArray.Length, workGroupSize) let kernel = kernel.GetKernel() processor.Post( Msg.MsgSetArguments (fun () -> - kernel.KernelFunc ndRange appendedArray.Length appendedArray.Length appendedArray targetArray) + kernel.KernelFunc ndRange targetPosition sourceArray.Length sourceArray targetArray) ) processor.Post(Msg.CreateRunMsg<_, _>(kernel)) diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs index 12e868de..65f2c0c5 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs @@ -1,4 +1,4 @@ -module GraphBLAS.FSharp.Tests.Backned.Common.ClArray.Assign +module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.Assign open Expecto open Brahma.FSharp @@ -13,21 +13,20 @@ let processor = Context.defaultContext.Queue let config = { Utils.defaultConfig with - arbitrary = [ typeof ] } + arbitrary = [ typeof ] } -let makeTest<'a> isEqual testFun (source: 'a []) (target: 'a []) = +let makeTest<'a> isEqual testFun (source: 'a [], target: 'a [], targetPosition: int) = if source.Length > 0 && target.Length > 0 then let clSource = context.CreateClArray source let clTarget = context.CreateClArray target - let targetPosition = 0 testFun processor clSource targetPosition clTarget - let actual = clSource.ToHostAndFree processor - clTarget.Free processor + clSource.Free processor + let actual = clTarget.ToHostAndFree processor // write to target --- target expected Array.blit source 0 target targetPosition source.Length @@ -37,15 +36,15 @@ let makeTest<'a> isEqual testFun (source: 'a []) (target: 'a []) = let createTest<'a when 'a : equality> isEqual = ClArray.assign context Utils.defaultWorkGroupSize - |> makeTest isEqual + |> makeTest<'a> isEqual |> testPropertyWithConfig config $"test on %A{typeof<'a>}" let tests = [ createTest (=) if Utils.isFloat64Available context.ClDevice then - createTest (=) + createTest Utils.floatIsEqual - createTest (=) + createTest Utils.float32IsEqual createTest (=) ] |> testList "Assign" diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs index 7f6e0b47..4501fa23 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs @@ -1,4 +1,4 @@ -module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.chunkBySize +module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.ChunkBySize open Expecto open Brahma.FSharp diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index 37ec7d81..63e07275 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -956,3 +956,63 @@ module Generators = static member BoolType() = arrayAndChunkPosition <| Arb.generate |> Arb.fromGen + + type AssignArray() = + static let pairOfVectorsOfEqualSize (valuesGenerator: Gen<'a>) = + gen { + let! targetArrayLength = Gen.sized <| fun size -> Gen.choose (2, size) + + let! targetArray = Gen.arrayOfLength targetArrayLength valuesGenerator + + let! sourceArrayLength = Gen.choose (1, targetArrayLength) + + let! sourceArray = Gen.arrayOfLength sourceArrayLength valuesGenerator + + let! startPosition = Gen.choose (0, targetArrayLength - sourceArrayLength) + + return (sourceArray, targetArray, startPosition) + } + + static member IntType() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member FloatType() = + pairOfVectorsOfEqualSize + <| (Arb.Default.NormalFloat() + |> Arb.toGen + |> Gen.map float) + |> Arb.fromGen + + static member Float32Type() = + pairOfVectorsOfEqualSize + <| (normalFloat32Generator <| System.Random()) + |> Arb.fromGen + + static member SByteType() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member ByteType() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member Int16Type() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member UInt16Type() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member Int32Type() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member UInt32Type() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member BoolType() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index aba6d04c..e1f76f9f 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -95,5 +95,5 @@ open GraphBLAS.FSharp.Tests [] let main argv = - testList "lol" [ Common.Reduce.ByKey.testsSegmentsSequentialOption ] + testList "lol" [ Common.ClArray.Assign.tests ] |> runTestsWithCLIArgs [] argv From 1f273d1d93835d0c772e829a922cf9b25bc4a884 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sun, 16 Apr 2023 19:10:33 +0300 Subject: [PATCH 10/44] add: ClArray.concat tests --- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 6 ++---- .../Common/ClArray/Concat.fs | 17 ++++++++--------- tests/GraphBLAS-sharp.Tests/Program.fs | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 4008e720..69b3ed5a 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -607,12 +607,10 @@ module ClArray = let result = clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - let assign = assign processor result - // write each array to result Seq.fold - (fun previousLength array -> - assign previousLength array + (fun previousLength (array: ClArray<_>) -> + assign processor array previousLength result previousLength + array.Length) 0 sourceArrays diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs index fd44df09..4e807e8f 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs @@ -3,7 +3,6 @@ module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.Concat open Expecto open Brahma.FSharp open GraphBLAS.FSharp.Backend.Common -open GraphBLAS.FSharp.Test open GraphBLAS.FSharp.Tests open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions open GraphBLAS.FSharp.Backend.Objects.ClContext @@ -12,13 +11,12 @@ let context = Context.defaultContext.ClContext let processor = Context.defaultContext.Queue -let config = - { Utils.defaultConfig with - arbitrary = [ typeof ] } +let config = Utils.defaultConfig -let makeTest<'a> isEqual testFun (arrays: 'a [] seq) = +let makeTest<'a> isEqual testFun (arrays: 'a [] []) = - if Seq.length arrays > 0 then + if Seq.length arrays > 0 + && arrays |> Seq.forall (fun array -> array.Length > 0) then let clArrays = arrays |> Seq.map context.CreateClArray @@ -35,14 +33,15 @@ let makeTest<'a> isEqual testFun (arrays: 'a [] seq) = let createTest<'a> isEqual = ClArray.concat context Utils.defaultWorkGroupSize - |> makeTest isEqual + |> makeTest<'a> isEqual |> testPropertyWithConfig config $"test on %A{typeof<'a>}" let tests = [ createTest (=) if Utils.isFloat64Available context.ClDevice then - createTest (=) + createTest Utils.floatIsEqual - createTest (=) + createTest Utils.float32IsEqual createTest (=) ] + |> testList "Concat" diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index e1f76f9f..a556294c 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -95,5 +95,5 @@ open GraphBLAS.FSharp.Tests [] let main argv = - testList "lol" [ Common.ClArray.Assign.tests ] + testList "lol" [ Common.ClArray.Concat.tests ] |> testSequenced |> runTestsWithCLIArgs [] argv From 830b2f9577fa79c37fb9401c842ddb5088b1cc7a Mon Sep 17 00:00:00 2001 From: IgorErin Date: Mon, 17 Apr 2023 10:14:22 +0300 Subject: [PATCH 11/44] wip: ClArray.pairwise --- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 55 +++++++++------- .../Matrix/SpGeMM/Expand.fs | 19 +++--- .../Common/ClArray/Fill.fs | 12 ++-- .../Common/ClArray/Pairwise.fs | 30 ++++----- tests/GraphBLAS-sharp.Tests/Generators.fs | 62 ++++++++++++++++++- tests/GraphBLAS-sharp.Tests/Program.fs | 2 +- 6 files changed, 125 insertions(+), 55 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 69b3ed5a..6fa25b54 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -621,35 +621,36 @@ module ClArray = let fill (clContext: ClContext) workGroupSize = let fill = - <@ fun (ndRange: Range1D) firstPosition endPosition (value: ClCell<'a>) (targetArray: ClArray<'a>) -> + <@ fun (ndRange: Range1D) firstPosition count (value: ClCell<'a>) (targetArray: ClArray<'a>) -> let gid = ndRange.GlobalID0 let writePosition = gid + firstPosition - if writePosition < endPosition then - + if gid < count then targetArray.[writePosition] <- value.Value @> let kernel = clContext.Compile fill fun (processor: MailboxProcessor<_>) value firstPosition count (targetArray: ClArray<'a>) -> - if firstPosition + count > targetArray.Length then - failwith "" + if count = 0 then () + else + if firstPosition + count > targetArray.Length then + failwith "" - if firstPosition < 0 then failwith "" - if count <= 0 then failwith "" // TODO() + if firstPosition < 0 then failwith "" + if count < 0 then failwith "" // TODO() - let ndRange = - Range1D.CreateValid(count, workGroupSize) + let ndRange = + Range1D.CreateValid(count, workGroupSize) - let kernel = kernel.GetKernel() + let kernel = kernel.GetKernel() - processor.Post( - Msg.MsgSetArguments - (fun () -> kernel.KernelFunc ndRange firstPosition (firstPosition + count) value targetArray) - ) + processor.Post( + Msg.MsgSetArguments + (fun () -> kernel.KernelFunc ndRange firstPosition count value targetArray) + ) - processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + processor.Post(Msg.CreateRunMsg<_, _>(kernel)) let pairwise (clContext: ClContext) workGroupSize = @@ -659,18 +660,26 @@ module ClArray = let incGather = Gather.runInit Map.inc clContext workGroupSize + let map = map2 clContext workGroupSize <@ fun first second -> (first, second) @> + fun (processor: MailboxProcessor<_>) allocationMode (values: ClArray<'a>) -> + if values.Length > 1 then + let resultLength = values.Length - 1 - let resultLength = values.Length - 1 + let firstItems = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - let firstItems = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + idGather processor values firstItems - idGather processor values firstItems + let secondItems = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - let secondItems = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + incGather processor values secondItems + + let result = map processor allocationMode firstItems secondItems - incGather processor values secondItems + firstItems.Free processor + secondItems.Free processor - firstItems, secondItems + Some result + else None diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index 194461eb..efab851d 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -26,15 +26,16 @@ module Expand = fun (processor: MailboxProcessor<_>) (matrix: ClMatrix.CSR<'b>) -> - let firstPointers, secondPointers = - pairwise processor DeviceOnly matrix.RowPointers - - let rowsLength = subtract processor DeviceOnly secondPointers firstPointers - - firstPointers.Free processor - secondPointers.Free processor - - rowsLength + // let firstPointers, secondPointers = + // pairwise processor DeviceOnly matrix.RowPointers + + // let rowsLength = subtract processor DeviceOnly secondPointers firstPointers + // + // firstPointers.Free processor + // secondPointers.Free processor + // + // rowsLength + clContext.CreateClArray [| |] let getSegmentPointers (clContext: ClContext) workGroupSize = diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs index 34c8b991..196d89f6 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs @@ -14,29 +14,28 @@ let processor = Context.defaultContext.Queue let config = { Utils.defaultConfig with - arbitrary = [ typeof ] } - -let makeTest<'a> isEqual testFun (value: 'a, targetIndex, count, target: 'a [] ) = + arbitrary = [ typeof ] } +let makeTest<'a> isEqual testFun (value: 'a, targetPosition, count, target: 'a [] ) = if target.Length > 0 then let clTarget = context.CreateClArray target let clValue = context.CreateClCell value - testFun processor clValue 0 0 clTarget + testFun processor clValue targetPosition count clTarget // release let actual = clTarget.ToHostAndFree processor // write to target - Array.fill target targetIndex count value + Array.fill target targetPosition count value "Results must be the same" |> Utils.compareArrays isEqual actual target let createTest<'a> isEqual = ClArray.fill context Utils.defaultWorkGroupSize - |> makeTest isEqual + |> makeTest<'a> isEqual |> testPropertyWithConfig config $"test on %A{typeof<'a>}" let tests = @@ -47,3 +46,4 @@ let tests = createTest (=) createTest (=) ] + |> testList "Fill" diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs index 5d35eae6..c78ac497 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs @@ -1,4 +1,4 @@ -module GraphBLAS.FSharp.Tests.Common.Backend.ClArray.Pairwise +module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.Pairwise open Expecto open Brahma.FSharp @@ -14,32 +14,31 @@ let processor = Context.defaultContext.Queue let config = { Utils.defaultConfig with - arbitrary = [ typeof ] } + arbitrary = [ typeof ] } let makeTest<'a> isEqual testFun (array: 'a [] ) = if array.Length > 0 then let clArray = context.CreateClArray array - let (clFirstActual: ClArray<_>), (clSecondActual: ClArray<_>) - = testFun processor HostInterop clArray + testFun processor HostInterop clArray + |> Option.bind (fun (clFirstActual: ClArray<_>, clSecondActual: ClArray<_>) -> + let firstActual = clFirstActual.ToHostAndFree processor + let secondActual = clSecondActual.ToHostAndFree processor - let firstActual = clFirstActual.ToHostAndFree processor - let secondActual = clSecondActual.ToHostAndFree processor + let firstExpected, secondExpected = Array.pairwise array |> Array.unzip - let firstExpected, secondExpected = - Array.pairwise array - |> Array.unzip + "First results must be the same" + |> Utils.compareArrays isEqual firstActual firstExpected - "First results must be the same" - |> Utils.compareArrays isEqual firstActual firstExpected - - "Second results must be the same" - |> Utils.compareArrays isEqual secondActual secondExpected + "Second results must be the same" + |> Utils.compareArrays isEqual secondActual secondExpected + None) + |> ignore let createTest<'a> isEqual = ClArray.pairwise context Utils.defaultWorkGroupSize - |> makeTest isEqual + |> makeTest<'a> isEqual |> testPropertyWithConfig config $"test on %A{typeof<'a>}" let tests = @@ -50,3 +49,4 @@ let tests = createTest (=) createTest (=) ] + |> testList "Pairwise" diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index 63e07275..aa84f71b 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -960,7 +960,7 @@ module Generators = type AssignArray() = static let pairOfVectorsOfEqualSize (valuesGenerator: Gen<'a>) = gen { - let! targetArrayLength = Gen.sized <| fun size -> Gen.choose (2, size) + let! targetArrayLength = Gen.sized <| fun size -> Gen.choose (2, size + 2) let! targetArray = Gen.arrayOfLength targetArrayLength valuesGenerator @@ -1016,3 +1016,63 @@ module Generators = static member BoolType() = pairOfVectorsOfEqualSize <| Arb.generate |> Arb.fromGen + + type Fill() = + static let pairOfVectorsOfEqualSize (valuesGenerator: Gen<'a>) = + gen { + let! value = valuesGenerator + + let! targetArrayLength = Gen.sized <| fun size -> Gen.choose(1, size + 1) + + let! targetArray = Gen.arrayOfLength targetArrayLength valuesGenerator + + let! targetPosition = Gen.choose (0, targetArrayLength) + + let! targetCount = Gen.choose(0, targetArrayLength - targetPosition) + + return (value, targetPosition, targetCount, targetArray) + } + + static member IntType() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member FloatType() = + pairOfVectorsOfEqualSize + <| (Arb.Default.NormalFloat() + |> Arb.toGen + |> Gen.map float) + |> Arb.fromGen + + static member Float32Type() = + pairOfVectorsOfEqualSize + <| (normalFloat32Generator <| System.Random()) + |> Arb.fromGen + + static member SByteType() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member ByteType() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member Int16Type() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member UInt16Type() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member Int32Type() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member UInt32Type() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen + + static member BoolType() = + pairOfVectorsOfEqualSize <| Arb.generate + |> Arb.fromGen diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index a556294c..19e04826 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -95,5 +95,5 @@ open GraphBLAS.FSharp.Tests [] let main argv = - testList "lol" [ Common.ClArray.Concat.tests ] |> testSequenced + testList "lol" [ Common.ClArray.Pairwise.tests ] |> testSequenced |> runTestsWithCLIArgs [] argv From 92b186f9be24f699a4e4056782932a12510afeb4 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Mon, 17 Apr 2023 10:16:49 +0300 Subject: [PATCH 12/44] add: ClArray.pairwise --- tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs index c78ac497..734087c1 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs @@ -22,9 +22,10 @@ let makeTest<'a> isEqual testFun (array: 'a [] ) = let clArray = context.CreateClArray array testFun processor HostInterop clArray - |> Option.bind (fun (clFirstActual: ClArray<_>, clSecondActual: ClArray<_>) -> - let firstActual = clFirstActual.ToHostAndFree processor - let secondActual = clSecondActual.ToHostAndFree processor + |> Option.bind (fun (actual: ClArray<_>) -> + let firstActual, secondActual = + actual.ToHostAndFree processor + |> Array.unzip let firstExpected, secondExpected = Array.pairwise array |> Array.unzip From 089e11ef603babec5dbfe0c2cb6b1f915621b9dd Mon Sep 17 00:00:00 2001 From: IgorErin Date: Mon, 17 Apr 2023 14:34:34 +0300 Subject: [PATCH 13/44] add: Matrix.Rows.Convert --- .../BenchmarksMxm.fs | 2 +- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 6 +- .../Matrix/COO/Matrix.fs | 38 +------- src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs | 2 +- .../Matrix/CSR/Map2.fs | 2 +- .../Matrix/CSR/Map2AtLeastOne.fs | 2 +- .../Matrix/CSR/Matrix.fs | 41 ++++++++- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 86 +++++++++++++------ .../Matrix/Rows/Matrix.fs | 77 ++++++----------- .../Matrix/SpGeMM/Expand.fs | 23 +---- src/GraphBLAS-sharp.Backend/Objects/Matrix.fs | 1 + src/GraphBLAS-sharp.Backend/Quotes/Map.fs | 2 + .../Vector/Sparse/SparseVector.fs | 21 ----- src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj | 2 +- src/GraphBLAS-sharp/Objects/Matrix.fs | 42 +++++++++ .../Objects/MatrixExtensions.fs | 86 ++++++------------- src/GraphBLAS-sharp/Objects/Vector.fs | 5 +- .../Objects/VectorExtensions.fs | 21 ++--- tests/GraphBLAS-sharp.Tests/Helpers.fs | 3 + tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs | 82 ++++++------------ tests/GraphBLAS-sharp.Tests/Program.fs | 2 +- 21 files changed, 249 insertions(+), 297 deletions(-) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs index f5c706d6..efbe86c9 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs @@ -75,7 +75,7 @@ type MxmBenchmarks<'elem when 'elem : struct>( member this.FunCSR2CSC = match funCSR2CSC with | None -> - let x = Matrix.toCSCInplace this.OclContext this.WorkGroupSize + let x = Matrix.toCSCInPlace this.OclContext this.WorkGroupSize funCSR2CSC <- Some x x | Some x -> x diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 6fa25b54..80e4f5a9 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -635,10 +635,10 @@ module ClArray = if count = 0 then () else if firstPosition + count > targetArray.Length then - failwith "" + failwith "The array should fit completely" - if firstPosition < 0 then failwith "" - if count < 0 then failwith "" // TODO() + if firstPosition < 0 then failwith "The starting position cannot be less than zero" + if count < 0 then failwith "The count cannot be less than zero" let ndRange = Range1D.CreateValid(count, workGroupSize) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs index 61006763..2230f815 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs @@ -107,7 +107,7 @@ module Matrix = Columns = cols Values = values } - let toCSRInplace (clContext: ClContext) workGroupSize = + let toCSRInPlace (clContext: ClContext) workGroupSize = let prepare = compressRows clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.COO<'a>) -> @@ -123,7 +123,7 @@ module Matrix = Columns = matrix.Columns Values = matrix.Values } - let transposeInplace (clContext: ClContext) workGroupSize = + let transposeInPlace (clContext: ClContext) workGroupSize = let sort = Sort.Bitonic.sortKeyValuesInplace clContext workGroupSize @@ -140,7 +140,7 @@ module Matrix = let transpose (clContext: ClContext) workGroupSize = - let transposeInplace = transposeInplace clContext workGroupSize + let transposeInPlace = transposeInPlace clContext workGroupSize let copy = ClArray.copy clContext workGroupSize @@ -154,34 +154,4 @@ module Matrix = Rows = copy queue allocationMode matrix.Rows Columns = copy queue allocationMode matrix.Columns Values = copyData queue allocationMode matrix.Values } - |> transposeInplace queue - - let concat (clContext: ClContext) workGroupSize = - - let concatValues = ClArray.concat clContext workGroupSize - - let concatIndices = ClArray.concat clContext workGroupSize - - fun (processor: MailboxProcessor<_>) allocationMode columnCount rowCount (matrices: ClMatrix.COO<'a> seq) -> - - let resultValues = - matrices - |> Seq.map (fun matrix -> matrix.Values) - |> concatValues processor allocationMode - - let resultColumns = - matrices - |> Seq.map (fun matrix -> matrix.Columns) - |> concatIndices processor allocationMode - - let resultRows = - matrices - |> Seq.map (fun matrix -> matrix.Rows) - |> concatIndices processor allocationMode - - { Context = clContext - RowCount = rowCount - ColumnCount = columnCount - Rows = resultRows - Columns = resultColumns - Values = resultValues } + |> transposeInPlace queue diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs index 67e73b93..018c027b 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs @@ -122,7 +122,7 @@ module internal Map = let mapToCOO = runToCOO clContext opAdd workGroupSize let toCSRInplace = - Matrix.toCSRInplace clContext workGroupSize + Matrix.toCSRInPlace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> mapToCOO queue allocationMode matrix diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs index b189da13..0d363dac 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs @@ -144,7 +144,7 @@ module internal Map2 = let map2ToCOO = runToCOO clContext opAdd workGroupSize let toCSRInplace = - Matrix.toCSRInplace clContext workGroupSize + Matrix.toCSRInPlace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrixLeft: ClMatrix.CSR<'a>) (matrixRight: ClMatrix.CSR<'b>) -> map2ToCOO queue allocationMode matrixLeft matrixRight diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs index 65bc2e42..3ec0a7be 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs @@ -339,7 +339,7 @@ module internal Map2AtLeastOne = let elementwiseToCOO = runToCOO clContext opAdd workGroupSize let toCSRInplace = - Matrix.toCSRInplace clContext workGroupSize + Matrix.toCSRInPlace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrixLeft: ClMatrix.CSR<'a>) (matrixRight: ClMatrix.CSR<'b>) -> elementwiseToCOO queue allocationMode matrixLeft matrixRight diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 1f7eadd8..05b77c11 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -82,10 +82,10 @@ module Matrix = let toCOOInPlace = toCOOInPlace clContext workGroupSize let transposeInPlace = - COO.Matrix.transposeInplace clContext workGroupSize + COO.Matrix.transposeInPlace clContext workGroupSize let toCSRInPlace = - COO.Matrix.toCSRInplace clContext workGroupSize + COO.Matrix.toCSRInPlace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> toCOOInPlace queue allocationMode matrix @@ -97,10 +97,10 @@ module Matrix = let toCOO = toCOO clContext workGroupSize let transposeInPlace = - COO.Matrix.transposeInplace clContext workGroupSize + COO.Matrix.transposeInPlace clContext workGroupSize let toCSRInPlace = - COO.Matrix.toCSRInplace clContext workGroupSize + COO.Matrix.toCSRInPlace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> toCOO queue allocationMode matrix @@ -148,3 +148,36 @@ module Matrix = runLazy processor allocationMode matrix |> Seq.map (fun lazyValue -> lazyValue.Value) |> Seq.toArray + + let toRows (clContext: ClContext) workGroupSize = + + let byRows = byRows clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> + let rows = byRows processor allocationMode matrix + + { Context = clContext + RowCount = matrix.RowCount + ColumnCount = matrix.ColumnCount + Rows = rows + NNZ = matrix.NNZ } + + let getRowsLength (clContext: ClContext) workGroupSize = + + let pairwise = ClArray.pairwise clContext workGroupSize + + let subtract = + ClArray.map clContext workGroupSize Map.pairSubtraction + + fun (processor: MailboxProcessor<_>) (matrix: ClMatrix.CSR<'b>) -> + let pointerPairs = + pairwise processor DeviceOnly matrix.RowPointers + // since row pointers length in matrix always >= 2 + |> Option.defaultWith (fun () -> + failwith "The state of the matrix is broken. The length of the rowPointers must be >= 2") + + let rowsLength = subtract processor DeviceOnly pointerPairs + + pointerPairs.Free processor + + rowsLength diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index baf88f47..d1b35a2a 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -94,7 +94,7 @@ module Matrix = ///Should be a power of 2 and greater than 1. let toCSRInPlace (clContext: ClContext) workGroupSize = let toCSRInPlace = - COO.Matrix.toCSRInplace clContext workGroupSize + COO.Matrix.toCSRInPlace clContext workGroupSize let transposeInPlace = CSR.Matrix.transposeInPlace clContext workGroupSize @@ -121,11 +121,11 @@ module Matrix = let copy = copy clContext workGroupSize - let transposeInplace = - COO.Matrix.transposeInplace clContext workGroupSize + let transposeInPlace = + COO.Matrix.transposeInPlace clContext workGroupSize - let rowsToCOO = - Rows.Matrix.toCOO clContext workGroupSize + let rowsToCSR = + Rows.Matrix.toCSR clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with @@ -134,10 +134,11 @@ module Matrix = | ClMatrix.CSC m -> m.ToCSR |> toCOO processor allocationMode - |> transposeInplace processor + |> transposeInPlace processor |> ClMatrix.COO | ClMatrix.Rows m -> - rowsToCOO processor allocationMode m + rowsToCSR processor allocationMode m + |> toCOO processor allocationMode |> ClMatrix.COO /// @@ -151,7 +152,7 @@ module Matrix = CSR.Matrix.toCOOInPlace clContext workGroupSize let transposeInPlace = - COO.Matrix.transposeInplace clContext workGroupSize + COO.Matrix.transposeInPlace clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with @@ -182,6 +183,8 @@ module Matrix = let transposeCOO = COO.Matrix.transpose clContext workGroupSize + let rowsToCSR = Rows.Matrix.toCSR clContext workGroupSize + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.CSC _ -> copy processor allocationMode matrix @@ -193,7 +196,11 @@ module Matrix = |> COOtoCSR processor allocationMode) .ToCSC |> ClMatrix.CSC - | _ -> failwith "Not yet implemented" + | ClMatrix.Rows m -> + rowsToCSR processor allocationMode m + |> transposeCSR processor allocationMode + |> fun m -> m.ToCSC + |> ClMatrix.CSC /// /// Returns the matrix, represented in CSC format, that is equal to the given one. @@ -201,29 +208,56 @@ module Matrix = /// ///OpenCL context. ///Should be a power of 2 and greater than 1. - let toCSCInplace (clContext: ClContext) workGroupSize = - let toCSRInplace = - COO.Matrix.toCSRInplace clContext workGroupSize + let toCSCInPlace (clContext: ClContext) workGroupSize = + let toCSRInPlace = + COO.Matrix.toCSRInPlace clContext workGroupSize - let transposeCSRInplace = + let transposeCSRInPlace = CSR.Matrix.transposeInPlace clContext workGroupSize - let transposeCOOInplace = - COO.Matrix.transposeInplace clContext workGroupSize + let transposeCOOInPlace = + COO.Matrix.transposeInPlace clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.CSC _ -> matrix | ClMatrix.CSR m -> - (transposeCSRInplace processor allocationMode m) + (transposeCSRInPlace processor allocationMode m) .ToCSC |> ClMatrix.CSC | ClMatrix.COO m -> - (transposeCOOInplace processor m - |> toCSRInplace processor allocationMode) + (transposeCOOInPlace processor m + |> toCSRInPlace processor allocationMode) .ToCSC |> ClMatrix.CSC - | _ -> failwith "not yet supported" + | _ -> failwith "Not yet implemented" + + let toRows (clContext: ClContext) workGroupSize = + + let copy = copy clContext workGroupSize + + let COOToCSR = COO.Matrix.toCSR clContext workGroupSize + + let transposeCSR = + CSR.Matrix.transposeInPlace clContext workGroupSize + + let CSRToRows = CSR.Matrix.toRows clContext workGroupSize + + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> + match matrix with + | ClMatrix.CSC m -> + m.ToCSR + |> transposeCSR processor allocationMode + |> CSRToRows processor allocationMode + |> ClMatrix.Rows + | ClMatrix.CSR m -> + CSRToRows processor allocationMode m + |> ClMatrix.Rows + | ClMatrix.COO m -> + COOToCSR processor allocationMode m + |> CSRToRows processor allocationMode + |> ClMatrix.Rows + | ClMatrix.Rows _ -> copy processor allocationMode matrix let map (clContext: ClContext) (opAdd: Expr<'a option -> 'b option>) workGroupSize = let mapCOO = @@ -241,7 +275,7 @@ module Matrix = |> ClMatrix.CSC | _ -> failwith "Not yet implemented" - let map2 (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) workGroupSize = // TODO() + let map2 (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) workGroupSize = let map2COO = COO.Matrix.map2 clContext opAdd workGroupSize @@ -291,7 +325,7 @@ module Matrix = CSR.Matrix.map2AtLeastOneToCOO clContext opAdd workGroupSize let transposeCOOInPlace = - COO.Matrix.transposeInplace clContext workGroupSize + COO.Matrix.transposeInPlace clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode matrix1 matrix2 -> match matrix1, matrix2 with @@ -322,14 +356,14 @@ module Matrix = ///Should be a power of 2 and greater than 1. let transposeInPlace (clContext: ClContext) workGroupSize = let COOTransposeInPlace = - COO.Matrix.transposeInplace clContext workGroupSize + COO.Matrix.transposeInPlace clContext workGroupSize fun (processor: MailboxProcessor<_>) matrix -> match matrix with | ClMatrix.COO m -> COOTransposeInPlace processor m |> ClMatrix.COO | ClMatrix.CSR m -> ClMatrix.CSC m.ToCSC | ClMatrix.CSC m -> ClMatrix.CSR m.ToCSR - | ClMatrix.Rows _ -> failwith "not yet supported" + | ClMatrix.Rows _ -> failwith "Not yet implemented" /// /// Transposes the given matrix and returns result as a new matrix. @@ -344,7 +378,7 @@ module Matrix = ///OpenCL context. ///Should be a power of 2 and greater than 1. let transpose (clContext: ClContext) workGroupSize = - let COOtranspose = + let COOTranspose = COO.Matrix.transpose clContext workGroupSize let copy = ClArray.copy clContext workGroupSize @@ -354,7 +388,7 @@ module Matrix = fun (processor: MailboxProcessor<_>) allocationMode matrix -> match matrix with | ClMatrix.COO m -> - COOtranspose processor allocationMode m + COOTranspose processor allocationMode m |> ClMatrix.COO | ClMatrix.CSR m -> { Context = m.Context @@ -372,7 +406,7 @@ module Matrix = Columns = copy processor allocationMode m.Rows Values = copyData processor allocationMode m.Values } |> ClMatrix.CSR - | ClMatrix.Rows _ -> failwith "not yet supported" + | ClMatrix.Rows _ -> failwith "Not yet implemented" module SpGeMM = let masked diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs index db3a986c..2f9a0a72 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs @@ -13,66 +13,37 @@ open FSharp.Quotations.Evaluator module Matrix = let toCSR (clContext: ClContext) workGroupSize = - let concatVectors = - Vector.Sparse.SparseVector.concat clContext workGroupSize + let concatIndices = ClArray.concat clContext workGroupSize + + let concatValues = ClArray.concat clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: Rows<'a>) -> - // create row pointers - let rowPointers = + let rowsPointers = matrix.Rows - |> Array.Parallel.map - (function - | None -> 0 - | Some array -> array.Size) - |> Array.scan (+) 0 // mb device prefix sum ??? - - let rowPointers = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, rowPointers) - - // compact columns and values - matrix.Rows - |> Array.Parallel.choose id - |> concatVectors processor allocationMode - |> fun vector -> - { Context = clContext - RowCount = matrix.RowCount - ColumnCount = matrix.ColumnCount - RowPointers = rowPointers - Columns = vector.Indices - Values = vector.Values } - - let toCOO (clContext: ClContext) workGroupSize = - - let create = ClArray.create clContext workGroupSize + |> Array.map (function None -> 0 | Some vector -> vector.Values.Length) + // prefix sum + |> Array.scan (+) 0 + |> fun pointers -> + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, pointers) - let concatMatrix = - COO.Matrix.concat clContext workGroupSize + let valuesByRows, columnsIndicesByRows = + matrix.Rows + |> Array.choose id + |> Array.map (fun vector -> vector.Values, vector.Indices) + |> Array.unzip - fun (processor: MailboxProcessor<_>) allocationMode (matrix: Rows<'a>) -> + let values = + concatValues processor allocationMode valuesByRows - let createMatrix (vector: ClVector.Sparse<_>) rows = - { Context = clContext - RowCount = matrix.RowCount - ColumnCount = matrix.ColumnCount - Rows = rows - Columns = vector.Indices - Values = vector.Values } + let columnsIndices = + concatIndices processor allocationMode columnsIndicesByRows - let indices, rowsVectors = - matrix.Rows - |> Array.Parallel.mapi - (fun index optionRow -> - (match optionRow with - | None -> None - | Some row -> Some(index, row))) - |> Array.Parallel.choose id - |> Array.unzip + { Context = clContext + RowCount = matrix.RowCount + ColumnCount = matrix.ColumnCount + RowPointers = rowsPointers + Columns = columnsIndices + Values = values } - // creat rows pointers - let rowsIndices = - (rowsVectors, indices) - ||> Array.map2 (fun array -> create processor allocationMode array.Values.Length) - Array.map2 createMatrix rowsVectors rowsIndices - |> concatMatrix processor allocationMode matrix.ColumnCount matrix.RowCount diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index efab851d..d061072e 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -18,25 +18,6 @@ type Indices = ClArray type Values<'a> = ClArray<'a> module Expand = - let getRowsLength (clContext: ClContext) workGroupSize = - let subtract = - ClArray.map2 clContext workGroupSize Map.subtraction - - let pairwise = ClArray.pairwise clContext workGroupSize - - fun (processor: MailboxProcessor<_>) (matrix: ClMatrix.CSR<'b>) -> - - // let firstPointers, secondPointers = - // pairwise processor DeviceOnly matrix.RowPointers - - // let rowsLength = subtract processor DeviceOnly secondPointers firstPointers - // - // firstPointers.Free processor - // secondPointers.Free processor - // - // rowsLength - clContext.CreateClArray [| |] - let getSegmentPointers (clContext: ClContext) workGroupSize = let gather = Gather.run clContext workGroupSize @@ -298,7 +279,7 @@ module Expand = (opMul: Expr<'a -> 'b -> 'c option>) = let getRowsLength = - getRowsLength clContext workGroupSize + CSR.Matrix.getRowsLength clContext workGroupSize let split = CSR.Matrix.byRowsLazy clContext workGroupSize @@ -314,3 +295,5 @@ module Expand = split processor allocationMode leftMatrix |> Seq.map (fun lazyRow -> Option.bind runRow lazyRow.Value) + |> Seq.toArray + diff --git a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs index 822b7c03..ebc7c81f 100644 --- a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs @@ -6,6 +6,7 @@ type MatrixFormat = | CSR | COO | CSC + | Rows module ClMatrix = type CSR<'elem when 'elem: struct> = diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Map.fs b/src/GraphBLAS-sharp.Backend/Quotes/Map.fs index 2f74a7c5..9cb476b3 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Map.fs @@ -30,6 +30,8 @@ module Map = let inc = <@ fun item -> item + 1 @> + let pairSubtraction = <@ fun (first, second) -> first - second @> + let subtraction = <@ fun first second -> first - second @> let fst () = <@ fun fst _ -> fst @> diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs index 4be224db..bf0a9e1a 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs @@ -68,24 +68,3 @@ module SparseVector = Reduce.reduce clContext workGroupSize opAdd fun (processor: MailboxProcessor<_>) (vector: ClVector.Sparse<'a>) -> reduce processor vector.Values - - let concat<'a> (clContext: ClContext) workGroupSize = - - let concatValues = ClArray.concat clContext workGroupSize - - let concatIndices = ClArray.concat clContext workGroupSize - - fun (processor: MailboxProcessor<_>) allocationMode (vectors: ClVector.Sparse<'a> seq) -> - - let resultValues = - Seq.map (fun vector -> vector.Values) vectors - |> concatValues processor allocationMode - - let resultIndices = - Seq.map (fun vector -> vector.Indices) vectors - |> concatIndices processor allocationMode - - { Context = clContext - Indices = resultIndices - Values = resultValues - Size = resultValues.Length } diff --git a/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj b/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj index 96e59d55..658f2876 100644 --- a/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj +++ b/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj @@ -18,9 +18,9 @@ + - diff --git a/src/GraphBLAS-sharp/Objects/Matrix.fs b/src/GraphBLAS-sharp/Objects/Matrix.fs index 5213e750..b064356a 100644 --- a/src/GraphBLAS-sharp/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp/Objects/Matrix.fs @@ -135,6 +135,43 @@ module Matrix = ColumnPointers = context.CreateClArray this.ColumnPointers Values = context.CreateClArray this.Values } + type Rows<'a when 'a : struct> = + { RowCount: int + ColumnCount: int + Rows: Vector.Sparse<'a> option [] + NNZ: int } + + static member FromArray2D(array: 'a [,], isZero: 'a -> bool) = + let mutable nnz = 0 + + let rows = + [ for i in 0 .. Array2D.length1 array - 1 do + let vector = Vector.Sparse.FromArray(array.[i, *], isZero) + + nnz <- nnz + vector.NNZ + + if vector.NNZ > 0 then Some vector + else None ] + |> Array.ofList + + { RowCount = Array2D.length1 array + ColumnCount = Array2D.length2 array + Rows = rows + NNZ = nnz } + + member this.ToDevice(context: ClContext) = + + let rows = + this.Rows + |> Array.map (Option.bind + (fun vector -> Some <| vector.ToDevice(context))) + + { Context = context + RowCount = this.RowCount + ColumnCount = this.ColumnCount + Rows = rows + NNZ = this.NNZ } + type Tuples<'a> = { RowIndices: int [] ColumnIndices: int [] @@ -145,27 +182,32 @@ type Matrix<'a when 'a: struct> = | CSR of Matrix.CSR<'a> | COO of Matrix.COO<'a> | CSC of Matrix.CSC<'a> + | Rows of Matrix.Rows<'a> member this.RowCount = match this with | CSR matrix -> matrix.RowCount | COO matrix -> matrix.RowCount | CSC matrix -> matrix.RowCount + | Rows matrix -> matrix.RowCount member this.ColumnCount = match this with | CSR matrix -> matrix.ColumnCount | COO matrix -> matrix.ColumnCount | CSC matrix -> matrix.ColumnCount + | Rows matrix -> matrix.ColumnCount member this.NNZ = match this with | COO m -> m.NNZ | CSR m -> m.NNZ | CSC m -> m.NNZ + | Rows m -> m.NNZ member this.ToDevice(context: ClContext) = match this with | COO matrix -> ClMatrix.COO <| matrix.ToDevice context | CSR matrix -> ClMatrix.CSR <| matrix.ToDevice context | CSC matrix -> ClMatrix.CSC <| matrix.ToDevice context + | Rows matrix -> ClMatrix.Rows <| matrix.ToDevice context diff --git a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs index f3019cce..6939b345 100644 --- a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs +++ b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs @@ -3,69 +3,39 @@ namespace GraphBLAS.FSharp.Objects open GraphBLAS.FSharp.Backend.Objects open Brahma.FSharp open Matrix +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +open GraphBLAS.FSharp.Objects.ClVectorExtensions module MatrixExtensions = type ClMatrix<'a when 'a: struct> with member this.ToHost(q: MailboxProcessor<_>) = match this with | ClMatrix.COO m -> - let rows = Array.zeroCreate m.Rows.Length - let columns = Array.zeroCreate m.Columns.Length - let values = Array.zeroCreate m.Values.Length - - q.Post(Msg.CreateToHostMsg(m.Rows, rows)) - - q.Post(Msg.CreateToHostMsg(m.Columns, columns)) - - ignore - <| q.PostAndReply(fun ch -> Msg.CreateToHostMsg(m.Values, values, ch)) - - let result = - { RowCount = m.RowCount - ColumnCount = m.ColumnCount - Rows = rows - Columns = columns - Values = values } - - Matrix.COO result + { RowCount = m.RowCount + ColumnCount = m.ColumnCount + Rows = m.Rows.ToHost q + Columns = m.Columns.ToHost q + Values = m.Values.ToHost q } + |> Matrix.COO | ClMatrix.CSR m -> - let rows = Array.zeroCreate m.RowPointers.Length - let columns = Array.zeroCreate m.Columns.Length - let values = Array.zeroCreate m.Values.Length - - q.Post(Msg.CreateToHostMsg(m.RowPointers, rows)) - - q.Post(Msg.CreateToHostMsg(m.Columns, columns)) - - ignore - <| q.PostAndReply(fun ch -> Msg.CreateToHostMsg(m.Values, values, ch)) - - let result = - { RowCount = m.RowCount - ColumnCount = m.ColumnCount - RowPointers = rows - ColumnIndices = columns - Values = values } - - Matrix.CSR result + { RowCount = m.RowCount + ColumnCount = m.ColumnCount + RowPointers = m.RowPointers.ToHost q + ColumnIndices = m.Columns.ToHost q + Values = m.Values.ToHost q } + |> Matrix.CSR | ClMatrix.CSC m -> - let rows = Array.zeroCreate m.Rows.Length - let columns = Array.zeroCreate m.ColumnPointers.Length - let values = Array.zeroCreate m.Values.Length - - q.Post(Msg.CreateToHostMsg(m.Rows, rows)) - - q.Post(Msg.CreateToHostMsg(m.ColumnPointers, columns)) - - ignore - <| q.PostAndReply(fun ch -> Msg.CreateToHostMsg(m.Values, values, ch)) - - let result = - { RowCount = m.RowCount - ColumnCount = m.ColumnCount - RowIndices = rows - ColumnPointers = columns - Values = values } - - Matrix.CSC result - | _ -> failwith "Not yet implemented" + { RowCount = m.RowCount + ColumnCount = m.ColumnCount + RowIndices = m.Rows.ToHost q + ColumnPointers = m.ColumnPointers.ToHost q + Values = m.Values.ToHost q } + |> Matrix.CSC + | ClMatrix.Rows m -> + { RowCount = m.RowCount + ColumnCount = m.ColumnCount + Rows = + m.Rows + |> Array.map (Option.bind (fun row -> Some <| row.ToHost q)) + NNZ = m.NNZ } + |> Matrix.Rows diff --git a/src/GraphBLAS-sharp/Objects/Vector.fs b/src/GraphBLAS-sharp/Objects/Vector.fs index 7caa47b6..19b7e01a 100644 --- a/src/GraphBLAS-sharp/Objects/Vector.fs +++ b/src/GraphBLAS-sharp/Objects/Vector.fs @@ -33,15 +33,14 @@ module Vector = Size = size } static member FromArray(array: 'a [], isZero: 'a -> bool) = - let (indices, vals) = + let indices, values = array - |> Seq.cast<'a> |> Seq.mapi (fun idx v -> (idx, v)) |> Seq.filter (fun (_, v) -> not (isZero v)) |> Array.ofSeq |> Array.unzip - Sparse.FromTuples(indices, vals, array.Length) + Sparse.FromTuples(indices, values, array.Length) member this.NNZ = this.Values.Length diff --git a/src/GraphBLAS-sharp/Objects/VectorExtensions.fs b/src/GraphBLAS-sharp/Objects/VectorExtensions.fs index ad9333be..23d40b26 100644 --- a/src/GraphBLAS-sharp/Objects/VectorExtensions.fs +++ b/src/GraphBLAS-sharp/Objects/VectorExtensions.fs @@ -2,23 +2,18 @@ namespace GraphBLAS.FSharp.Objects open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions open GraphBLAS.FSharp.Backend.Objects -open Brahma.FSharp +open GraphBLAS.FSharp.Objects.Vector module ClVectorExtensions = + type ClVector.Sparse<'a> with + member this.ToHost(q: MailboxProcessor<_>) = + { Indices = this.Indices.ToHost q + Values = this.Values.ToHost q + Size = this.Size } + type ClVector<'a when 'a: struct> with member this.ToHost(q: MailboxProcessor<_>) = match this with | ClVector.Sparse vector -> - let indices = Array.zeroCreate vector.Indices.Length - let values = Array.zeroCreate vector.Values.Length - - q.Post(Msg.CreateToHostMsg(vector.Indices, indices)) - - q.PostAndReply(fun ch -> Msg.CreateToHostMsg(vector.Values, values, ch)) - |> ignore - - Vector.Sparse - <| { Indices = indices - Values = values - Size = this.Size } + Vector.Sparse <| vector.ToHost q | ClVector.Dense vector -> Vector.Dense <| vector.ToHost q diff --git a/tests/GraphBLAS-sharp.Tests/Helpers.fs b/tests/GraphBLAS-sharp.Tests/Helpers.fs index d39742c7..6e287866 100644 --- a/tests/GraphBLAS-sharp.Tests/Helpers.fs +++ b/tests/GraphBLAS-sharp.Tests/Helpers.fs @@ -63,6 +63,9 @@ module Utils = | CSC -> Matrix.CSC <| Matrix.CSC.FromArray2D(array, isZero) + | Rows -> + Matrix.Rows + <| Matrix.Rows.FromArray2D(array, isZero) let createVectorFromArray vectorCase array isZero = match vectorCase with diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs index 150ec153..a62dade9 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs @@ -18,6 +18,12 @@ let config = Utils.defaultConfig let workGroupSize = Utils.defaultWorkGroupSize +let context = defaultContext.ClContext + +let q = defaultContext.Queue + +q.Error.Add(fun e -> failwithf "%A" e) + let makeTest context q formatFrom formatTo convertFun isZero (array: 'a [,]) = let mtx = Utils.createMatrixFromArray2D formatFrom array isZero @@ -42,68 +48,32 @@ let makeTest context q formatFrom formatTo convertFun isZero (array: 'a [,]) = "Matrices should be equal" |> Expect.equal actual expected -let testFixtures formatTo = - let getCorrectnessTestName datatype formatFrom = - $"Correctness on %s{datatype}, %A{formatFrom} to %A{formatTo}" +let createTest<'a when 'a : struct and 'a : equality> convertFun formatTo (isZero: 'a -> bool) = + let convertFun = convertFun context Utils.defaultWorkGroupSize - let context = defaultContext.ClContext - let q = defaultContext.Queue - q.Error.Add(fun e -> failwithf "%A" e) + Utils.listOfUnionCases + |> List.map (fun formatFrom -> + makeTest context q formatFrom formatTo convertFun isZero + |> testPropertyWithConfig { config with endSize = 10 } $"test on %A{typeof<'a>} from %A{formatFrom}") +let testFixtures formatTo = match formatTo with | COO -> - [ let convertFun = Matrix.toCOO context workGroupSize - - Utils.listOfUnionCases - |> List.map - (fun formatFrom -> - makeTest context q formatFrom formatTo convertFun ((=) 0) - |> testPropertyWithConfig config (getCorrectnessTestName "int" formatFrom)) - - let convertFun = Matrix.toCOO context workGroupSize - - Utils.listOfUnionCases - |> List.map - (fun formatFrom -> - makeTest context q formatFrom formatTo convertFun ((=) false) - |> testPropertyWithConfig config (getCorrectnessTestName "bool" formatFrom)) ] - |> List.concat + [ createTest Matrix.toCOO formatTo ((=) 0) + createTest Matrix.toCOO formatTo ((=) false) ] | CSR -> - [ let convertFun = Matrix.toCSR context workGroupSize - - Utils.listOfUnionCases - |> List.map - (fun formatFrom -> - makeTest context q formatFrom formatTo convertFun ((=) 0) - |> testPropertyWithConfig config (getCorrectnessTestName "int" formatFrom)) - - let convertFun = Matrix.toCSR context workGroupSize - - Utils.listOfUnionCases - |> List.map - (fun formatFrom -> - makeTest context q formatFrom formatTo convertFun ((=) false) - |> testPropertyWithConfig config (getCorrectnessTestName "bool" formatFrom)) ] - |> List.concat + [ createTest Matrix.toCSR formatTo ((=) 0) + createTest Matrix.toCSR formatTo ((=) false) ] | CSC -> - [ let convertFun = Matrix.toCSC context workGroupSize - - Utils.listOfUnionCases - |> List.map - (fun formatFrom -> - makeTest context q formatFrom formatTo convertFun ((=) 0) - |> testPropertyWithConfig config (getCorrectnessTestName "int" formatFrom)) - - let convertFun = Matrix.toCSC context workGroupSize - - Utils.listOfUnionCases - |> List.map - (fun formatFrom -> - makeTest context q formatFrom formatTo convertFun ((=) false) - |> testPropertyWithConfig config (getCorrectnessTestName "bool" formatFrom)) ] - |> List.concat + [ createTest Matrix.toCSC formatTo ((=) 0) + createTest Matrix.toCSC formatTo ((=) false) ] + | Rows -> + [ createTest Matrix.toRows formatTo ((=) 0) + createTest Matrix.toRows formatTo ((=) false) ] + |> List.concat + |> testList $"%A{formatTo}" let tests = Utils.listOfUnionCases - |> List.collect testFixtures - |> testList "Convert tests" + |> List.map testFixtures + |> testList "Convert" diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index 19e04826..a0bf2c8a 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -95,5 +95,5 @@ open GraphBLAS.FSharp.Tests [] let main argv = - testList "lol" [ Common.ClArray.Pairwise.tests ] |> testSequenced + testList "lol" [ Matrix.Convert.tests ] |> testSequenced |> runTestsWithCLIArgs [] argv From 6f2adb3516b2c940b1d4b640e07c0fbb6219b3e9 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Tue, 18 Apr 2023 19:08:08 +0300 Subject: [PATCH 14/44] wip: SpGeMM expand phase --- .../Matrix/CSR/Matrix.fs | 2 +- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 31 +- .../Matrix/SpGeMM/Expand.fs | 139 +++-- src/GraphBLAS-sharp.Backend/Objects/Vector.fs | 2 + src/GraphBLAS-sharp.Backend/Quotes/Map.fs | 2 - .../Objects/MatrixExtensions.fs | 7 + .../Common/ClArray/Pairwise.fs | 20 +- tests/GraphBLAS-sharp.Tests/Generators.fs | 59 +- tests/GraphBLAS-sharp.Tests/Helpers.fs | 7 +- .../Matrix/SpGeMM/Expand.fs | 532 +++++++++--------- .../GraphBLAS-sharp.Tests/Matrix/Transpose.fs | 1 + tests/GraphBLAS-sharp.Tests/Program.fs | 2 +- 12 files changed, 437 insertions(+), 367 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 05b77c11..0d941012 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -167,7 +167,7 @@ module Matrix = let pairwise = ClArray.pairwise clContext workGroupSize let subtract = - ClArray.map clContext workGroupSize Map.pairSubtraction + ClArray.map clContext workGroupSize <@ fun (fst, snd) -> snd - fst @> fun (processor: MailboxProcessor<_>) (matrix: ClMatrix.CSR<'b>) -> let pointerPairs = diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index d1b35a2a..fda92183 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -424,19 +424,18 @@ module Matrix = | ClMatrix.CSR m1, ClMatrix.CSC m2, ClMatrix.COO mask -> runCSRnCSC queue m1 m2 mask |> ClMatrix.COO | _ -> failwith "Matrix formats are not matching" - // let expand // TODO() - // (clContext: ClContext) - // workGroupSize - // (opAdd: Expr<'c -> 'c -> 'c option>) - // (opMul: Expr<'a -> 'b -> 'c option>) - // = - // - // let run = - // SpGeMM.Expand.run clContext workGroupSize opAdd opMul - // - // fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix<'a>) (rightMatrix: ClMatrix<'b>) -> - // match leftMatrix, rightMatrix with - // | ClMatrix.CSR leftMatrix, ClMatrix.CSR rightMatrix -> - // run processor allocationMode leftMatrix rightMatrix - // |> ClMatrix.COO - // | _ -> failwith "Matrix formats are not matching" + let expand + (clContext: ClContext) + workGroupSize + (opAdd: Expr<'c -> 'c -> 'c option>) + (opMul: Expr<'a -> 'b -> 'c option>) + = + + let run = + SpGeMM.Expand.run clContext workGroupSize opAdd opMul + + fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix<'a>) (rightMatrix: ClMatrix<'b>) -> + match leftMatrix, rightMatrix with + | ClMatrix.CSR leftMatrix, ClMatrix.CSR rightMatrix -> + ClMatrix.Rows <| run processor allocationMode leftMatrix rightMatrix + | _ -> failwith "Matrix formats are not matching" diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index d061072e..241aa54a 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -12,6 +12,7 @@ open GraphBLAS.FSharp.Backend.Objects.ClCell open FSharp.Quotations open GraphBLAS.FSharp.Backend.Vector.Sparse open GraphBLAS.FSharp.Backend.Objects.ClVector +open GraphBLAS.FSharp.Backend.Objects.ClMatrix type Indices = ClArray @@ -70,60 +71,62 @@ module Expand = let rightMatrixGather = Gather.run clContext workGroupSize - fun (processor: MailboxProcessor<_>) lengths (segmentsPointers: Indices) (leftMatrixRow: ClVector.Sparse<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> - - // Compute left matrix positions - let leftMatrixPositions = zeroCreate processor DeviceOnly lengths + fun (processor: MailboxProcessor<_>) length (segmentsPointers: Indices) (leftMatrixRow: ClVector.Sparse<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> + if length = 0 then None + else + printfn "expand length: %A" length + // Compute left matrix positions + let leftMatrixPositions = zeroCreate processor DeviceOnly length - idScatter processor segmentsPointers leftMatrixPositions + idScatter processor segmentsPointers leftMatrixPositions - (maxPrefixSum processor leftMatrixPositions 0) - .Free processor + (maxPrefixSum processor leftMatrixPositions 0) + .Free processor - // Compute right matrix positions - let rightMatrixPositions = create processor DeviceOnly lengths 1 + // Compute right matrix positions + let rightMatrixPositions = create processor DeviceOnly length 1 - let requiredRightMatrixPointers = - zeroCreate processor DeviceOnly leftMatrixRow.Indices.Length + let requiredRightMatrixPointers = + zeroCreate processor DeviceOnly leftMatrixRow.Indices.Length - gather processor leftMatrixRow.Indices rightMatrix.RowPointers requiredRightMatrixPointers + gather processor leftMatrixRow.Indices rightMatrix.RowPointers requiredRightMatrixPointers - scatter processor segmentsPointers requiredRightMatrixPointers rightMatrixPositions + scatter processor segmentsPointers requiredRightMatrixPointers rightMatrixPositions - requiredRightMatrixPointers.Free processor + requiredRightMatrixPointers.Free processor - // another way to get offsets ??? - let offsets = - removeDuplicates processor segmentsPointers + // another way to get offsets ??? + let offsets = + removeDuplicates processor segmentsPointers - segmentPrefixSum processor offsets.Length rightMatrixPositions leftMatrixPositions offsets + segmentPrefixSum processor offsets.Length rightMatrixPositions leftMatrixPositions offsets - offsets.Free processor + offsets.Free processor - // compute columns - let columns = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, lengths) + // compute columns + let columns = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, length) - gather processor rightMatrixPositions rightMatrix.Columns columns + gather processor rightMatrixPositions rightMatrix.Columns columns - // compute left matrix values - let leftMatrixValues = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, lengths) + // compute left matrix values + let leftMatrixValues = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, length) - leftMatrixGather processor leftMatrixPositions leftMatrixRow.Values leftMatrixValues + leftMatrixGather processor leftMatrixPositions leftMatrixRow.Values leftMatrixValues - leftMatrixPositions.Free processor + leftMatrixPositions.Free processor - // compute right matrix values - let rightMatrixValues = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, lengths) + // compute right matrix values + let rightMatrixValues = + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, length) - rightMatrixGather processor rightMatrixPositions rightMatrix.Values rightMatrixValues + rightMatrixGather processor rightMatrixPositions rightMatrix.Values rightMatrixValues - rightMatrixPositions.Free processor + rightMatrixPositions.Free processor - // left, right matrix values, columns and rows indices - leftMatrixValues, rightMatrixValues, columns + // left, right matrix values, columns indices + Some (leftMatrixValues, rightMatrixValues, columns) let multiply (clContext: ClContext) workGroupSize (predicate: Expr<'a -> 'b -> 'c option>) = let getBitmap = @@ -235,42 +238,48 @@ module Expand = let length, segmentPointers = getSegmentPointers processor leftMatrixRow leftMatrixRowsLengths + if length < 0 then failwith "length < 0" + // expand - let leftMatrixValues, rightMatrixValues, columns = + let expandResult = expand processor length segmentPointers leftMatrixRow rightMatrix - // multiplication - let mulResult = - multiply processor leftMatrixValues rightMatrixValues columns + segmentPointers.Free processor + + expandResult + |> Option.bind (fun (leftMatrixValues, rightMatrixValues, columns) -> + // multiplication + let mulResult = + multiply processor leftMatrixValues rightMatrixValues columns - leftMatrixValues.Free processor - rightMatrixValues.Free processor - columns.Free processor + leftMatrixValues.Free processor + rightMatrixValues.Free processor + columns.Free processor - // check multiplication result - mulResult - |> Option.bind (fun (resultValues, resultColumns) -> - // sort - let sortedValues, sortedColumns = - sort processor resultValues resultColumns + // check multiplication result + mulResult + |> Option.bind (fun (resultValues, resultColumns) -> + // sort + let sortedValues, sortedColumns = + sort processor resultValues resultColumns - resultValues.Free processor - resultColumns.Free processor + resultValues.Free processor + resultColumns.Free processor - let reduceResult = - reduce processor allocationMode sortedValues sortedColumns + let reduceResult = + reduce processor allocationMode sortedValues sortedColumns - sortedValues.Free processor - sortedColumns.Free processor + sortedValues.Free processor + sortedColumns.Free processor - // create sparse vector (TODO(empty vector)) - reduceResult - |> Option.bind (fun (values, columns) -> - { Context = clContext - Indices = columns - Values = values - Size = rightMatrix.ColumnCount } - |> Some)) + // create sparse vector (TODO(empty vector)) + reduceResult + |> Option.bind (fun (values, columns) -> + { Context = clContext + Indices = columns + Values = values + Size = rightMatrix.ColumnCount } + |> Some))) let run<'a, 'b, 'c when 'a : struct and 'b : struct and 'c : struct> (clContext: ClContext) @@ -296,4 +305,10 @@ module Expand = split processor allocationMode leftMatrix |> Seq.map (fun lazyRow -> Option.bind runRow lazyRow.Value) |> Seq.toArray + |> fun rows -> + { Rows.Context = clContext + RowCount = leftMatrix.RowCount + ColumnCount = rightMatrix.ColumnCount + Rows = rows + NNZ = -1 } // TODO(nnz count) diff --git a/src/GraphBLAS-sharp.Backend/Objects/Vector.fs b/src/GraphBLAS-sharp.Backend/Objects/Vector.fs index fb8cdcc8..f7430242 100644 --- a/src/GraphBLAS-sharp.Backend/Objects/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Objects/Vector.fs @@ -22,6 +22,8 @@ module ClVector = member this.Dispose(q) = (this :> IDeviceMemObject).Dispose(q) + member this.NNZ = this.Values.Length + [] type ClVector<'a when 'a: struct> = | Sparse of ClVector.Sparse<'a> diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Map.fs b/src/GraphBLAS-sharp.Backend/Quotes/Map.fs index 9cb476b3..2f74a7c5 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Map.fs @@ -30,8 +30,6 @@ module Map = let inc = <@ fun item -> item + 1 @> - let pairSubtraction = <@ fun (first, second) -> first - second @> - let subtraction = <@ fun first second -> first - second @> let fst () = <@ fun fst _ -> fst @> diff --git a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs index 6939b345..0a90c4c3 100644 --- a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs +++ b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs @@ -39,3 +39,10 @@ module MatrixExtensions = |> Array.map (Option.bind (fun row -> Some <| row.ToHost q)) NNZ = m.NNZ } |> Matrix.Rows + + member this.ToHostAndDispose(processor: MailboxProcessor<_>) = + let result = this.ToHost processor + + this.Dispose processor + + result diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs index 734087c1..e0ed32d7 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs @@ -21,21 +21,17 @@ let makeTest<'a> isEqual testFun (array: 'a [] ) = let clArray = context.CreateClArray array - testFun processor HostInterop clArray - |> Option.bind (fun (actual: ClArray<_>) -> - let firstActual, secondActual = - actual.ToHostAndFree processor - |> Array.unzip + match testFun processor HostInterop clArray with + | Some (actual: ClArray<_>) -> + let actual = actual.ToHostAndFree processor - let firstExpected, secondExpected = Array.pairwise array |> Array.unzip + let expected = Array.pairwise array "First results must be the same" - |> Utils.compareArrays isEqual firstActual firstExpected - - "Second results must be the same" - |> Utils.compareArrays isEqual secondActual secondExpected - None) - |> ignore + |> Utils.compareArrays isEqual actual expected + | None -> + "Result must be empty" + |> Expect.isTrue (array.Size <= 1) let createTest<'a> isEqual = ClArray.pairwise context Utils.defaultWorkGroupSize diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index aa84f71b..3d4c3e37 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -318,7 +318,7 @@ module Generators = Arb.generate |> Arb.fromGen - type PairOfSparseVectorAndMatrixOfCompatibleSize() = + type PairOfSparseVectorAndMatrixAndMaskOfCompatibleSize() = static let pairOfVectorAndMatrixOfCompatibleSizeGenerator (valuesGenerator: Gen<'a>) = gen { let! nRows, nColumns = dimension2DGenerator @@ -376,6 +376,63 @@ module Generators = |> genericSparseGenerator false Arb.generate |> Arb.fromGen + type VectorXMatrix() = + static let pairOfVectorAndMatrixOfCompatibleSizeGenerator (valuesGenerator: Gen<'a>) = + gen { + let! nRows, nColumns = dimension2DGenerator + let! vector = valuesGenerator |> Gen.arrayOfLength nRows + + let! matrix = + valuesGenerator + |> Gen.array2DOfDim (nRows, nColumns) + + return (vector, matrix) + } + + static member IntType() = + pairOfVectorAndMatrixOfCompatibleSizeGenerator + |> genericSparseGenerator 0 Arb.generate + |> Arb.fromGen + + static member FloatType() = + pairOfVectorAndMatrixOfCompatibleSizeGenerator + |> genericSparseGenerator + 0. + (Arb.Default.NormalFloat() + |> Arb.toGen + |> Gen.map float) + |> Arb.fromGen + + static member Float32Type() = + pairOfVectorAndMatrixOfCompatibleSizeGenerator + |> genericSparseGenerator 0.0f (normalFloat32Generator <| System.Random()) + |> Arb.fromGen + + static member SByteType() = + pairOfVectorAndMatrixOfCompatibleSizeGenerator + |> genericSparseGenerator 0y Arb.generate + |> Arb.fromGen + + static member ByteType() = + pairOfVectorAndMatrixOfCompatibleSizeGenerator + |> genericSparseGenerator 0uy Arb.generate + |> Arb.fromGen + + static member Int16Type() = + pairOfVectorAndMatrixOfCompatibleSizeGenerator + |> genericSparseGenerator 0s Arb.generate + |> Arb.fromGen + + static member UInt16Type() = + pairOfVectorAndMatrixOfCompatibleSizeGenerator + |> genericSparseGenerator 0us Arb.generate + |> Arb.fromGen + + static member BoolType() = + pairOfVectorAndMatrixOfCompatibleSizeGenerator + |> genericSparseGenerator false Arb.generate + |> Arb.fromGen + type PairOfMatricesOfCompatibleSize() = static let pairOfMatricesOfCompatibleSizeGenerator (valuesGenerator: Gen<'a>) = gen { diff --git a/tests/GraphBLAS-sharp.Tests/Helpers.fs b/tests/GraphBLAS-sharp.Tests/Helpers.fs index 6e287866..751bc6fe 100644 --- a/tests/GraphBLAS-sharp.Tests/Helpers.fs +++ b/tests/GraphBLAS-sharp.Tests/Helpers.fs @@ -25,7 +25,7 @@ module Utils = typeof typeof typeof - typeof + typeof typeof typeof typeof @@ -150,11 +150,6 @@ module Utils = result - let castMatrixToCSR = - function - | Matrix.CSR matrix -> matrix - | _ -> failwith "matrix format must be CSR" - module HostPrimitives = let prefixSumInclude zero add array = Array.scan add zero array diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs index 38d70b6c..7e9ed80b 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs @@ -1,266 +1,266 @@ - module GraphBLAS.FSharp.Tests.Matrix.SpGeMM.Expand -// TODO() -// open Expecto -// open GraphBLAS.FSharp.Backend.Matrix.CSR.SpGeMM -// open GraphBLAS.FSharp.Backend.Quotes -// open GraphBLAS.FSharp.Test -// open Microsoft.FSharp.Collections -// open GraphBLAS.FSharp.Backend -// open GraphBLAS.FSharp.Backend.Matrix -// open GraphBLAS.FSharp.Backend.Objects -// open GraphBLAS.FSharp.Tests -// open GraphBLAS.FSharp.Tests.Backend -// open GraphBLAS.FSharp.Objects -// open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions -// open Brahma.FSharp -// open GraphBLAS.FSharp.Backend.Objects.ClContext -// open GraphBLAS.FSharp.Objects.MatrixExtensions -// -// let context = Context.defaultContext.ClContext -// -// let processor = Context.defaultContext.Queue -// -// let config = -// { Utils.defaultConfig with -// arbitrary = [ typeof ] -// endSize = 100 -// maxTest = 100 } -// -// let createCSRMatrix array isZero = -// Utils.createMatrixFromArray2D CSR array isZero -// |> Utils.castMatrixToCSR -// -// let getSegmentsPointers (leftMatrix: Matrix.CSR<'a>) (rightMatrix: Matrix.CSR<'b>) = -// Array.map -// (fun item -> -// rightMatrix.RowPointers.[item + 1] -// - rightMatrix.RowPointers.[item]) -// leftMatrix.ColumnIndices -// |> HostPrimitives.prefixSumExclude 0 (+) -// -// let makeTest isZero testFun (leftArray: 'a [,], rightArray: 'a [,]) = -// -// let leftMatrix = createCSRMatrix leftArray isZero -// -// let rightMatrix = createCSRMatrix rightArray isZero -// -// if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then -// -// let clLeftMatrix = leftMatrix.ToDevice context -// -// let clRightMatrix = rightMatrix.ToDevice context -// -// let actualLength, (clActual: ClArray) = -// testFun processor clLeftMatrix clRightMatrix -// -// clLeftMatrix.Dispose processor -// clRightMatrix.Dispose processor -// -// let actualPointers = clActual.ToHostAndFree processor -// -// let expectedPointers, expectedLength = -// getSegmentsPointers leftMatrix rightMatrix -// -// "Results lengths must be the same" -// |> Expect.equal actualLength expectedLength -// -// "Result pointers must be the same" -// |> Expect.sequenceEqual actualPointers expectedPointers -// -// let createTest<'a when 'a: struct> (isZero: 'a -> bool) = -// -// let testFun = -// Expand.getSegmentPointers context Utils.defaultWorkGroupSize -// -// makeTest isZero testFun -// |> testPropertyWithConfig config $"test on {typeof<'a>}" -// -// let getSegmentsTests = -// [ createTest ((=) 0) -// -// if Utils.isFloat64Available context.ClDevice then -// createTest ((=) 0.0) -// -// createTest ((=) 0f) -// createTest ((=) false) -// createTest ((=) 0uy) ] -// |> testList "get segment pointers" -// -// let expand length segmentPointers (leftMatrix: Matrix.CSR<'a>) (rightMatrix: Matrix.CSR<'b>) = -// let extendPointers pointers = -// Array.pairwise pointers -// |> Array.map (fun (fst, snd) -> snd - fst) -// |> Array.mapi (fun index length -> Array.create length index) -// |> Array.concat -// -// let segmentsLengths = -// Array.append segmentPointers [| length |] -// |> Array.pairwise -// |> Array.map (fun (fst, snd) -> snd - fst) -// -// let leftMatrixValues, expectedRows = -// let tripleFst (fst, _, _) = fst -// -// Array.zip3 segmentsLengths leftMatrix.Values -// <| extendPointers leftMatrix.RowPointers -// // select items each segment length not zero -// |> Array.filter (tripleFst >> ((=) 0) >> not) -// |> Array.collect (fun (length, value, rowIndex) -> Array.create length (value, rowIndex)) -// |> Array.unzip -// -// let rightMatrixValues, expectedColumns = -// let valuesAndColumns = -// Array.zip rightMatrix.Values rightMatrix.ColumnIndices -// -// Array.map2 -// (fun column length -> -// let rowStart = rightMatrix.RowPointers.[column] -// Array.take length valuesAndColumns.[rowStart..]) -// leftMatrix.ColumnIndices -// segmentsLengths -// |> Array.concat -// |> Array.unzip -// -// leftMatrixValues, rightMatrixValues, expectedColumns, expectedRows -// -// let makeExpandTest isEqual zero testFun (leftArray: 'a [,], rightArray: 'a [,]) = -// -// let leftMatrix = -// createCSRMatrix leftArray <| isEqual zero -// -// let rightMatrix = -// createCSRMatrix rightArray <| isEqual zero -// -// if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then -// -// let segmentPointers, length = -// getSegmentsPointers leftMatrix rightMatrix -// -// let clLeftMatrix = leftMatrix.ToDevice context -// let clRightMatrix = rightMatrix.ToDevice context -// let clSegmentPointers = context.CreateClArray segmentPointers -// -// let ((clActualLeftValues: ClArray<'a>), -// (clActualRightValues: ClArray<'a>), -// (clActualColumns: ClArray), -// (clActualRows: ClArray)) = -// testFun processor length clSegmentPointers clLeftMatrix clRightMatrix -// -// clLeftMatrix.Dispose processor -// clRightMatrix.Dispose processor -// clSegmentPointers.Free processor -// -// let actualLeftValues = -// clActualLeftValues.ToHostAndFree processor -// -// let actualRightValues = -// clActualRightValues.ToHostAndFree processor -// -// let actualColumns = clActualColumns.ToHostAndFree processor -// let actualRows = clActualRows.ToHostAndFree processor -// -// let expectedLeftMatrixValues, expectedRightMatrixValues, expectedColumns, expectedRows = -// expand length segmentPointers leftMatrix rightMatrix -// -// "Left values must be the same" -// |> Utils.compareArrays isEqual actualLeftValues expectedLeftMatrixValues -// -// "Right values must be the same" -// |> Utils.compareArrays isEqual actualRightValues expectedRightMatrixValues -// -// "Columns must be the same" -// |> Utils.compareArrays (=) actualColumns expectedColumns -// -// "Rows must be the same" -// |> Utils.compareArrays (=) actualRows expectedRows -// -// let createExpandTest isEqual (zero: 'a) testFun = -// -// let testFun = -// testFun context Utils.defaultWorkGroupSize -// -// makeExpandTest isEqual zero testFun -// |> testPropertyWithConfig config $"test on %A{typeof<'a>}" -// -// // expand phase tests -// let expandTests = -// [ createExpandTest (=) 0 Expand.expand -// -// if Utils.isFloat64Available context.ClDevice then -// createExpandTest Utils.floatIsEqual 0.0 Expand.expand -// -// createExpandTest Utils.float32IsEqual 0f Expand.expand -// createExpandTest (=) false Expand.expand -// createExpandTest (=) 0uy Expand.expand ] -// |> testList "Expand.expand" -// -// let checkGeneralResult zero isEqual (actualMatrix: Matrix<'a>) mul add (leftArray: 'a [,]) (rightArray: 'a [,]) = -// -// let expected = -// HostPrimitives.array2DMultiplication zero mul add leftArray rightArray -// |> fun array -> Utils.createMatrixFromArray2D COO array (isEqual zero) -// -// match actualMatrix, expected with -// | Matrix.COO actualMatrix, Matrix.COO expected -> -// -// "Values must be the same" -// |> Utils.compareArrays isEqual actualMatrix.Values expected.Values -// -// "Columns must be the same" -// |> Utils.compareArrays (=) actualMatrix.Columns expected.Columns -// -// "Rows must be the same" -// |> Utils.compareArrays (=) actualMatrix.Rows expected.Rows -// | _ -> failwith "Matrix format are not matching" -// -// let makeGeneralTest zero isEqual opMul opAdd testFun (leftArray: 'a [,], rightArray: 'a [,]) = -// -// let leftMatrix = -// Utils.createMatrixFromArray2D CSR leftArray (isEqual zero) -// -// let rightMatrix = -// Utils.createMatrixFromArray2D CSR rightArray (isEqual zero) -// -// if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then -// try -// let clLeftMatrix = leftMatrix.ToDevice context -// let clRightMatrix = rightMatrix.ToDevice context -// -// let (clMatrixActual: ClMatrix<_>) = -// testFun processor HostInterop clLeftMatrix clRightMatrix -// -// let matrixActual = clMatrixActual.ToHost processor -// clMatrixActual.Dispose processor -// -// checkGeneralResult zero isEqual matrixActual opMul opAdd leftArray rightArray -// with -// | ex when ex.Message = "InvalidBufferSize" -> () -// | _ -> reraise () -// -// let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = -// -// let testFun = -// testFun context Utils.defaultWorkGroupSize opAddQ opMulQ -// -// makeGeneralTest zero isEqual opMul opAdd testFun -// |> testPropertyWithConfig config $"test on %A{typeof<'a>}" -// -// let generalTests = -// [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand -// -// if Utils.isFloat64Available context.ClDevice then -// createGeneralTest -// 0.0 -// Utils.floatIsEqual -// ArithmeticOperations.floatAdd -// ArithmeticOperations.floatMul -// Matrix.SpGeMM.expand -// -// createGeneralTest -// 0.0f -// Utils.float32IsEqual -// ArithmeticOperations.float32Add -// ArithmeticOperations.float32Mul -// Matrix.SpGeMM.expand -// createGeneralTest false (=) ArithmeticOperations.boolAdd ArithmeticOperations.boolMul Matrix.SpGeMM.expand ] -// |> testList "general" +module GraphBLAS.FSharp.Tests.Matrix.SpGeMM.Expand + +open Expecto +open GraphBLAS.FSharp.Backend.Matrix.SpGeMM +open GraphBLAS.FSharp.Backend.Quotes +open GraphBLAS.FSharp.Test +open Microsoft.FSharp.Collections +open GraphBLAS.FSharp.Backend +open GraphBLAS.FSharp.Backend.Matrix +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Tests +open GraphBLAS.FSharp.Tests.Backend +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +open Brahma.FSharp +open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Objects.MatrixExtensions + +let context = Context.defaultContext.ClContext + +let processor = Context.defaultContext.Queue + +let config = + { Utils.defaultConfig with + arbitrary = [ typeof ] } + +let makeTest isZero testFun (leftArray: 'a [], rightArray: 'a [,]) = + + let leftMatrixRow = + Vector.Sparse.FromArray(leftArray, isZero) + + let rightMatrix = + Matrix.CSR.FromArray2D(rightArray, isZero) + + if leftMatrixRow.NNZ > 0 && rightMatrix.NNZ > 0 then + + // compute expected result + let rightMatrixRowsLength = + rightMatrix.RowPointers + |> Array.pairwise + |> Array.map (fun (fst, snd) -> snd - fst) + + let expectedPointers, expectedLength = + Array.init leftMatrixRow.Indices.Length (fun index -> + rightMatrixRowsLength.[leftMatrixRow.Indices[index]]) + |> HostPrimitives.prefixSumExclude 0 (+) + + let clLeftMatrixRow = leftMatrixRow.ToDevice context + + let clRightMatrixRowsLength = + context.CreateClArray rightMatrixRowsLength + + let actualLength, (clActual: ClArray) = + testFun processor clLeftMatrixRow clRightMatrixRowsLength + + clLeftMatrixRow.Dispose processor + + let actualPointers = clActual.ToHostAndFree processor + + "Results lengths must be the same" + |> Expect.equal actualLength expectedLength + + "Result pointers must be the same" + |> Expect.sequenceEqual actualPointers expectedPointers + +let createTest<'a when 'a: struct> (isZero: 'a -> bool) = + Expand.getSegmentPointers context Utils.defaultWorkGroupSize + |> makeTest isZero + |> testPropertyWithConfig config $"test on {typeof<'a>}" + +// Debug tests +let getSegmentsTests = + [ createTest ((=) 0) + + if Utils.isFloat64Available context.ClDevice then + createTest ((=) 0.0) + + createTest ((=) 0f) + createTest ((=) false) + createTest ((=) 0uy) ] + |> testList "get segment pointers" + +let expand (leftMatrixRow: Vector.Sparse<'a>) (rightMatrix: Matrix.CSR<'b>) = + let rightMatrixRowsLengths = + rightMatrix.RowPointers + |> Array.pairwise + |> Array.map (fun (fst, snd) -> snd - fst) + + let segmentsLengths = + Array.map (fun columnIndex -> rightMatrixRowsLengths.[columnIndex]) leftMatrixRow.Indices + + let leftMatrixValues = + Array.map2 Array.create segmentsLengths leftMatrixRow.Values + |> Array.concat + + let rightMatrixRowPointers = + Array.map (fun index -> rightMatrix.RowPointers.[index]) leftMatrixRow.Indices + + let rightMatrixValues = + Array.map2(fun rowPointer segmentLength -> + Array.take segmentLength rightMatrix.Values.[rowPointer..]) + rightMatrixRowPointers segmentsLengths + |> Array.concat + + let columns = + Array.map2 (fun rowPointer segmentLength -> + Array.take segmentLength rightMatrix.ColumnIndices.[rowPointer ..]) + rightMatrixRowPointers segmentsLengths + |> Array.concat + + leftMatrixValues, rightMatrixValues, columns + +let makeExpandTest isEqual zero testFun (leftArray: 'a [], rightArray: 'a [,]) = + + let leftMatrixRow = + Vector.Sparse.FromArray(leftArray, (isEqual zero)) + + let rightMatrix = + Matrix.CSR.FromArray2D(rightArray, (isEqual zero)) + + if leftMatrixRow.NNZ > 0 && rightMatrix.NNZ > 0 then + + let clPointers, lenght = + rightMatrix.RowPointers + |> Array.pairwise + |> Array.map (fun (fst, snd) -> snd - fst) + |> fun rightMatrixRowsLengths -> + Array.init leftMatrixRow.Indices.Length (fun index -> + rightMatrixRowsLengths.[leftMatrixRow.Indices[index]]) + |> HostPrimitives.prefixSumExclude 0 (+) + |> fun (pointers, length) -> + context.CreateClArray(pointers), length + + let clLeftMatrixRow = leftMatrixRow.ToDevice context + let clRightMatrix = rightMatrix.ToDevice context + + let result + = testFun processor lenght clPointers clLeftMatrixRow clRightMatrix + + clLeftMatrixRow.Dispose processor + clRightMatrix.Dispose processor + clPointers.Free processor + + let expectedLeftMatrixValues, expectedRightMatrixValues, expectedColumns = + expand leftMatrixRow rightMatrix + + match result with + | Some (clActualLeftValues: ClArray<'a>, + clActualRightValues: ClArray<'a>, + clActualColumns: ClArray) -> + + let actualLeftValues = + clActualLeftValues.ToHostAndFree processor + + let actualRightValues = + clActualRightValues.ToHostAndFree processor + + let actualColumns = clActualColumns.ToHostAndFree processor + + "Left values must be the same" + |> Utils.compareArrays isEqual actualLeftValues expectedLeftMatrixValues + + "Right values must be the same" + |> Utils.compareArrays isEqual actualRightValues expectedRightMatrixValues + + "Columns must be the same" + |> Utils.compareArrays (=) actualColumns expectedColumns + | None -> + "Result must be empty" + |> Expect.isTrue (expectedColumns.Length = 0) + +let createExpandTest isEqual (zero: 'a) testFun = + testFun context Utils.defaultWorkGroupSize + |> makeExpandTest isEqual zero + |> testPropertyWithConfig { config with endSize = 10 ; maxTest = 100 } $"test on %A{typeof<'a>}" + +// (Debug only) expand phase tests +let expandTests = + [ createExpandTest (=) 0 Expand.expand + + if Utils.isFloat64Available context.ClDevice then + createExpandTest Utils.floatIsEqual 0.0 Expand.expand + + createExpandTest Utils.float32IsEqual 0f Expand.expand + createExpandTest (=) false Expand.expand + createExpandTest (=) 0uy Expand.expand ] + |> testList "Expand.expand" + +let compareSparseVectors isEqual (actual: Vector.Sparse<'a>) (expected: Vector.Sparse<'a>) = + "Sparse vector size must be the same" + |> Expect.equal actual.Size expected.Size + + "Value must be the same" + |> Utils.compareArrays isEqual actual.Values expected.Values + + "Indices must be the same" + |> Utils.compareArrays (=) actual.Indices expected.Indices + +let compareLILMatrix isEqual (actual: Matrix.Rows<'a>) (expected: Matrix.Rows<'a>) = + "Column count must be the same" + |> Expect.equal actual.ColumnCount expected.ColumnCount + + "Rows count must be the same" + |> Expect.equal actual.RowCount expected.RowCount + + Array.iter2 (fun actualRow expected -> + match actualRow, expected with + | Some actualVector, Some expectedVector -> + compareSparseVectors isEqual actualVector expectedVector + | None, None -> () + | _ -> failwith "Rows are not matching") + <| actual.Rows + <| expected.Rows + +let makeGeneralTest zero isEqual opMul opAdd testFun (leftArray: 'a [,], rightArray: 'a [,]) = + + let leftMatrix = + Utils.createMatrixFromArray2D CSR leftArray (isEqual zero) + + let rightMatrix = + Utils.createMatrixFromArray2D CSR rightArray (isEqual zero) + + if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then + + let clLeftMatrix = leftMatrix.ToDevice context + let clRightMatrix = rightMatrix.ToDevice context + + let (clMatrixActual: ClMatrix<_>) = + testFun processor HostInterop clLeftMatrix clRightMatrix + + let matrixActual = clMatrixActual.ToHostAndDispose processor + + match matrixActual with + | Matrix.Rows actual -> + HostPrimitives.array2DMultiplication zero opMul opAdd leftArray rightArray + |> fun array -> Matrix.Rows.FromArray2D(array, (isEqual zero)) + |> compareLILMatrix isEqual actual + | _ -> failwith "Matrix format are not matching" + +let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = + + let testFun = + testFun context Utils.defaultWorkGroupSize opAddQ opMulQ + + makeGeneralTest zero isEqual opMul opAdd testFun + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let generalTests = + [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand + + if Utils.isFloat64Available context.ClDevice then + createGeneralTest + 0.0 + Utils.floatIsEqual + ArithmeticOperations.floatAdd + ArithmeticOperations.floatMul + Matrix.SpGeMM.expand + + createGeneralTest + 0.0f + Utils.float32IsEqual + ArithmeticOperations.float32Add + ArithmeticOperations.float32Mul + Matrix.SpGeMM.expand + createGeneralTest false (=) ArithmeticOperations.boolAdd ArithmeticOperations.boolMul Matrix.SpGeMM.expand ] + |> testList "general" diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs index 4e894609..fadc30df 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs @@ -77,6 +77,7 @@ let checkResult areEqual zero actual (expected2D: 'a [,]) = "Value arrays should be equal" |> Utils.compareArrays areEqual actual.Values expected.Values + | _ -> () // TODO() let makeTestRegular context q transposeFun hostTranspose isEqual zero case (array: 'a [,]) = let mtx = diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index a0bf2c8a..19e04826 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -95,5 +95,5 @@ open GraphBLAS.FSharp.Tests [] let main argv = - testList "lol" [ Matrix.Convert.tests ] |> testSequenced + testList "lol" [ Common.ClArray.Pairwise.tests ] |> testSequenced |> runTestsWithCLIArgs [] argv From cf48196f77c0b5c13339e7ff7b6bbcfc1667cde5 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Wed, 19 Apr 2023 14:10:30 +0300 Subject: [PATCH 15/44] add: CSR.RowsLengths tests --- .../Matrix/CSR/Matrix.fs | 4 +- .../Matrix/SpGeMM/Expand.fs | 8 +-- .../GraphBLAS-sharp.Tests.fsproj | 1 + .../Matrix/RowsLengths.fs | 53 +++++++++++++++++++ .../Matrix/SpGeMM/Expand.fs | 48 +++++++++-------- tests/GraphBLAS-sharp.Tests/Program.fs | 2 +- 6 files changed, 88 insertions(+), 28 deletions(-) create mode 100644 tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 0d941012..fe28d499 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -169,14 +169,14 @@ module Matrix = let subtract = ClArray.map clContext workGroupSize <@ fun (fst, snd) -> snd - fst @> - fun (processor: MailboxProcessor<_>) (matrix: ClMatrix.CSR<'b>) -> + fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'b>) -> let pointerPairs = pairwise processor DeviceOnly matrix.RowPointers // since row pointers length in matrix always >= 2 |> Option.defaultWith (fun () -> failwith "The state of the matrix is broken. The length of the rowPointers must be >= 2") - let rowsLength = subtract processor DeviceOnly pointerPairs + let rowsLength = subtract processor allocationMode pointerPairs pointerPairs.Free processor diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index 241aa54a..30308585 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -34,8 +34,6 @@ module Expand = // extract needed lengths by left matrix nnz gather processor leftMatrixRow.Indices rightMatrixRowsLengths segmentsLengths - rightMatrixRowsLengths.Free processor - // compute pointers let length = (prefixSum processor segmentsLengths) @@ -297,11 +295,15 @@ module Expand = fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix.CSR<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> let rightMatrixRowsLengths = - getRowsLength processor rightMatrix + getRowsLength processor DeviceOnly rightMatrix + + printfn "right matrix rows lengths: %A" <| rightMatrixRowsLengths.ToHost processor let runRow = runRow processor allocationMode rightMatrix rightMatrixRowsLengths + rightMatrixRowsLengths.Free processor + split processor allocationMode leftMatrix |> Seq.map (fun lazyRow -> Option.bind runRow lazyRow.Value) |> Seq.toArray diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index 5493767f..64400aa6 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -56,6 +56,7 @@ + diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs b/tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs new file mode 100644 index 00000000..847c7f74 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs @@ -0,0 +1,53 @@ +module GraphBLAS.FSharp.Tests.Backend.Matrix.RowsLengths + +open Expecto +open Microsoft.FSharp.Collections +open GraphBLAS.FSharp.Backend +open GraphBLAS.FSharp.Backend.Matrix +open GraphBLAS.FSharp.Tests +open GraphBLAS.FSharp.Tests.Backend +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +open Brahma.FSharp +open GraphBLAS.FSharp.Backend.Objects.ClContext + +let processor = Context.defaultContext.Queue + +let context = Context.defaultContext.ClContext + +let config = Utils.defaultConfig + +let makeTest isZero testFun (array: 'a [,]) = + + let matrix = Matrix.CSR.FromArray2D(array, isZero) + + if matrix.NNZ > 0 then + + let clMatrix = matrix.ToDevice context + let (clActual: ClArray) = testFun processor HostInterop clMatrix + + clMatrix.Dispose processor + let actual = clActual.ToHostAndFree processor + + let expected = + matrix.RowPointers + |> Array.pairwise + |> Array.map (fun (fst, snd) -> snd - fst) + + "Results must be the same" + |> Utils.compareArrays (=) actual expected + +let createTest<'a when 'a : struct> (isZero: 'a -> bool) = + CSR.Matrix.getRowsLength context Utils.defaultWorkGroupSize + |> makeTest isZero + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let tests = + [ createTest <| (=) 0 + + if Utils.isFloat64Available context.ClDevice then + createTest <| Utils.floatIsEqual 0.0 + + createTest <| Utils.float32IsEqual 0.0f + createTest <| (=) false ] + |> testList "CSR.RowsLengths" diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs index 7e9ed80b..952fa08a 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs @@ -20,9 +20,12 @@ let context = Context.defaultContext.ClContext let processor = Context.defaultContext.Queue +processor.Error.Add(fun e -> failwithf "%A" e) + let config = { Utils.defaultConfig with - arbitrary = [ typeof ] } + arbitrary = [ typeof + typeof ] } let makeTest isZero testFun (leftArray: 'a [], rightArray: 'a [,]) = @@ -228,6 +231,9 @@ let makeGeneralTest zero isEqual opMul opAdd testFun (leftArray: 'a [,], rightAr let (clMatrixActual: ClMatrix<_>) = testFun processor HostInterop clLeftMatrix clRightMatrix + clLeftMatrix.Dispose processor + clRightMatrix.Dispose processor + let matrixActual = clMatrixActual.ToHostAndDispose processor match matrixActual with @@ -238,29 +244,27 @@ let makeGeneralTest zero isEqual opMul opAdd testFun (leftArray: 'a [,], rightAr | _ -> failwith "Matrix format are not matching" let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = - - let testFun = - testFun context Utils.defaultWorkGroupSize opAddQ opMulQ - - makeGeneralTest zero isEqual opMul opAdd testFun - |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + testFun context Utils.defaultWorkGroupSize opAddQ opMulQ + |> makeGeneralTest zero isEqual opMul opAdd + |> testPropertyWithConfig { config with endSize = 10 } $"test on %A{typeof<'a>}" let generalTests = [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand - if Utils.isFloat64Available context.ClDevice then - createGeneralTest - 0.0 - Utils.floatIsEqual - ArithmeticOperations.floatAdd - ArithmeticOperations.floatMul - Matrix.SpGeMM.expand - - createGeneralTest - 0.0f - Utils.float32IsEqual - ArithmeticOperations.float32Add - ArithmeticOperations.float32Mul - Matrix.SpGeMM.expand - createGeneralTest false (=) ArithmeticOperations.boolAdd ArithmeticOperations.boolMul Matrix.SpGeMM.expand ] + // if Utils.isFloat64Available context.ClDevice then + // createGeneralTest + // 0.0 + // Utils.floatIsEqual + // ArithmeticOperations.floatAdd + // ArithmeticOperations.floatMul + // Matrix.SpGeMM.expand + // + // createGeneralTest + // 0.0f + // Utils.float32IsEqual + // ArithmeticOperations.float32Add + // ArithmeticOperations.float32Mul + // Matrix.SpGeMM.expand + // createGeneralTest false (=) ArithmeticOperations.boolAdd ArithmeticOperations.boolMul Matrix.SpGeMM.expand ] + ] |> testList "general" diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index 19e04826..0fdf40ae 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -95,5 +95,5 @@ open GraphBLAS.FSharp.Tests [] let main argv = - testList "lol" [ Common.ClArray.Pairwise.tests ] |> testSequenced + testList "lol" [ Matrix.RowsLengths.tests ] |> testSequenced |> runTestsWithCLIArgs [] argv From a60b12a0fa31d7265c4b4667bea1c9f865f8f6f6 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Thu, 20 Apr 2023 10:53:32 +0300 Subject: [PATCH 16/44] add: spgemm row wise --- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 25 ++- src/GraphBLAS-sharp.Backend/Common/Sum.fs | 11 +- .../Matrix/CSR/Matrix.fs | 9 +- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 31 +-- .../Matrix/Rows/Matrix.fs | 12 +- .../Matrix/SpGeMM/Expand.fs | 124 ++++++------ src/GraphBLAS-sharp.Backend/Objects/Matrix.fs | 16 +- src/GraphBLAS-sharp.Backend/Quotes/Convert.fs | 2 +- .../Vector/Sparse/Map.fs | 3 +- src/GraphBLAS-sharp/Objects/Matrix.fs | 18 +- .../Objects/MatrixExtensions.fs | 12 +- .../Objects/VectorExtensions.fs | 3 +- .../Common/ClArray/Assign.fs | 7 +- .../Common/ClArray/Concat.fs | 9 +- .../Common/ClArray/Fill.fs | 4 +- .../Common/ClArray/Pairwise.fs | 4 +- .../Common/Reduce/ReduceByKey.fs | 41 ++-- .../Common/Sort/Radix.fs | 102 +++++----- tests/GraphBLAS-sharp.Tests/Generators.fs | 8 +- tests/GraphBLAS-sharp.Tests/Helpers.fs | 28 ++- tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs | 14 +- .../Matrix/RowsLengths.fs | 22 +- .../Matrix/SpGeMM/Expand.fs | 126 +++++------- tests/GraphBLAS-sharp.Tests/Program.fs | 190 +++++++++--------- 24 files changed, 435 insertions(+), 386 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 80e4f5a9..211984f5 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -588,8 +588,7 @@ module ClArray = processor.Post( Msg.MsgSetArguments - (fun () -> - kernel.KernelFunc ndRange targetPosition sourceArray.Length sourceArray targetArray) + (fun () -> kernel.KernelFunc ndRange targetPosition sourceArray.Length sourceArray targetArray) ) processor.Post(Msg.CreateRunMsg<_, _>(kernel)) @@ -632,13 +631,17 @@ module ClArray = let kernel = clContext.Compile fill fun (processor: MailboxProcessor<_>) value firstPosition count (targetArray: ClArray<'a>) -> - if count = 0 then () + if count = 0 then + () else if firstPosition + count > targetArray.Length then failwith "The array should fit completely" - if firstPosition < 0 then failwith "The starting position cannot be less than zero" - if count < 0 then failwith "The count cannot be less than zero" + if firstPosition < 0 then + failwith "The starting position cannot be less than zero" + + if count < 0 then + failwith "The count cannot be less than zero" let ndRange = Range1D.CreateValid(count, workGroupSize) @@ -646,8 +649,7 @@ module ClArray = let kernel = kernel.GetKernel() processor.Post( - Msg.MsgSetArguments - (fun () -> kernel.KernelFunc ndRange firstPosition count value targetArray) + Msg.MsgSetArguments(fun () -> kernel.KernelFunc ndRange firstPosition count value targetArray) ) processor.Post(Msg.CreateRunMsg<_, _>(kernel)) @@ -660,7 +662,8 @@ module ClArray = let incGather = Gather.runInit Map.inc clContext workGroupSize - let map = map2 clContext workGroupSize <@ fun first second -> (first, second) @> + let map = + map2 clContext workGroupSize <@ fun first second -> (first, second) @> fun (processor: MailboxProcessor<_>) allocationMode (values: ClArray<'a>) -> if values.Length > 1 then @@ -676,10 +679,12 @@ module ClArray = incGather processor values secondItems - let result = map processor allocationMode firstItems secondItems + let result = + map processor allocationMode firstItems secondItems firstItems.Free processor secondItems.Free processor Some result - else None + else + None diff --git a/src/GraphBLAS-sharp.Backend/Common/Sum.fs b/src/GraphBLAS-sharp.Backend/Common/Sum.fs index df2b3c1b..d243d14e 100644 --- a/src/GraphBLAS-sharp.Backend/Common/Sum.fs +++ b/src/GraphBLAS-sharp.Backend/Common/Sum.fs @@ -567,7 +567,8 @@ module Reduce = (prefixSum processor resultPositions) .ToHostAndFree processor - if resultLength = 0 then None + if resultLength = 0 then + None else // write values let resultValues = @@ -586,7 +587,8 @@ module Reduce = reducedKeys.Free processor resultPositions.Free processor - Some (resultValues, resultKeys) + Some(resultValues, resultKeys) + module ByKey2D = /// /// Reduce an array of values by 2D keys using a single work item. @@ -845,7 +847,8 @@ module Reduce = (prefixSum processor resultPositions) .ToHostAndFree processor - if resultLength = 0 then None + if resultLength = 0 then + None else // write value let resultValues = @@ -873,4 +876,4 @@ module Reduce = resultPositions.Free processor - Some (resultValues, resultFirstKeys, resultSecondKeys) + Some(resultValues, resultFirstKeys, resultSecondKeys) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index fe28d499..d6009d01 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -162,7 +162,7 @@ module Matrix = Rows = rows NNZ = matrix.NNZ } - let getRowsLength (clContext: ClContext) workGroupSize = + let NNZInRows (clContext: ClContext) workGroupSize = let pairwise = ClArray.pairwise clContext workGroupSize @@ -173,10 +173,11 @@ module Matrix = let pointerPairs = pairwise processor DeviceOnly matrix.RowPointers // since row pointers length in matrix always >= 2 - |> Option.defaultWith (fun () -> - failwith "The state of the matrix is broken. The length of the rowPointers must be >= 2") + |> Option.defaultWith + (fun () -> failwith "The state of the matrix is broken. The length of the rowPointers must be >= 2") - let rowsLength = subtract processor allocationMode pointerPairs + let rowsLength = + subtract processor allocationMode pointerPairs pointerPairs.Free processor diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index fda92183..be3f5521 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -44,7 +44,7 @@ module Matrix = Rows = copy processor allocationMode m.Rows ColumnPointers = copy processor allocationMode m.ColumnPointers Values = copyData processor allocationMode m.Values } - | ClMatrix.Rows matrix -> + | ClMatrix.LIL matrix -> matrix.Rows |> Array.map ( Option.bind @@ -56,7 +56,7 @@ module Matrix = ColumnCount = matrix.ColumnCount Rows = rows NNZ = matrix.NNZ } - |> ClMatrix.Rows + |> ClMatrix.LIL /// /// Creates a new matrix, represented in CSR format, that is equal to the given one. @@ -82,7 +82,7 @@ module Matrix = m.ToCSR |> transpose processor allocationMode |> ClMatrix.CSR - | ClMatrix.Rows m -> + | ClMatrix.LIL m -> rowsToCSR processor allocationMode m |> ClMatrix.CSR @@ -136,7 +136,7 @@ module Matrix = |> toCOO processor allocationMode |> transposeInPlace processor |> ClMatrix.COO - | ClMatrix.Rows m -> + | ClMatrix.LIL m -> rowsToCSR processor allocationMode m |> toCOO processor allocationMode |> ClMatrix.COO @@ -183,7 +183,8 @@ module Matrix = let transposeCOO = COO.Matrix.transpose clContext workGroupSize - let rowsToCSR = Rows.Matrix.toCSR clContext workGroupSize + let rowsToCSR = + Rows.Matrix.toCSR clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with @@ -196,7 +197,7 @@ module Matrix = |> COOtoCSR processor allocationMode) .ToCSC |> ClMatrix.CSC - | ClMatrix.Rows m -> + | ClMatrix.LIL m -> rowsToCSR processor allocationMode m |> transposeCSR processor allocationMode |> fun m -> m.ToCSC @@ -241,7 +242,8 @@ module Matrix = let transposeCSR = CSR.Matrix.transposeInPlace clContext workGroupSize - let CSRToRows = CSR.Matrix.toRows clContext workGroupSize + let CSRToRows = + CSR.Matrix.toRows clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with @@ -249,15 +251,15 @@ module Matrix = m.ToCSR |> transposeCSR processor allocationMode |> CSRToRows processor allocationMode - |> ClMatrix.Rows + |> ClMatrix.LIL | ClMatrix.CSR m -> CSRToRows processor allocationMode m - |> ClMatrix.Rows + |> ClMatrix.LIL | ClMatrix.COO m -> COOToCSR processor allocationMode m |> CSRToRows processor allocationMode - |> ClMatrix.Rows - | ClMatrix.Rows _ -> copy processor allocationMode matrix + |> ClMatrix.LIL + | ClMatrix.LIL _ -> copy processor allocationMode matrix let map (clContext: ClContext) (opAdd: Expr<'a option -> 'b option>) workGroupSize = let mapCOO = @@ -363,7 +365,7 @@ module Matrix = | ClMatrix.COO m -> COOTransposeInPlace processor m |> ClMatrix.COO | ClMatrix.CSR m -> ClMatrix.CSC m.ToCSC | ClMatrix.CSC m -> ClMatrix.CSR m.ToCSR - | ClMatrix.Rows _ -> failwith "Not yet implemented" + | ClMatrix.LIL _ -> failwith "Not yet implemented" /// /// Transposes the given matrix and returns result as a new matrix. @@ -406,7 +408,7 @@ module Matrix = Columns = copy processor allocationMode m.Rows Values = copyData processor allocationMode m.Values } |> ClMatrix.CSR - | ClMatrix.Rows _ -> failwith "Not yet implemented" + | ClMatrix.LIL _ -> failwith "Not yet implemented" module SpGeMM = let masked @@ -437,5 +439,6 @@ module Matrix = fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix<'a>) (rightMatrix: ClMatrix<'b>) -> match leftMatrix, rightMatrix with | ClMatrix.CSR leftMatrix, ClMatrix.CSR rightMatrix -> - ClMatrix.Rows <| run processor allocationMode leftMatrix rightMatrix + ClMatrix.LIL + <| run processor allocationMode leftMatrix rightMatrix | _ -> failwith "Matrix formats are not matching" diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs index 2f9a0a72..b7bea530 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs @@ -17,15 +17,17 @@ module Matrix = let concatValues = ClArray.concat clContext workGroupSize - fun (processor: MailboxProcessor<_>) allocationMode (matrix: Rows<'a>) -> + fun (processor: MailboxProcessor<_>) allocationMode (matrix: LIL<'a>) -> let rowsPointers = matrix.Rows - |> Array.map (function None -> 0 | Some vector -> vector.Values.Length) + |> Array.map + (function + | None -> 0 + | Some vector -> vector.Values.Length) // prefix sum |> Array.scan (+) 0 - |> fun pointers -> - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, pointers) + |> fun pointers -> clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, pointers) let valuesByRows, columnsIndicesByRows = matrix.Rows @@ -45,5 +47,3 @@ module Matrix = RowPointers = rowsPointers Columns = columnsIndices Values = values } - - diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index 30308585..214e8a49 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -29,7 +29,7 @@ module Expand = fun (processor: MailboxProcessor<_>) (leftMatrixRow: ClVector.Sparse<'a>) (rightMatrixRowsLengths: ClArray) -> let segmentsLengths = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, leftMatrixRow.Indices.Length) + clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, leftMatrixRow.NNZ) // extract needed lengths by left matrix nnz gather processor leftMatrixRow.Indices rightMatrixRowsLengths segmentsLengths @@ -70,9 +70,9 @@ module Expand = let rightMatrixGather = Gather.run clContext workGroupSize fun (processor: MailboxProcessor<_>) length (segmentsPointers: Indices) (leftMatrixRow: ClVector.Sparse<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> - if length = 0 then None + if length = 0 then + None else - printfn "expand length: %A" length // Compute left matrix positions let leftMatrixPositions = zeroCreate processor DeviceOnly length @@ -124,7 +124,7 @@ module Expand = rightMatrixPositions.Free processor // left, right matrix values, columns indices - Some (leftMatrixValues, rightMatrixValues, columns) + Some(leftMatrixValues, rightMatrixValues, columns) let multiply (clContext: ClContext) workGroupSize (predicate: Expr<'a -> 'b -> 'c option>) = let getBitmap = @@ -149,7 +149,8 @@ module Expand = (prefixSum processor positions) .ToHostAndFree(processor) - if resultLength = 0 then None + if resultLength = 0 then + None else let resultIndices = clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, resultLength) @@ -161,7 +162,7 @@ module Expand = assignValues processor firstValues secondValues positions resultValues - Some (resultValues, resultIndices) + Some(resultValues, resultIndices) let sortByColumns (clContext: ClContext) workGroupSize = @@ -236,8 +237,6 @@ module Expand = let length, segmentPointers = getSegmentPointers processor leftMatrixRow leftMatrixRowsLengths - if length < 0 then failwith "length < 0" - // expand let expandResult = expand processor length segmentPointers leftMatrixRow rightMatrix @@ -245,72 +244,85 @@ module Expand = segmentPointers.Free processor expandResult - |> Option.bind (fun (leftMatrixValues, rightMatrixValues, columns) -> - // multiplication - let mulResult = - multiply processor leftMatrixValues rightMatrixValues columns - - leftMatrixValues.Free processor - rightMatrixValues.Free processor - columns.Free processor - - // check multiplication result - mulResult - |> Option.bind (fun (resultValues, resultColumns) -> - // sort - let sortedValues, sortedColumns = - sort processor resultValues resultColumns - - resultValues.Free processor - resultColumns.Free processor - - let reduceResult = - reduce processor allocationMode sortedValues sortedColumns - - sortedValues.Free processor - sortedColumns.Free processor - - // create sparse vector (TODO(empty vector)) - reduceResult - |> Option.bind (fun (values, columns) -> - { Context = clContext - Indices = columns - Values = values - Size = rightMatrix.ColumnCount } - |> Some))) - - let run<'a, 'b, 'c when 'a : struct and 'b : struct and 'c : struct> + |> Option.bind + (fun (leftMatrixValues, rightMatrixValues, columns) -> + // multiplication + let mulResult = + multiply processor leftMatrixValues rightMatrixValues columns + + leftMatrixValues.Free processor + rightMatrixValues.Free processor + columns.Free processor + + // check multiplication result + mulResult + |> Option.bind + (fun (resultValues, resultColumns) -> + // sort + let sortedValues, sortedColumns = + sort processor resultValues resultColumns + + resultValues.Free processor + resultColumns.Free processor + + let reduceResult = + reduce processor allocationMode sortedValues sortedColumns + + sortedValues.Free processor + sortedColumns.Free processor + + // create sparse vector (TODO(empty vector)) + reduceResult + |> Option.bind + (fun (values, columns) -> + { Context = clContext + Indices = columns + Values = values + Size = rightMatrix.ColumnCount } + |> Some))) + + let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> (clContext: ClContext) workGroupSize opAdd - (opMul: Expr<'a -> 'b -> 'c option>) = + (opMul: Expr<'a -> 'b -> 'c option>) + = - let getRowsLength = - CSR.Matrix.getRowsLength clContext workGroupSize + let getNNZInRows = + CSR.Matrix.NNZInRows clContext workGroupSize - let split = CSR.Matrix.byRowsLazy clContext workGroupSize + let split = + CSR.Matrix.byRowsLazy clContext workGroupSize - let runRow = runRow clContext workGroupSize opAdd opMul + let runRow = + runRow clContext workGroupSize opAdd opMul fun (processor: MailboxProcessor<_>) allocationMode (leftMatrix: ClMatrix.CSR<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> let rightMatrixRowsLengths = - getRowsLength processor DeviceOnly rightMatrix - - printfn "right matrix rows lengths: %A" <| rightMatrixRowsLengths.ToHost processor + getNNZInRows processor DeviceOnly rightMatrix let runRow = runRow processor allocationMode rightMatrix rightMatrixRowsLengths - rightMatrixRowsLengths.Free processor - split processor allocationMode leftMatrix |> Seq.map (fun lazyRow -> Option.bind runRow lazyRow.Value) |> Seq.toArray |> fun rows -> - { Rows.Context = clContext + rightMatrixRowsLengths.Free processor + + // compute nnz + let nnz = + rows + |> Array.fold + (fun count -> + function + | Some row -> count + row.Size + | None -> count) + 0 + + { LIL.Context = clContext RowCount = leftMatrix.RowCount ColumnCount = rightMatrix.ColumnCount Rows = rows - NNZ = -1 } // TODO(nnz count) - + NNZ = nnz } diff --git a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs index ebc7c81f..e2a1d76a 100644 --- a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs @@ -6,7 +6,7 @@ type MatrixFormat = | CSR | COO | CSC - | Rows + | LIL module ClMatrix = type CSR<'elem when 'elem: struct> = @@ -82,12 +82,12 @@ module ClMatrix = member this.NNZ = this.Values.Length - type Rows<'elem when 'elem: struct> = + type LIL<'elem when 'elem: struct> = { Context: ClContext RowCount: int ColumnCount: int Rows: ClVector.Sparse<'elem> option [] - NNZ: int } // TODO(empty vector) (or only some with row index ???) + NNZ: int } interface IDeviceMemObject with member this.Dispose q = @@ -117,32 +117,32 @@ type ClMatrix<'a when 'a: struct> = | CSR of ClMatrix.CSR<'a> | COO of ClMatrix.COO<'a> | CSC of ClMatrix.CSC<'a> - | Rows of ClMatrix.Rows<'a> + | LIL of ClMatrix.LIL<'a> member this.RowCount = match this with | ClMatrix.CSR matrix -> matrix.RowCount | ClMatrix.COO matrix -> matrix.RowCount | ClMatrix.CSC matrix -> matrix.RowCount - | ClMatrix.Rows matrix -> matrix.RowCount + | ClMatrix.LIL matrix -> matrix.RowCount member this.ColumnCount = match this with | ClMatrix.CSR matrix -> matrix.ColumnCount | ClMatrix.COO matrix -> matrix.ColumnCount | ClMatrix.CSC matrix -> matrix.ColumnCount - | ClMatrix.Rows matrix -> matrix.ColumnCount + | ClMatrix.LIL matrix -> matrix.ColumnCount member this.Dispose q = match this with | ClMatrix.CSR matrix -> (matrix :> IDeviceMemObject).Dispose q | ClMatrix.COO matrix -> (matrix :> IDeviceMemObject).Dispose q | ClMatrix.CSC matrix -> (matrix :> IDeviceMemObject).Dispose q - | ClMatrix.Rows matrix -> (matrix :> IDeviceMemObject).Dispose q + | ClMatrix.LIL matrix -> (matrix :> IDeviceMemObject).Dispose q member this.NNZ = match this with | ClMatrix.CSR matrix -> matrix.NNZ | ClMatrix.COO matrix -> matrix.NNZ | ClMatrix.CSC matrix -> matrix.NNZ - | ClMatrix.Rows matrix -> matrix.NNZ + | ClMatrix.LIL matrix -> matrix.NNZ diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs b/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs index 561f8993..d779ba5a 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs @@ -28,6 +28,6 @@ module Convert = <@ fun rightItem -> (%op) None rightItem @> let map2ToMapRightNone (op: Expr<'a option -> 'b option -> 'c option>) = - <@ fun leftItem -> (%op) leftItem None @> + <@ fun leftItem -> (%op) leftItem None @> let map2ToNoneNone (op: Expr<'a option -> 'b option -> 'c option>) = <@ (%op) None None @> diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs index 7cb77404..08b706c5 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs @@ -110,7 +110,8 @@ module internal Map = let scatter = Scatter.lastOccurrence clContext workGroupSize - let setOption = ClArray.assignOption clContext workGroupSize op + let setOption = + ClArray.assignOption clContext workGroupSize op fun (processor: MailboxProcessor<_>) allocationMode (vector: ClVector.Sparse<'a>) -> diff --git a/src/GraphBLAS-sharp/Objects/Matrix.fs b/src/GraphBLAS-sharp/Objects/Matrix.fs index b064356a..8775731b 100644 --- a/src/GraphBLAS-sharp/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp/Objects/Matrix.fs @@ -135,7 +135,7 @@ module Matrix = ColumnPointers = context.CreateClArray this.ColumnPointers Values = context.CreateClArray this.Values } - type Rows<'a when 'a : struct> = + type Rows<'a when 'a: struct> = { RowCount: int ColumnCount: int Rows: Vector.Sparse<'a> option [] @@ -146,12 +146,15 @@ module Matrix = let rows = [ for i in 0 .. Array2D.length1 array - 1 do - let vector = Vector.Sparse.FromArray(array.[i, *], isZero) + let vector = + Vector.Sparse.FromArray(array.[i, *], isZero) - nnz <- nnz + vector.NNZ + nnz <- nnz + vector.NNZ - if vector.NNZ > 0 then Some vector - else None ] + if vector.NNZ > 0 then + Some vector + else + None ] |> Array.ofList { RowCount = Array2D.length1 array @@ -163,8 +166,7 @@ module Matrix = let rows = this.Rows - |> Array.map (Option.bind - (fun vector -> Some <| vector.ToDevice(context))) + |> Array.map (Option.bind (fun vector -> Some <| vector.ToDevice(context))) { Context = context RowCount = this.RowCount @@ -210,4 +212,4 @@ type Matrix<'a when 'a: struct> = | COO matrix -> ClMatrix.COO <| matrix.ToDevice context | CSR matrix -> ClMatrix.CSR <| matrix.ToDevice context | CSC matrix -> ClMatrix.CSC <| matrix.ToDevice context - | Rows matrix -> ClMatrix.Rows <| matrix.ToDevice context + | Rows matrix -> ClMatrix.LIL <| matrix.ToDevice context diff --git a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs index 0a90c4c3..f4bfb15d 100644 --- a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs +++ b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs @@ -15,14 +15,14 @@ module MatrixExtensions = ColumnCount = m.ColumnCount Rows = m.Rows.ToHost q Columns = m.Columns.ToHost q - Values = m.Values.ToHost q } + Values = m.Values.ToHost q } |> Matrix.COO | ClMatrix.CSR m -> { RowCount = m.RowCount ColumnCount = m.ColumnCount RowPointers = m.RowPointers.ToHost q - ColumnIndices = m.Columns.ToHost q - Values = m.Values.ToHost q } + ColumnIndices = m.Columns.ToHost q + Values = m.Values.ToHost q } |> Matrix.CSR | ClMatrix.CSC m -> { RowCount = m.RowCount @@ -31,12 +31,12 @@ module MatrixExtensions = ColumnPointers = m.ColumnPointers.ToHost q Values = m.Values.ToHost q } |> Matrix.CSC - | ClMatrix.Rows m -> + | ClMatrix.LIL m -> { RowCount = m.RowCount ColumnCount = m.ColumnCount Rows = - m.Rows - |> Array.map (Option.bind (fun row -> Some <| row.ToHost q)) + m.Rows + |> Array.map (Option.bind (fun row -> Some <| row.ToHost q)) NNZ = m.NNZ } |> Matrix.Rows diff --git a/src/GraphBLAS-sharp/Objects/VectorExtensions.fs b/src/GraphBLAS-sharp/Objects/VectorExtensions.fs index 23d40b26..4bdb6a01 100644 --- a/src/GraphBLAS-sharp/Objects/VectorExtensions.fs +++ b/src/GraphBLAS-sharp/Objects/VectorExtensions.fs @@ -14,6 +14,5 @@ module ClVectorExtensions = type ClVector<'a when 'a: struct> with member this.ToHost(q: MailboxProcessor<_>) = match this with - | ClVector.Sparse vector -> - Vector.Sparse <| vector.ToHost q + | ClVector.Sparse vector -> Vector.Sparse <| vector.ToHost q | ClVector.Dense vector -> Vector.Dense <| vector.ToHost q diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs index 65f2c0c5..092e3cb8 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs @@ -17,8 +17,7 @@ let config = let makeTest<'a> isEqual testFun (source: 'a [], target: 'a [], targetPosition: int) = - if source.Length > 0 - && target.Length > 0 then + if source.Length > 0 && target.Length > 0 then let clSource = context.CreateClArray source let clTarget = context.CreateClArray target @@ -34,7 +33,7 @@ let makeTest<'a> isEqual testFun (source: 'a [], target: 'a [], targetPosition: "Results should be the same" |> Utils.compareArrays isEqual actual target -let createTest<'a when 'a : equality> isEqual = +let createTest<'a when 'a: equality> isEqual = ClArray.assign context Utils.defaultWorkGroupSize |> makeTest<'a> isEqual |> testPropertyWithConfig config $"test on %A{typeof<'a>}" @@ -43,7 +42,7 @@ let tests = [ createTest (=) if Utils.isFloat64Available context.ClDevice then - createTest Utils.floatIsEqual + createTest Utils.floatIsEqual createTest Utils.float32IsEqual createTest (=) ] diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs index 4e807e8f..d27cdebf 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs @@ -16,7 +16,8 @@ let config = Utils.defaultConfig let makeTest<'a> isEqual testFun (arrays: 'a [] []) = if Seq.length arrays > 0 - && arrays |> Seq.forall (fun array -> array.Length > 0) then + && arrays + |> Seq.forall (fun array -> array.Length > 0) then let clArrays = arrays |> Seq.map context.CreateClArray @@ -24,7 +25,9 @@ let makeTest<'a> isEqual testFun (arrays: 'a [] []) = // release let actual = clActual.ToHostAndFree processor - clArrays |> Seq.iter (fun array -> array.Free processor) + + clArrays + |> Seq.iter (fun array -> array.Free processor) let expected = Seq.concat arrays |> Seq.toArray @@ -40,7 +43,7 @@ let tests = [ createTest (=) if Utils.isFloat64Available context.ClDevice then - createTest Utils.floatIsEqual + createTest Utils.floatIsEqual createTest Utils.float32IsEqual createTest (=) ] diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs index 196d89f6..0921ff26 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs @@ -16,7 +16,7 @@ let config = { Utils.defaultConfig with arbitrary = [ typeof ] } -let makeTest<'a> isEqual testFun (value: 'a, targetPosition, count, target: 'a [] ) = +let makeTest<'a> isEqual testFun (value: 'a, targetPosition, count, target: 'a []) = if target.Length > 0 then let clTarget = context.CreateClArray target @@ -42,7 +42,7 @@ let tests = [ createTest (=) if Utils.isFloat64Available context.ClDevice then - createTest (=) + createTest (=) createTest (=) createTest (=) ] diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs index e0ed32d7..5bd6957d 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs @@ -16,7 +16,7 @@ let config = { Utils.defaultConfig with arbitrary = [ typeof ] } -let makeTest<'a> isEqual testFun (array: 'a [] ) = +let makeTest<'a> isEqual testFun (array: 'a []) = if array.Length > 0 then let clArray = context.CreateClArray array @@ -42,7 +42,7 @@ let tests = [ createTest (=) if Utils.isFloat64Available context.ClDevice then - createTest (=) + createTest (=) createTest (=) createTest (=) ] diff --git a/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs b/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs index 9226fd9b..75e0b9dd 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs @@ -368,11 +368,11 @@ let sequentialSegment2DTests = // segments sequential Option let createReduceOp reduceOp left right = - match left, right with - | Some left, Some right -> reduceOp left right - | Some value, None - | None, Some value -> Some value - | _ -> None + match left, right with + | Some left, Some right -> reduceOp left right + | Some value, None + | None, Some value -> Some value + | _ -> None let checkResultOption isEqual keys values reduceOp actual = @@ -401,10 +401,9 @@ let checkResultOption isEqual keys values reduceOp actual = "Values must the same" |> Utils.compareArrays isEqual actualValues expectedValues - | None -> - Expect.isTrue (expectedValues.Length = 0) "Result should be Some _" + | None -> Expect.isTrue (expectedValues.Length = 0) "Result should be Some _" -let testOption<'a> isEqual reduceOp testFun (array: (int * 'a) []) = +let testOption<'a> isEqual reduceOp testFun (array: (int * 'a) []) = if array.Length > 0 then let array = Array.sortBy fst array @@ -422,12 +421,13 @@ let testOption<'a> isEqual reduceOp testFun (array: (int * 'a) []) = context.CreateClArrayWithSpecificAllocationMode(DeviceOnly, values) testFun processor HostInterop offsets.Length clOffsets clKeys clValues - |> Option.bind (fun ((clActualValues, clActualKeys): ClArray<_> * ClArray<_>) -> - let actualValues = clActualValues.ToHostAndFree processor - let actualKeys = clActualKeys.ToHostAndFree processor + |> Option.bind + (fun ((clActualValues, clActualKeys): ClArray<_> * ClArray<_>) -> + let actualValues = clActualValues.ToHostAndFree processor + let actualKeys = clActualKeys.ToHostAndFree processor - Some (actualValues, actualKeys)) - |> checkResultOption isEqual keys values reduceOp + Some(actualValues, actualKeys)) + |> checkResultOption isEqual keys values reduceOp let createTestOption (isEqual: 'a -> 'a -> bool) (reduceOpQ, reduceOp) = Reduce.ByKey.Option.segmentSequential context Utils.defaultWorkGroupSize reduceOpQ @@ -504,16 +504,17 @@ let test2DOption<'a> isEqual reduceOp reduce (array: (int * int * 'a) []) = context.CreateClArrayWithSpecificAllocationMode(DeviceOnly, values) reduce processor DeviceOnly offsets.Length clOffsets clFirstKeys clSecondKeys clValues - |> Option.bind (fun ((clReducedValues, clFirstActualKeys, clSecondActualKeys): ClArray<'a> * ClArray * ClArray) -> - let reducedFirstKeys = - clFirstActualKeys.ToHostAndFree processor + |> Option.bind + (fun ((clReducedValues, clFirstActualKeys, clSecondActualKeys): ClArray<'a> * ClArray * ClArray) -> + let reducedFirstKeys = + clFirstActualKeys.ToHostAndFree processor - let reducedSecondKeys = - clSecondActualKeys.ToHostAndFree processor + let reducedSecondKeys = + clSecondActualKeys.ToHostAndFree processor - let reducedValues = clReducedValues.ToHostAndFree processor + let reducedValues = clReducedValues.ToHostAndFree processor - Some (reducedValues, reducedFirstKeys, reducedSecondKeys)) + Some(reducedValues, reducedFirstKeys, reducedSecondKeys)) |> checkResult2DOption isEqual firstKeys secondKeys values reduceOp let createTest2DOption (isEqual: 'a -> 'a -> bool) (reduceOpQ, reduceOp) = diff --git a/tests/GraphBLAS-sharp.Tests/Common/Sort/Radix.fs b/tests/GraphBLAS-sharp.Tests/Common/Sort/Radix.fs index 049568c5..2f565f3e 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/Sort/Radix.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/Sort/Radix.fs @@ -1,4 +1,4 @@ -namespace GraphBLAS.FSharp.Tests.Backend.Common.Sort +module GraphBLAS.FSharp.Tests.Backend.Common.Sort.Radix open Expecto open GraphBLAS.FSharp.Backend.Common.Sort @@ -7,75 +7,77 @@ open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions open Brahma.FSharp open GraphBLAS.FSharp.Backend.Objects.ClContext -module Radix = - let config = - { Utils.defaultConfig with - startSize = 1000000 } +let config = + { Utils.defaultConfig with + startSize = 1000000 } - let workGroupSize = Utils.defaultWorkGroupSize +let workGroupSize = Utils.defaultWorkGroupSize - let processor = Context.defaultContext.Queue +let processor = Context.defaultContext.Queue - let context = Context.defaultContext.ClContext +let context = Context.defaultContext.ClContext - let checkResultByKeys (inputArray: (int * 'a) []) (actualValues: 'a []) = - let expectedValues = Seq.sortBy fst inputArray |> Seq.map snd +let checkResultByKeys (inputArray: (int * 'a) []) (actualValues: 'a []) = + let expectedValues = Seq.sortBy fst inputArray |> Seq.map snd - "Values must be the same" - |> Expect.sequenceEqual expectedValues actualValues + "Values must be the same" + |> Expect.sequenceEqual expectedValues actualValues - let makeTestByKeys<'a when 'a: equality> sortFun (array: (int * 'a) []) = +let makeTestByKeys<'a when 'a: equality> sortFun (array: (int * 'a) []) = - if array.Length > 0 then - let keys = Array.map fst array - let values = Array.map snd array + if array.Length > 0 then + let keys = Array.map fst array + let values = Array.map snd array - let clKeys = keys.ToDevice context - let clValues = values.ToDevice context + let clKeys = keys.ToDevice context + let clValues = values.ToDevice context - let clActualValues: ClArray<'a> = - sortFun processor HostInterop clKeys clValues + let clActualValues: ClArray<'a> = + sortFun processor HostInterop clKeys clValues - let actualValues = clActualValues.ToHostAndFree processor + let actualValues = clActualValues.ToHostAndFree processor - checkResultByKeys array actualValues + checkResultByKeys array actualValues - let createTestByKeys<'a when 'a: equality and 'a: struct> = - let sort = - Radix.runByKeysStandard context workGroupSize +let createTestByKeys<'a when 'a: equality and 'a: struct> = + let sort = + Radix.runByKeysStandard context workGroupSize - makeTestByKeys<'a> sort - |> testPropertyWithConfig config $"test on {typeof<'a>}" + makeTestByKeys<'a> sort + |> testPropertyWithConfig config $"test on {typeof<'a>}" - let testByKeys = - [ createTestByKeys - createTestByKeys +let testByKeys = + [ createTestByKeys + createTestByKeys - if Utils.isFloat64Available context.ClDevice then - createTestByKeys + if Utils.isFloat64Available context.ClDevice then + createTestByKeys - createTestByKeys - createTestByKeys ] - |> testList "Radix sort by keys" + createTestByKeys + createTestByKeys ] + |> testList "Radix sort by keys" - let makeTestKeysOnly sort (keys: uint []) = - if keys.Length > 0 then - let keys = Array.map int keys +let makeTestKeysOnly sort (keys: uint []) = + if keys.Length > 0 then + let keys = Array.map int keys - let clKeys = keys.ToDevice context + let clKeys = keys.ToDevice context - let actual = - (sort processor clKeys: ClArray) - .ToHostAndFree processor + let actual = + (sort processor clKeys: ClArray) + .ToHostAndFree processor - let expected = Array.sort keys + let expected = Array.sort keys - "Keys must be the same" - |> Expect.sequenceEqual expected actual + "Keys must be the same" + |> Expect.sequenceEqual expected actual - let testKeysOnly = - let sort = - Radix.standardRunKeysOnly context workGroupSize +let testKeysOnly = + let sort = + Radix.standardRunKeysOnly context workGroupSize - makeTestKeysOnly sort - |> testPropertyWithConfig config $"keys only" + makeTestKeysOnly sort + |> testPropertyWithConfig config $"keys only" + +let allTests = + testList "Radix" [ testKeysOnly; testByKeys ] diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index 3d4c3e37..7616b6cd 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -570,9 +570,7 @@ module Generators = type ArrayOfDistinctKeys() = static let arrayOfDistinctKeysGenerator (keysGenerator: Gen<'n>) (valuesGenerator: Gen<'a>) = let tuplesGenerator = - Gen.zip - <| keysGenerator - <| valuesGenerator + Gen.zip <| keysGenerator <| valuesGenerator gen { let! length = Gen.sized <| fun size -> Gen.choose (1, size) @@ -1079,13 +1077,13 @@ module Generators = gen { let! value = valuesGenerator - let! targetArrayLength = Gen.sized <| fun size -> Gen.choose(1, size + 1) + let! targetArrayLength = Gen.sized <| fun size -> Gen.choose (1, size + 1) let! targetArray = Gen.arrayOfLength targetArrayLength valuesGenerator let! targetPosition = Gen.choose (0, targetArrayLength) - let! targetCount = Gen.choose(0, targetArrayLength - targetPosition) + let! targetCount = Gen.choose (0, targetArrayLength - targetPosition) return (value, targetPosition, targetCount, targetArray) } diff --git a/tests/GraphBLAS-sharp.Tests/Helpers.fs b/tests/GraphBLAS-sharp.Tests/Helpers.fs index 751bc6fe..e177a50c 100644 --- a/tests/GraphBLAS-sharp.Tests/Helpers.fs +++ b/tests/GraphBLAS-sharp.Tests/Helpers.fs @@ -63,7 +63,7 @@ module Utils = | CSC -> Matrix.CSC <| Matrix.CSC.FromArray2D(array, isZero) - | Rows -> + | LIL -> Matrix.Rows <| Matrix.Rows.FromArray2D(array, isZero) @@ -120,6 +120,32 @@ module Utils = Actual value is %A{actual.[i, j]}, expected %A{expected.[i, j]}" |> failtestf "%s" + let compareSparseVectors isEqual (actual: Vector.Sparse<'a>) (expected: Vector.Sparse<'a>) = + "Sparse vector size must be the same" + |> Expect.equal actual.Size expected.Size + + "Value must be the same" + |> compareArrays isEqual actual.Values expected.Values + + "Indices must be the same" + |> compareArrays (=) actual.Indices expected.Indices + + let compareLILMatrix isEqual (actual: Matrix.Rows<'a>) (expected: Matrix.Rows<'a>) = + "Column count must be the same" + |> Expect.equal actual.ColumnCount expected.ColumnCount + + "Rows count must be the same" + |> Expect.equal actual.RowCount expected.RowCount + + Array.iter2 + (fun actualRow expected -> + match actualRow, expected with + | Some actualVector, Some expectedVector -> compareSparseVectors isEqual actualVector expectedVector + | None, None -> () + | _ -> failwith "Rows are not matching") + <| actual.Rows + <| expected.Rows + let listOfUnionCases<'a> = FSharpType.GetUnionCases typeof<'a> |> Array.map (fun caseInfo -> FSharpValue.MakeUnion(caseInfo, [||]) :?> 'a) diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs index a62dade9..058337d0 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs @@ -48,13 +48,15 @@ let makeTest context q formatFrom formatTo convertFun isZero (array: 'a [,]) = "Matrices should be equal" |> Expect.equal actual expected -let createTest<'a when 'a : struct and 'a : equality> convertFun formatTo (isZero: 'a -> bool) = - let convertFun = convertFun context Utils.defaultWorkGroupSize +let createTest<'a when 'a: struct and 'a: equality> convertFun formatTo (isZero: 'a -> bool) = + let convertFun = + convertFun context Utils.defaultWorkGroupSize Utils.listOfUnionCases - |> List.map (fun formatFrom -> - makeTest context q formatFrom formatTo convertFun isZero - |> testPropertyWithConfig { config with endSize = 10 } $"test on %A{typeof<'a>} from %A{formatFrom}") + |> List.map + (fun formatFrom -> + makeTest context q formatFrom formatTo convertFun isZero + |> testPropertyWithConfig { config with endSize = 10 } $"test on %A{typeof<'a>} from %A{formatFrom}") let testFixtures formatTo = match formatTo with @@ -67,7 +69,7 @@ let testFixtures formatTo = | CSC -> [ createTest Matrix.toCSC formatTo ((=) 0) createTest Matrix.toCSC formatTo ((=) false) ] - | Rows -> + | LIL -> [ createTest Matrix.toRows formatTo ((=) 0) createTest Matrix.toRows formatTo ((=) false) ] |> List.concat diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs b/tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs index 847c7f74..6aab0988 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs @@ -30,15 +30,27 @@ let makeTest isZero testFun (array: 'a [,]) = let actual = clActual.ToHostAndFree processor let expected = - matrix.RowPointers - |> Array.pairwise - |> Array.map (fun (fst, snd) -> snd - fst) + Array.zeroCreate <| Array2D.length1 array + + // count nnz in each row + for i in 0 .. Array2D.length1 array - 1 do + let nnzRowCount = + array.[i, *] + |> Array.fold + (fun count item -> + if not <| isZero item then + count + 1 + else + count) + 0 + + expected.[i] <- nnzRowCount "Results must be the same" |> Utils.compareArrays (=) actual expected -let createTest<'a when 'a : struct> (isZero: 'a -> bool) = - CSR.Matrix.getRowsLength context Utils.defaultWorkGroupSize +let createTest<'a when 'a: struct> (isZero: 'a -> bool) = + CSR.Matrix.NNZInRows context Utils.defaultWorkGroupSize |> makeTest isZero |> testPropertyWithConfig config $"test on %A{typeof<'a>}" diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs index 952fa08a..71ed17bb 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs @@ -24,8 +24,9 @@ processor.Error.Add(fun e -> failwithf "%A" e) let config = { Utils.defaultConfig with - arbitrary = [ typeof - typeof ] } + arbitrary = + [ typeof + typeof ] } let makeTest isZero testFun (leftArray: 'a [], rightArray: 'a [,]) = @@ -44,8 +45,9 @@ let makeTest isZero testFun (leftArray: 'a [], rightArray: 'a [,]) = |> Array.map (fun (fst, snd) -> snd - fst) let expectedPointers, expectedLength = - Array.init leftMatrixRow.Indices.Length (fun index -> - rightMatrixRowsLength.[leftMatrixRow.Indices[index]]) + Array.init + leftMatrixRow.Indices.Length + (fun index -> rightMatrixRowsLength.[leftMatrixRow.Indices [ index ]]) |> HostPrimitives.prefixSumExclude 0 (+) let clLeftMatrixRow = leftMatrixRow.ToDevice context @@ -100,15 +102,17 @@ let expand (leftMatrixRow: Vector.Sparse<'a>) (rightMatrix: Matrix.CSR<'b>) = Array.map (fun index -> rightMatrix.RowPointers.[index]) leftMatrixRow.Indices let rightMatrixValues = - Array.map2(fun rowPointer segmentLength -> - Array.take segmentLength rightMatrix.Values.[rowPointer..]) - rightMatrixRowPointers segmentsLengths + Array.map2 + (fun rowPointer segmentLength -> Array.take segmentLength rightMatrix.Values.[rowPointer..]) + rightMatrixRowPointers + segmentsLengths |> Array.concat let columns = - Array.map2 (fun rowPointer segmentLength -> - Array.take segmentLength rightMatrix.ColumnIndices.[rowPointer ..]) - rightMatrixRowPointers segmentsLengths + Array.map2 + (fun rowPointer segmentLength -> Array.take segmentLength rightMatrix.ColumnIndices.[rowPointer..]) + rightMatrixRowPointers + segmentsLengths |> Array.concat leftMatrixValues, rightMatrixValues, columns @@ -124,33 +128,30 @@ let makeExpandTest isEqual zero testFun (leftArray: 'a [], rightArray: 'a [,]) = if leftMatrixRow.NNZ > 0 && rightMatrix.NNZ > 0 then let clPointers, lenght = - rightMatrix.RowPointers - |> Array.pairwise - |> Array.map (fun (fst, snd) -> snd - fst) - |> fun rightMatrixRowsLengths -> - Array.init leftMatrixRow.Indices.Length (fun index -> - rightMatrixRowsLengths.[leftMatrixRow.Indices[index]]) + rightMatrix.RowPointers + |> Array.pairwise + |> Array.map (fun (fst, snd) -> snd - fst) + |> fun rightMatrixRowsLengths -> + Array.init + leftMatrixRow.Indices.Length + (fun index -> rightMatrixRowsLengths.[leftMatrixRow.Indices [ index ]]) |> HostPrimitives.prefixSumExclude 0 (+) - |> fun (pointers, length) -> - context.CreateClArray(pointers), length + |> fun (pointers, length) -> context.CreateClArray(pointers), length let clLeftMatrixRow = leftMatrixRow.ToDevice context let clRightMatrix = rightMatrix.ToDevice context - let result - = testFun processor lenght clPointers clLeftMatrixRow clRightMatrix + let result = + testFun processor lenght clPointers clLeftMatrixRow clRightMatrix clLeftMatrixRow.Dispose processor clRightMatrix.Dispose processor clPointers.Free processor - let expectedLeftMatrixValues, expectedRightMatrixValues, expectedColumns = - expand leftMatrixRow rightMatrix + let expectedLeftMatrixValues, expectedRightMatrixValues, expectedColumns = expand leftMatrixRow rightMatrix match result with - | Some (clActualLeftValues: ClArray<'a>, - clActualRightValues: ClArray<'a>, - clActualColumns: ClArray) -> + | Some (clActualLeftValues: ClArray<'a>, clActualRightValues: ClArray<'a>, clActualColumns: ClArray) -> let actualLeftValues = clActualLeftValues.ToHostAndFree processor @@ -175,7 +176,7 @@ let makeExpandTest isEqual zero testFun (leftArray: 'a [], rightArray: 'a [,]) = let createExpandTest isEqual (zero: 'a) testFun = testFun context Utils.defaultWorkGroupSize |> makeExpandTest isEqual zero - |> testPropertyWithConfig { config with endSize = 10 ; maxTest = 100 } $"test on %A{typeof<'a>}" + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" // (Debug only) expand phase tests let expandTests = @@ -189,33 +190,7 @@ let expandTests = createExpandTest (=) 0uy Expand.expand ] |> testList "Expand.expand" -let compareSparseVectors isEqual (actual: Vector.Sparse<'a>) (expected: Vector.Sparse<'a>) = - "Sparse vector size must be the same" - |> Expect.equal actual.Size expected.Size - - "Value must be the same" - |> Utils.compareArrays isEqual actual.Values expected.Values - - "Indices must be the same" - |> Utils.compareArrays (=) actual.Indices expected.Indices - -let compareLILMatrix isEqual (actual: Matrix.Rows<'a>) (expected: Matrix.Rows<'a>) = - "Column count must be the same" - |> Expect.equal actual.ColumnCount expected.ColumnCount - - "Rows count must be the same" - |> Expect.equal actual.RowCount expected.RowCount - - Array.iter2 (fun actualRow expected -> - match actualRow, expected with - | Some actualVector, Some expectedVector -> - compareSparseVectors isEqual actualVector expectedVector - | None, None -> () - | _ -> failwith "Rows are not matching") - <| actual.Rows - <| expected.Rows - -let makeGeneralTest zero isEqual opMul opAdd testFun (leftArray: 'a [,], rightArray: 'a [,]) = +let makeGeneralTest<'a when 'a: struct> zero isEqual opMul opAdd testFun (leftArray: 'a [,], rightArray: 'a [,]) = let leftMatrix = Utils.createMatrixFromArray2D CSR leftArray (isEqual zero) @@ -234,37 +209,38 @@ let makeGeneralTest zero isEqual opMul opAdd testFun (leftArray: 'a [,], rightAr clLeftMatrix.Dispose processor clRightMatrix.Dispose processor - let matrixActual = clMatrixActual.ToHostAndDispose processor + let matrixActual = + clMatrixActual.ToHostAndDispose processor match matrixActual with | Matrix.Rows actual -> HostPrimitives.array2DMultiplication zero opMul opAdd leftArray rightArray |> fun array -> Matrix.Rows.FromArray2D(array, (isEqual zero)) - |> compareLILMatrix isEqual actual + |> Utils.compareLILMatrix isEqual actual | _ -> failwith "Matrix format are not matching" let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = testFun context Utils.defaultWorkGroupSize opAddQ opMulQ - |> makeGeneralTest zero isEqual opMul opAdd - |> testPropertyWithConfig { config with endSize = 10 } $"test on %A{typeof<'a>}" + |> makeGeneralTest<'a> zero isEqual opMul opAdd + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" let generalTests = - [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand - - // if Utils.isFloat64Available context.ClDevice then - // createGeneralTest - // 0.0 - // Utils.floatIsEqual - // ArithmeticOperations.floatAdd - // ArithmeticOperations.floatMul - // Matrix.SpGeMM.expand - // - // createGeneralTest - // 0.0f - // Utils.float32IsEqual - // ArithmeticOperations.float32Add - // ArithmeticOperations.float32Mul - // Matrix.SpGeMM.expand - // createGeneralTest false (=) ArithmeticOperations.boolAdd ArithmeticOperations.boolMul Matrix.SpGeMM.expand ] - ] + [ //createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand + + if Utils.isFloat64Available context.ClDevice then + createGeneralTest + 0.0 + Utils.floatIsEqual + ArithmeticOperations.floatAdd + ArithmeticOperations.floatMul + Matrix.SpGeMM.expand + + createGeneralTest + 0.0f + Utils.float32IsEqual + ArithmeticOperations.float32Add + ArithmeticOperations.float32Mul + Matrix.SpGeMM.expand + + createGeneralTest false (=) ArithmeticOperations.boolAdd ArithmeticOperations.boolMul Matrix.SpGeMM.expand ] |> testList "general" diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index 0fdf40ae..e5fec84a 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -2,98 +2,102 @@ open Expecto open GraphBLAS.FSharp.Tests.Backend open GraphBLAS.FSharp.Tests -// let matrixTests = -// testList -// "Matrix tests" -// [ Matrix.Convert.tests -// Matrix.Map2.addTests -// Matrix.Map2.addAtLeastOneTests -// Matrix.Map2.mulAtLeastOneTests -// Matrix.Map2.addAtLeastOneToCOOTests -// Matrix.Map.notTests -// Matrix.Map.addTests -// Matrix.Map.mulTests -// Matrix.Mxm.tests -// Matrix.Transpose.tests ] -// |> testSequenced -// -// let commonTests = -// let scanTests = -// testList -// "Scan" -// [ Common.Scan.ByKey.sequentialSegmentsTests -// Common.Scan.PrefixSum.tests ] -// -// let reduceTests = -// testList -// "Reduce" -// [ Common.Reduce.ByKey.sequentialTest -// Common.Reduce.ByKey.sequentialSegmentTests -// Common.Reduce.ByKey.oneWorkGroupTest -// Common.Reduce.Reduce.tests -// Common.Reduce.Sum.tests ] -// -// let clArrayTests = -// testList -// "ClArray" -// [ Common.ClArray.RemoveDuplicates.tests -// Common.ClArray.Copy.tests -// Common.ClArray.Replicate.tests -// Common.ClArray.Exists.tests -// Common.ClArray.Map.tests -// Common.ClArray.Map2.addTests -// Common.ClArray.Map2.mulTests -// Common.ClArray.Choose.tests ] -// -// let sortTests = -// testList -// "Sort" -// [ Common.Sort.Bitonic.tests -// Common.Sort.Radix.testsByKeys -// Common.Sort.Radix.testKeysOnly ] -// -// testList -// "Common tests" -// [ clArrayTests -// sortTests -// reduceTests -// scanTests -// Common.Scatter.tests ] -// |> testSequenced -// -// let vectorTests = -// testList -// "Vector tests" -// [ Vector.SpMV.tests -// Vector.ZeroCreate.tests -// Vector.OfList.tests -// Vector.Copy.tests -// Vector.Convert.tests -// Vector.Map2.addTests -// Vector.Map2.mulTests -// Vector.Map2.addAtLeastOneTests -// Vector.Map2.mulAtLeastOneTests -// Vector.Map2.complementedGeneralTests -// Vector.AssignByMask.tests -// Vector.AssignByMask.complementedTests -// Vector.Reduce.tests ] -// |> testSequenced -// -// let algorithmsTests = -// testList "Algorithms tests" [ Algorithms.BFS.tests ] -// |> testSequenced -// -// [] -// let allTests = -// testList -// "All tests" -// [ matrixTests -// commonTests -// vectorTests -// algorithmsTests ] -// |> testSequenced +let matrixTests = + testList + "Matrix tests" + [ Matrix.Convert.tests + Matrix.Map2.addTests + Matrix.Map2.addAtLeastOneTests + Matrix.Map2.mulAtLeastOneTests + Matrix.Map2.addAtLeastOneToCOOTests + Matrix.Map.notTests + Matrix.Map.addTests + Matrix.Map.mulTests + Matrix.SpGeMM.Expand.generalTests + Matrix.SpGeMM.Masked.tests + Matrix.Transpose.tests + Matrix.RowsLengths.tests ] + |> testSequenced + +let commonTests = + let scanTests = + testList + "Scan" + [ Common.Scan.ByKey.sequentialSegmentsTests + Common.Scan.PrefixSum.tests ] + + let reduceTests = + testList + "Reduce" + [ Common.Reduce.ByKey.sequentialTest + Common.Reduce.ByKey.sequentialSegmentTests + Common.Reduce.ByKey.oneWorkGroupTest + Common.Reduce.Reduce.tests + Common.Reduce.Sum.tests ] + + let clArrayTests = + testList + "ClArray" + [ Common.ClArray.RemoveDuplicates.tests + Common.ClArray.Copy.tests + Common.ClArray.Replicate.tests + Common.ClArray.Exists.tests + Common.ClArray.Map.tests + Common.ClArray.Map2.addTests + Common.ClArray.Map2.mulTests + Common.ClArray.Choose.tests + Common.ClArray.ChunkBySize.allTests + Common.ClArray.Assign.tests + Common.ClArray.Concat.tests + Common.ClArray.Fill.tests + Common.ClArray.Pairwise.tests ] + + let sortTests = + testList + "Sort" + [ Common.Sort.Bitonic.tests + Common.Sort.Radix.allTests ] + + testList + "Common tests" + [ clArrayTests + sortTests + reduceTests + scanTests + Common.Scatter.tests ] + |> testSequenced + +let vectorTests = + testList + "Vector tests" + [ Vector.SpMV.tests + Vector.ZeroCreate.tests + Vector.OfList.tests + Vector.Copy.tests + Vector.Convert.tests + Vector.Map2.addTests + Vector.Map2.mulTests + Vector.Map2.addAtLeastOneTests + Vector.Map2.mulAtLeastOneTests + Vector.Map2.complementedGeneralTests + Vector.AssignByMask.tests + Vector.AssignByMask.complementedTests + Vector.Reduce.tests ] + |> testSequenced + +let algorithmsTests = + testList "Algorithms tests" [ Algorithms.BFS.tests ] + |> testSequenced + +[] +let allTests = + testList + "All tests" + [ matrixTests + commonTests + vectorTests + algorithmsTests ] + |> testSequenced [] -let main argv = - testList "lol" [ Matrix.RowsLengths.tests ] |> testSequenced - |> runTestsWithCLIArgs [] argv +let main argv = allTests |> runTestsWithCLIArgs [] argv From 3d0b07b39bdb3f9818773cc4aa13fe208dffab88 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Thu, 20 Apr 2023 11:12:15 +0300 Subject: [PATCH 17/44] refactor: formatting --- .../GraphBLAS-sharp.Backend.fsproj | 2 +- .../Matrix/CSR/Matrix.fs | 2 +- .../Matrix/{Rows => LIL}/Matrix.fs | 7 +------ src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 20 ++++++++----------- src/GraphBLAS-sharp/Objects/Matrix.fs | 12 +++++------ .../Objects/MatrixExtensions.fs | 2 +- tests/GraphBLAS-sharp.Tests/Helpers.fs | 6 +++--- tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs | 4 ++-- .../Matrix/SpGeMM/Expand.fs | 12 +++++------ tests/GraphBLAS-sharp.Tests/Program.fs | 4 +--- 10 files changed, 29 insertions(+), 42 deletions(-) rename src/GraphBLAS-sharp.Backend/Matrix/{Rows => LIL}/Matrix.fs (87%) diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index d0e03da6..3157c369 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -52,7 +52,7 @@ - + diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index d6009d01..1e95a3c0 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -149,7 +149,7 @@ module Matrix = |> Seq.map (fun lazyValue -> lazyValue.Value) |> Seq.toArray - let toRows (clContext: ClContext) workGroupSize = + let toLIL (clContext: ClContext) workGroupSize = let byRows = byRows clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/LIL/Matrix.fs similarity index 87% rename from src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs rename to src/GraphBLAS-sharp.Backend/Matrix/LIL/Matrix.fs index b7bea530..4cc3944a 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Rows/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/LIL/Matrix.fs @@ -1,14 +1,9 @@ -namespace GraphBLAS.FSharp.Backend.Matrix.Rows +namespace GraphBLAS.FSharp.Backend.Matrix.LIL open Brahma.FSharp open GraphBLAS.FSharp.Backend.Common -open GraphBLAS.FSharp.Backend.Matrix -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend open GraphBLAS.FSharp.Backend.Objects.ClContext open GraphBLAS.FSharp.Backend.Objects.ClMatrix -open GraphBLAS.FSharp.Backend.Quotes -open FSharp.Quotations.Evaluator module Matrix = let toCSR (clContext: ClContext) workGroupSize = diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index be3f5521..cc2d45ad 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -71,8 +71,7 @@ module Matrix = let transpose = CSR.Matrix.transpose clContext workGroupSize - let rowsToCSR = - Rows.Matrix.toCSR clContext workGroupSize + let rowsToCSR = LIL.Matrix.toCSR clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with @@ -124,8 +123,7 @@ module Matrix = let transposeInPlace = COO.Matrix.transposeInPlace clContext workGroupSize - let rowsToCSR = - Rows.Matrix.toCSR clContext workGroupSize + let rowsToCSR = LIL.Matrix.toCSR clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with @@ -183,8 +181,7 @@ module Matrix = let transposeCOO = COO.Matrix.transpose clContext workGroupSize - let rowsToCSR = - Rows.Matrix.toCSR clContext workGroupSize + let rowsToCSR = LIL.Matrix.toCSR clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with @@ -233,7 +230,7 @@ module Matrix = |> ClMatrix.CSC | _ -> failwith "Not yet implemented" - let toRows (clContext: ClContext) workGroupSize = + let toLIL (clContext: ClContext) workGroupSize = let copy = copy clContext workGroupSize @@ -242,22 +239,21 @@ module Matrix = let transposeCSR = CSR.Matrix.transposeInPlace clContext workGroupSize - let CSRToRows = - CSR.Matrix.toRows clContext workGroupSize + let CSRToLIL = CSR.Matrix.toLIL clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with | ClMatrix.CSC m -> m.ToCSR |> transposeCSR processor allocationMode - |> CSRToRows processor allocationMode + |> CSRToLIL processor allocationMode |> ClMatrix.LIL | ClMatrix.CSR m -> - CSRToRows processor allocationMode m + CSRToLIL processor allocationMode m |> ClMatrix.LIL | ClMatrix.COO m -> COOToCSR processor allocationMode m - |> CSRToRows processor allocationMode + |> CSRToLIL processor allocationMode |> ClMatrix.LIL | ClMatrix.LIL _ -> copy processor allocationMode matrix diff --git a/src/GraphBLAS-sharp/Objects/Matrix.fs b/src/GraphBLAS-sharp/Objects/Matrix.fs index 8775731b..fd7dcadc 100644 --- a/src/GraphBLAS-sharp/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp/Objects/Matrix.fs @@ -135,7 +135,7 @@ module Matrix = ColumnPointers = context.CreateClArray this.ColumnPointers Values = context.CreateClArray this.Values } - type Rows<'a when 'a: struct> = + type LIL<'a when 'a: struct> = { RowCount: int ColumnCount: int Rows: Vector.Sparse<'a> option [] @@ -184,32 +184,32 @@ type Matrix<'a when 'a: struct> = | CSR of Matrix.CSR<'a> | COO of Matrix.COO<'a> | CSC of Matrix.CSC<'a> - | Rows of Matrix.Rows<'a> + | LIL of Matrix.LIL<'a> member this.RowCount = match this with | CSR matrix -> matrix.RowCount | COO matrix -> matrix.RowCount | CSC matrix -> matrix.RowCount - | Rows matrix -> matrix.RowCount + | LIL matrix -> matrix.RowCount member this.ColumnCount = match this with | CSR matrix -> matrix.ColumnCount | COO matrix -> matrix.ColumnCount | CSC matrix -> matrix.ColumnCount - | Rows matrix -> matrix.ColumnCount + | LIL matrix -> matrix.ColumnCount member this.NNZ = match this with | COO m -> m.NNZ | CSR m -> m.NNZ | CSC m -> m.NNZ - | Rows m -> m.NNZ + | LIL m -> m.NNZ member this.ToDevice(context: ClContext) = match this with | COO matrix -> ClMatrix.COO <| matrix.ToDevice context | CSR matrix -> ClMatrix.CSR <| matrix.ToDevice context | CSC matrix -> ClMatrix.CSC <| matrix.ToDevice context - | Rows matrix -> ClMatrix.LIL <| matrix.ToDevice context + | LIL matrix -> ClMatrix.LIL <| matrix.ToDevice context diff --git a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs index f4bfb15d..47f987f8 100644 --- a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs +++ b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs @@ -38,7 +38,7 @@ module MatrixExtensions = m.Rows |> Array.map (Option.bind (fun row -> Some <| row.ToHost q)) NNZ = m.NNZ } - |> Matrix.Rows + |> Matrix.LIL member this.ToHostAndDispose(processor: MailboxProcessor<_>) = let result = this.ToHost processor diff --git a/tests/GraphBLAS-sharp.Tests/Helpers.fs b/tests/GraphBLAS-sharp.Tests/Helpers.fs index e177a50c..5325be0c 100644 --- a/tests/GraphBLAS-sharp.Tests/Helpers.fs +++ b/tests/GraphBLAS-sharp.Tests/Helpers.fs @@ -64,8 +64,8 @@ module Utils = Matrix.CSC <| Matrix.CSC.FromArray2D(array, isZero) | LIL -> - Matrix.Rows - <| Matrix.Rows.FromArray2D(array, isZero) + Matrix.LIL + <| Matrix.LIL.FromArray2D(array, isZero) let createVectorFromArray vectorCase array isZero = match vectorCase with @@ -130,7 +130,7 @@ module Utils = "Indices must be the same" |> compareArrays (=) actual.Indices expected.Indices - let compareLILMatrix isEqual (actual: Matrix.Rows<'a>) (expected: Matrix.Rows<'a>) = + let compareLILMatrix isEqual (actual: Matrix.LIL<'a>) (expected: Matrix.LIL<'a>) = "Column count must be the same" |> Expect.equal actual.ColumnCount expected.ColumnCount diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs index 058337d0..c9c171db 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs @@ -70,8 +70,8 @@ let testFixtures formatTo = [ createTest Matrix.toCSC formatTo ((=) 0) createTest Matrix.toCSC formatTo ((=) false) ] | LIL -> - [ createTest Matrix.toRows formatTo ((=) 0) - createTest Matrix.toRows formatTo ((=) false) ] + [ createTest Matrix.toLIL formatTo ((=) 0) + createTest Matrix.toLIL formatTo ((=) false) ] |> List.concat |> testList $"%A{formatTo}" diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs index 71ed17bb..bf946e4f 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs @@ -45,9 +45,7 @@ let makeTest isZero testFun (leftArray: 'a [], rightArray: 'a [,]) = |> Array.map (fun (fst, snd) -> snd - fst) let expectedPointers, expectedLength = - Array.init - leftMatrixRow.Indices.Length - (fun index -> rightMatrixRowsLength.[leftMatrixRow.Indices [ index ]]) + Array.init leftMatrixRow.Indices.Length (fun index -> rightMatrixRowsLength.[leftMatrixRow.Indices.[index]]) |> HostPrimitives.prefixSumExclude 0 (+) let clLeftMatrixRow = leftMatrixRow.ToDevice context @@ -134,7 +132,7 @@ let makeExpandTest isEqual zero testFun (leftArray: 'a [], rightArray: 'a [,]) = |> fun rightMatrixRowsLengths -> Array.init leftMatrixRow.Indices.Length - (fun index -> rightMatrixRowsLengths.[leftMatrixRow.Indices [ index ]]) + (fun index -> rightMatrixRowsLengths.[leftMatrixRow.Indices.[index]]) |> HostPrimitives.prefixSumExclude 0 (+) |> fun (pointers, length) -> context.CreateClArray(pointers), length @@ -213,9 +211,9 @@ let makeGeneralTest<'a when 'a: struct> zero isEqual opMul opAdd testFun (leftAr clMatrixActual.ToHostAndDispose processor match matrixActual with - | Matrix.Rows actual -> + | Matrix.LIL actual -> HostPrimitives.array2DMultiplication zero opMul opAdd leftArray rightArray - |> fun array -> Matrix.Rows.FromArray2D(array, (isEqual zero)) + |> fun array -> Matrix.LIL.FromArray2D(array, (isEqual zero)) |> Utils.compareLILMatrix isEqual actual | _ -> failwith "Matrix format are not matching" @@ -225,7 +223,7 @@ let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun |> testPropertyWithConfig config $"test on %A{typeof<'a>}" let generalTests = - [ //createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand + [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand if Utils.isFloat64Available context.ClDevice then createGeneralTest diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index e5fec84a..637ca279 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -29,9 +29,7 @@ let commonTests = let reduceTests = testList "Reduce" - [ Common.Reduce.ByKey.sequentialTest - Common.Reduce.ByKey.sequentialSegmentTests - Common.Reduce.ByKey.oneWorkGroupTest + [ Common.Reduce.ByKey.allTests Common.Reduce.Reduce.tests Common.Reduce.Sum.tests ] From c75fd575a331c35434cd3abf98198eceb3bf3f52 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Thu, 20 Apr 2023 14:14:47 +0300 Subject: [PATCH 18/44] wip: ArithmeticOps --- .../GraphBLAS-sharp.Backend.fsproj | 2 +- .../Quotes/Arithmetic.fs | 139 ++++++------- src/GraphBLAS-sharp.Backend/Quotes/Convert.fs | 7 + .../GraphBLAS-sharp.Tests.fsproj | 1 + tests/GraphBLAS-sharp.Tests/Program.fs | 190 +++++++++--------- tests/GraphBLAS-sharp.Tests/Vector/Map.fs | 61 ++++++ 6 files changed, 227 insertions(+), 173 deletions(-) create mode 100644 tests/GraphBLAS-sharp.Tests/Vector/Map.fs diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index 3157c369..88732c3e 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -19,8 +19,8 @@ + - diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs b/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs index 5e0ba6c4..f3cee370 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs @@ -3,7 +3,8 @@ open GraphBLAS.FSharp.Backend.Objects module ArithmeticOperations = - let inline mkUnaryOp zero unaryOp = + // unary + let inline optionUnOp zero unaryOp = <@ fun x -> let mutable res = zero @@ -13,113 +14,96 @@ module ArithmeticOperations = if res = zero then None else Some res @> - let inline mkNumericSum zero = - <@ fun (x: 't option) (y: 't option) -> - let mutable res = zero - - match x, y with - | Some f, Some s -> res <- f + s - | Some f, None -> res <- f - | None, Some s -> res <- s - | None, None -> () + let inline addLeftConst zero constant = + optionUnOp zero <@ fun x -> constant + x @> - if res = zero then None else Some res @> + let inline addRightConst zero constant = + optionUnOp zero <@ fun x -> x + constant @> - let inline mkNumericSumAtLeastOne zero = - <@ fun (values: AtLeastOne<'t, 't>) -> - let mutable res = zero + let inline mulLeftConst zero constant = + optionUnOp zero <@ fun x -> constant * x @> - match values with - | Both (f, s) -> res <- f + s - | Left f -> res <- f - | Right s -> res <- s + let inline mulRightConst zero constant = + optionUnOp zero <@ fun x -> x * constant @> - if res = zero then None else Some res @> + // binary - let inline mkNumericMul zero = - <@ fun (x: 't option) (y: 't option) -> + let inline optionBinOpQ zero binOp = + <@ fun (x: 'a option) (y: 'a option) -> let mutable res = zero match x, y with - | Some f, Some s -> res <- f * s - | _ -> () + | Some f, Some s -> res <- (%binOp) f s + | Some f, None -> res <- f + | None, Some s -> res <- s + | None, None -> () if res = zero then None else Some res @> - let inline mkNumericMulAtLeastOne zero = - <@ fun (values: AtLeastOne<'t, 't>) -> + let inline optionBinOp zero binOp = + fun (x: 'a option) (y: 'a option) -> let mutable res = zero - match values with - | Both (f, s) -> res <- f * s - | _ -> () - - if res = zero then None else Some res @> - - let boolSum = - <@ fun (x: bool option) (y: bool option) -> - let mutable res = false - match x, y with + | Some left, Some right -> res <- binOp left right + | Some left, None -> res <- left + | None, Some right -> res <- right | None, None -> () - | _ -> res <- true - if res then Some true else None @> + if res = zero then None else Some res - let inline addLeftConst zero constant = - mkUnaryOp zero <@ fun x -> constant + x @> + let createOptionPair zero opQ op = + optionBinOpQ zero opQ, optionBinOp zero op - let inline addRightConst zero constant = - mkUnaryOp zero <@ fun x -> x + constant @> + let inline createOptionSumPair zero = createOptionPair zero <@ (+) @> (+) - let intSumOption = mkNumericSum 0 - let byteSumOption = mkNumericSum 0uy - let floatSumOption = mkNumericSum 0.0 - let float32SumOption = mkNumericSum 0f + let intSumOption = createOptionSumPair 0 + let byteSumOption = createOptionSumPair 0uy + let floatSumOption = createOptionSumPair 0.0 + let float32SumOption = createOptionSumPair 0f - let boolSumAtLeastOne = - <@ fun (_: AtLeastOne) -> Some true @> + let boolSumOption = createOptionPair false <@ (||) @> (||) - let intSumAtLeastOne = mkNumericSumAtLeastOne 0 - let byteSumAtLeastOne = mkNumericSumAtLeastOne 0uy - let floatSumAtLeastOne = mkNumericSumAtLeastOne 0.0 - let float32SumAtLeastOne = mkNumericSumAtLeastOne 0f + let inline createOptionMulPair zero = createOptionPair zero <@ (*) @> (*) - let boolMulOption = - <@ fun (x: bool option) (y: bool option) -> - let mutable res = false + let intMulOption = createOptionMulPair 0 + let byteMulOption = createOptionMulPair 0uy + let floatMulOption = createOptionMulPair 0.0 + let float32MulOption = createOptionMulPair 0f - match x, y with - | Some _, Some _ -> res <- true - | _ -> () + let boolMulOption = createOptionPair true <@ (&&) @> (&&) - if res then Some true else None @> + let inline atLeastOneBinOpQ zero binOp = + Convert.optionToAtLeastOne <| optionBinOpQ zero binOp - let inline mulLeftConst zero constant = - mkUnaryOp zero <@ fun x -> constant * x @> + let inline atLeastOneBinOp zero binOp = + let optionOp = optionBinOp zero binOp + // convert AtLeastOne -> Option + function + | Both (left, right) -> optionOp (Some left) (Some right) + | Left left -> optionOp (Some left) None + | Right right -> optionOp None (Some right) - let inline mulRightConst zero constant = - mkUnaryOp zero <@ fun x -> x * constant @> + let inline createAtLeastOnePair zero opQ op = + atLeastOneBinOpQ zero opQ, atLeastOneBinOp zero op + + let inline createAtLeastOneSumPair zero = createAtLeastOnePair zero <@ (+) @> (+) - let intMulOption = mkNumericMul 0 - let byteMulOption = mkNumericMul 0uy - let floatMulOption = mkNumericMul 0.0 - let float32MulOption = mkNumericMul 0f + let intSumAtLeastOne = createAtLeastOneSumPair 0 + let byteSumAtLeastOne = createAtLeastOneSumPair 0uy + let floatSumAtLeastOne = createAtLeastOneSumPair 0.0 + let float32SumAtLeastOne = createAtLeastOneSumPair 0f - let boolMulAtLeastOne = - <@ fun (values: AtLeastOne) -> - let mutable res = false + let boolSumAtLeastOne = createAtLeastOnePair false <@ (||) @> (||) - match values with - | Both _ -> res <- true - | _ -> () + let inline createAtLeastOneMulPair zero = createAtLeastOnePair zero <@ (*) @> (*) - if res then Some true else None @> + let intMulAtLeastOne = createAtLeastOneMulPair 0 + let byteMulAtLeastOne = createAtLeastOneMulPair 0uy + let floatMulAtLeastOne = createAtLeastOneMulPair 0.0 + let float32MulAtLeastOne = createAtLeastOneMulPair 0f - let intMulAtLeastOne = mkNumericMulAtLeastOne 0 - let byteMulAtLeastOne = mkNumericMulAtLeastOne 0uy - let floatMulAtLeastOne = mkNumericMulAtLeastOne 0.0 - let float32MulAtLeastOne = mkNumericMulAtLeastOne 0f + let boolMulAtLeastOne = createAtLeastOnePair true <@ (&&) @> (&&) let notOption = <@ fun x -> @@ -127,6 +111,7 @@ module ArithmeticOperations = | Some true -> None | _ -> Some true @> + // unwrapped operands let inline private binOpQ zero op = <@ fun (left: 'a) (right: 'a) -> let result = (%op) left right diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs b/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs index d779ba5a..ce73ed5e 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs @@ -12,6 +12,13 @@ module Convert = | Some left, None -> (%op) (Left left) | None, None -> None @> + let optionToAtLeastOne (op: Expr<'a option -> 'b option -> 'c option>) = + <@ fun (item: AtLeastOne<'a, 'b>) -> + match item with + | Both (left, right) -> (%op) (Some left) (Some right) + | Left left -> (%op) (Some left) None + | Right right -> (%op) None (Some right) @> + let assignToOption (op: Expr<'a option -> 'a option -> 'a option>) = <@ fun (leftItem: 'a option) (rightItem: 'b option) (value: 'a) -> match rightItem with diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index 64400aa6..8a4a7b11 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -49,6 +49,7 @@ + diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index 637ca279..e90d3a1f 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -2,100 +2,100 @@ open Expecto open GraphBLAS.FSharp.Tests.Backend open GraphBLAS.FSharp.Tests -let matrixTests = - testList - "Matrix tests" - [ Matrix.Convert.tests - Matrix.Map2.addTests - Matrix.Map2.addAtLeastOneTests - Matrix.Map2.mulAtLeastOneTests - Matrix.Map2.addAtLeastOneToCOOTests - Matrix.Map.notTests - Matrix.Map.addTests - Matrix.Map.mulTests - Matrix.SpGeMM.Expand.generalTests - Matrix.SpGeMM.Masked.tests - Matrix.Transpose.tests - Matrix.RowsLengths.tests ] - |> testSequenced - -let commonTests = - let scanTests = - testList - "Scan" - [ Common.Scan.ByKey.sequentialSegmentsTests - Common.Scan.PrefixSum.tests ] - - let reduceTests = - testList - "Reduce" - [ Common.Reduce.ByKey.allTests - Common.Reduce.Reduce.tests - Common.Reduce.Sum.tests ] - - let clArrayTests = - testList - "ClArray" - [ Common.ClArray.RemoveDuplicates.tests - Common.ClArray.Copy.tests - Common.ClArray.Replicate.tests - Common.ClArray.Exists.tests - Common.ClArray.Map.tests - Common.ClArray.Map2.addTests - Common.ClArray.Map2.mulTests - Common.ClArray.Choose.tests - Common.ClArray.ChunkBySize.allTests - Common.ClArray.Assign.tests - Common.ClArray.Concat.tests - Common.ClArray.Fill.tests - Common.ClArray.Pairwise.tests ] - - let sortTests = - testList - "Sort" - [ Common.Sort.Bitonic.tests - Common.Sort.Radix.allTests ] - - testList - "Common tests" - [ clArrayTests - sortTests - reduceTests - scanTests - Common.Scatter.tests ] - |> testSequenced - -let vectorTests = - testList - "Vector tests" - [ Vector.SpMV.tests - Vector.ZeroCreate.tests - Vector.OfList.tests - Vector.Copy.tests - Vector.Convert.tests - Vector.Map2.addTests - Vector.Map2.mulTests - Vector.Map2.addAtLeastOneTests - Vector.Map2.mulAtLeastOneTests - Vector.Map2.complementedGeneralTests - Vector.AssignByMask.tests - Vector.AssignByMask.complementedTests - Vector.Reduce.tests ] - |> testSequenced - -let algorithmsTests = - testList "Algorithms tests" [ Algorithms.BFS.tests ] - |> testSequenced - -[] -let allTests = - testList - "All tests" - [ matrixTests - commonTests - vectorTests - algorithmsTests ] - |> testSequenced +// let matrixTests = +// testList +// "Matrix tests" +// [ Matrix.Convert.tests +// Matrix.Map2.addTests +// Matrix.Map2.addAtLeastOneTests +// Matrix.Map2.mulAtLeastOneTests +// Matrix.Map2.addAtLeastOneToCOOTests +// Matrix.Map.notTests +// Matrix.Map.addTests +// Matrix.Map.mulTests +// Matrix.SpGeMM.Expand.generalTests +// Matrix.SpGeMM.Masked.tests +// Matrix.Transpose.tests +// Matrix.RowsLengths.tests ] +// |> testSequenced +// +// let commonTests = +// let scanTests = +// testList +// "Scan" +// [ Common.Scan.ByKey.sequentialSegmentsTests +// Common.Scan.PrefixSum.tests ] +// +// let reduceTests = +// testList +// "Reduce" +// [ Common.Reduce.ByKey.allTests +// Common.Reduce.Reduce.tests +// Common.Reduce.Sum.tests ] +// +// let clArrayTests = +// testList +// "ClArray" +// [ Common.ClArray.RemoveDuplicates.tests +// Common.ClArray.Copy.tests +// Common.ClArray.Replicate.tests +// Common.ClArray.Exists.tests +// Common.ClArray.Map.tests +// Common.ClArray.Map2.addTests +// Common.ClArray.Map2.mulTests +// Common.ClArray.Choose.tests +// Common.ClArray.ChunkBySize.allTests +// Common.ClArray.Assign.tests +// Common.ClArray.Concat.tests +// Common.ClArray.Fill.tests +// Common.ClArray.Pairwise.tests ] +// +// let sortTests = +// testList +// "Sort" +// [ Common.Sort.Bitonic.tests +// Common.Sort.Radix.allTests ] +// +// testList +// "Common tests" +// [ clArrayTests +// sortTests +// reduceTests +// scanTests +// Common.Scatter.tests ] +// |> testSequenced +// +// let vectorTests = +// testList +// "Vector tests" +// [ Vector.SpMV.tests +// Vector.ZeroCreate.tests +// Vector.OfList.tests +// Vector.Copy.tests +// Vector.Convert.tests +// Vector.Map2.addTests +// Vector.Map2.mulTests +// Vector.Map2.addAtLeastOneTests +// Vector.Map2.mulAtLeastOneTests +// Vector.Map2.complementedGeneralTests +// Vector.AssignByMask.tests +// Vector.AssignByMask.complementedTests +// Vector.Reduce.tests ] +// |> testSequenced +// +// let algorithmsTests = +// testList "Algorithms tests" [ Algorithms.BFS.tests ] +// |> testSequenced +// +// [] +// let allTests = +// testList +// "All tests" +// [ matrixTests +// commonTests +// vectorTests +// algorithmsTests ] +// |> testSequenced [] -let main argv = allTests |> runTestsWithCLIArgs [] argv +let main argv = Matrix.Transpose.tests |> testSequenced |> runTestsWithCLIArgs [] argv diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Map.fs b/tests/GraphBLAS-sharp.Tests/Vector/Map.fs new file mode 100644 index 00000000..b2ae3165 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Vector/Map.fs @@ -0,0 +1,61 @@ +module GraphBLAS.FSharp.Tests.Vector.Map + +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Tests +open Expecto +open Expecto.Logging +open GraphBLAS.FSharp.Backend +open GraphBLAS.FSharp.Tests +open Context +open TestCases +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Vector +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Objects.ClVectorExtensions +open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Backend.Quotes + +let processor = Context.defaultContext.Queue + +let context = Context.defaultContext.ClContext + + +let config = Utils.defaultConfig + +let makeTest<'a> op isEqual zero testFun (array: 'a []) = + + let vector = Vector.Sparse.FromArray(array, isEqual zero) + + if vector.NNZ > 0 then + let clVector = vector.ToDevice context + + let (clActual: ClVector.Sparse<'a>) = + testFun processor HostInterop clVector + + let actual = clActual.ToHost processor + + let expectedIndices, expectedValues = + array + // apply op + |> Array.map (fun item -> + if isEqual zero item then None else op <| Some item) + // Dense to Sparse + |> Array.mapi (fun index -> function + | Some value -> Some (index, value) + | None -> None) + |> Array.choose id + |> Array.unzip + + "Indices must be the same" + |> Utils.compareArrays (=) actual.Indices expectedIndices + + "Values must be the same" + |> Utils.compareArrays isEqual actual.Values expectedValues + +let createTest<'a when 'a : struct and 'a : equality> isEqual (zero: 'a) (opQ, op) = + Vector.Sparse.Map.run context Utils.defaultWorkGroupSize opQ + |> makeTest<'a> op isEqual zero + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let tests = + [ createTest (=) 0 ] From 244155862509b2edf0d68503adfe180af4d3759e Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 21 Apr 2023 15:27:21 +0300 Subject: [PATCH 19/44] refactor: formatting --- .../GraphBLAS-sharp.Backend.fsproj | 44 ++-- .../Quotes/Arithmetic.fs | 139 +++++++------ src/GraphBLAS-sharp.Backend/Quotes/Convert.fs | 7 - src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj | 2 +- .../GraphBLAS-sharp.Tests.fsproj | 17 +- tests/GraphBLAS-sharp.Tests/Matrix/Map.fs | 42 ++-- tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs | 50 ++--- .../Matrix/SpGeMM/Expand.fs | 8 +- .../GraphBLAS-sharp.Tests/Matrix/Transpose.fs | 43 ++-- tests/GraphBLAS-sharp.Tests/Program.fs | 190 +++++++++--------- tests/GraphBLAS-sharp.Tests/Vector/Map.fs | 27 ++- 11 files changed, 295 insertions(+), 274 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index 88732c3e..cc3db014 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -19,8 +19,8 @@ - + @@ -35,27 +35,27 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs b/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs index f3cee370..5e0ba6c4 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs @@ -3,8 +3,7 @@ open GraphBLAS.FSharp.Backend.Objects module ArithmeticOperations = - // unary - let inline optionUnOp zero unaryOp = + let inline mkUnaryOp zero unaryOp = <@ fun x -> let mutable res = zero @@ -14,96 +13,113 @@ module ArithmeticOperations = if res = zero then None else Some res @> - let inline addLeftConst zero constant = - optionUnOp zero <@ fun x -> constant + x @> + let inline mkNumericSum zero = + <@ fun (x: 't option) (y: 't option) -> + let mutable res = zero - let inline addRightConst zero constant = - optionUnOp zero <@ fun x -> x + constant @> + match x, y with + | Some f, Some s -> res <- f + s + | Some f, None -> res <- f + | None, Some s -> res <- s + | None, None -> () - let inline mulLeftConst zero constant = - optionUnOp zero <@ fun x -> constant * x @> + if res = zero then None else Some res @> - let inline mulRightConst zero constant = - optionUnOp zero <@ fun x -> x * constant @> + let inline mkNumericSumAtLeastOne zero = + <@ fun (values: AtLeastOne<'t, 't>) -> + let mutable res = zero + + match values with + | Both (f, s) -> res <- f + s + | Left f -> res <- f + | Right s -> res <- s - // binary + if res = zero then None else Some res @> - let inline optionBinOpQ zero binOp = - <@ fun (x: 'a option) (y: 'a option) -> + let inline mkNumericMul zero = + <@ fun (x: 't option) (y: 't option) -> let mutable res = zero match x, y with - | Some f, Some s -> res <- (%binOp) f s - | Some f, None -> res <- f - | None, Some s -> res <- s - | None, None -> () + | Some f, Some s -> res <- f * s + | _ -> () if res = zero then None else Some res @> - let inline optionBinOp zero binOp = - fun (x: 'a option) (y: 'a option) -> + let inline mkNumericMulAtLeastOne zero = + <@ fun (values: AtLeastOne<'t, 't>) -> let mutable res = zero + match values with + | Both (f, s) -> res <- f * s + | _ -> () + + if res = zero then None else Some res @> + + let boolSum = + <@ fun (x: bool option) (y: bool option) -> + let mutable res = false + match x, y with - | Some left, Some right -> res <- binOp left right - | Some left, None -> res <- left - | None, Some right -> res <- right | None, None -> () + | _ -> res <- true - if res = zero then None else Some res + if res then Some true else None @> - let createOptionPair zero opQ op = - optionBinOpQ zero opQ, optionBinOp zero op - - let inline createOptionSumPair zero = createOptionPair zero <@ (+) @> (+) + let inline addLeftConst zero constant = + mkUnaryOp zero <@ fun x -> constant + x @> - let intSumOption = createOptionSumPair 0 - let byteSumOption = createOptionSumPair 0uy - let floatSumOption = createOptionSumPair 0.0 - let float32SumOption = createOptionSumPair 0f + let inline addRightConst zero constant = + mkUnaryOp zero <@ fun x -> x + constant @> - let boolSumOption = createOptionPair false <@ (||) @> (||) + let intSumOption = mkNumericSum 0 + let byteSumOption = mkNumericSum 0uy + let floatSumOption = mkNumericSum 0.0 + let float32SumOption = mkNumericSum 0f - let inline createOptionMulPair zero = createOptionPair zero <@ (*) @> (*) + let boolSumAtLeastOne = + <@ fun (_: AtLeastOne) -> Some true @> - let intMulOption = createOptionMulPair 0 - let byteMulOption = createOptionMulPair 0uy - let floatMulOption = createOptionMulPair 0.0 - let float32MulOption = createOptionMulPair 0f + let intSumAtLeastOne = mkNumericSumAtLeastOne 0 + let byteSumAtLeastOne = mkNumericSumAtLeastOne 0uy + let floatSumAtLeastOne = mkNumericSumAtLeastOne 0.0 + let float32SumAtLeastOne = mkNumericSumAtLeastOne 0f - let boolMulOption = createOptionPair true <@ (&&) @> (&&) + let boolMulOption = + <@ fun (x: bool option) (y: bool option) -> + let mutable res = false - let inline atLeastOneBinOpQ zero binOp = - Convert.optionToAtLeastOne <| optionBinOpQ zero binOp + match x, y with + | Some _, Some _ -> res <- true + | _ -> () - let inline atLeastOneBinOp zero binOp = - let optionOp = optionBinOp zero binOp - // convert AtLeastOne -> Option - function - | Both (left, right) -> optionOp (Some left) (Some right) - | Left left -> optionOp (Some left) None - | Right right -> optionOp None (Some right) + if res then Some true else None @> - let inline createAtLeastOnePair zero opQ op = - atLeastOneBinOpQ zero opQ, atLeastOneBinOp zero op + let inline mulLeftConst zero constant = + mkUnaryOp zero <@ fun x -> constant * x @> - let inline createAtLeastOneSumPair zero = createAtLeastOnePair zero <@ (+) @> (+) + let inline mulRightConst zero constant = + mkUnaryOp zero <@ fun x -> x * constant @> - let intSumAtLeastOne = createAtLeastOneSumPair 0 - let byteSumAtLeastOne = createAtLeastOneSumPair 0uy - let floatSumAtLeastOne = createAtLeastOneSumPair 0.0 - let float32SumAtLeastOne = createAtLeastOneSumPair 0f + let intMulOption = mkNumericMul 0 + let byteMulOption = mkNumericMul 0uy + let floatMulOption = mkNumericMul 0.0 + let float32MulOption = mkNumericMul 0f - let boolSumAtLeastOne = createAtLeastOnePair false <@ (||) @> (||) + let boolMulAtLeastOne = + <@ fun (values: AtLeastOne) -> + let mutable res = false - let inline createAtLeastOneMulPair zero = createAtLeastOnePair zero <@ (*) @> (*) + match values with + | Both _ -> res <- true + | _ -> () - let intMulAtLeastOne = createAtLeastOneMulPair 0 - let byteMulAtLeastOne = createAtLeastOneMulPair 0uy - let floatMulAtLeastOne = createAtLeastOneMulPair 0.0 - let float32MulAtLeastOne = createAtLeastOneMulPair 0f + if res then Some true else None @> - let boolMulAtLeastOne = createAtLeastOnePair true <@ (&&) @> (&&) + let intMulAtLeastOne = mkNumericMulAtLeastOne 0 + let byteMulAtLeastOne = mkNumericMulAtLeastOne 0uy + let floatMulAtLeastOne = mkNumericMulAtLeastOne 0.0 + let float32MulAtLeastOne = mkNumericMulAtLeastOne 0f let notOption = <@ fun x -> @@ -111,7 +127,6 @@ module ArithmeticOperations = | Some true -> None | _ -> Some true @> - // unwrapped operands let inline private binOpQ zero op = <@ fun (left: 'a) (right: 'a) -> let result = (%op) left right diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs b/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs index ce73ed5e..d779ba5a 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Convert.fs @@ -12,13 +12,6 @@ module Convert = | Some left, None -> (%op) (Left left) | None, None -> None @> - let optionToAtLeastOne (op: Expr<'a option -> 'b option -> 'c option>) = - <@ fun (item: AtLeastOne<'a, 'b>) -> - match item with - | Both (left, right) -> (%op) (Some left) (Some right) - | Left left -> (%op) (Some left) None - | Right right -> (%op) None (Some right) @> - let assignToOption (op: Expr<'a option -> 'a option -> 'a option>) = <@ fun (leftItem: 'a option) (rightItem: 'b option) (value: 'a) -> match rightItem with diff --git a/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj b/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj index 658f2876..6e3620cf 100644 --- a/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj +++ b/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj @@ -18,7 +18,7 @@ - + diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index 8a4a7b11..b397735d 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -25,11 +25,11 @@ - - - - - + + + + + @@ -37,10 +37,6 @@ - - - - @@ -49,7 +45,6 @@ - @@ -57,7 +52,7 @@ - + diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Map.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Map.fs index b89042a4..cb5b7e51 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Map.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Map.fs @@ -59,33 +59,35 @@ let correctnessGenericTest (case: OperationCase) (matrix: 'a [,]) = + match case.Format with + | LIL -> () + | _ -> + let mtx = + Utils.createMatrixFromArray2D case.Format matrix (isEqual zero) - let mtx = - Utils.createMatrixFromArray2D case.Format matrix (isEqual zero) + if mtx.NNZ > 0 then + try + let m = mtx.ToDevice case.TestContext.ClContext - if mtx.NNZ > 0 then - try - let m = mtx.ToDevice case.TestContext.ClContext + let res = addFun q HostInterop m - let res = addFun q HostInterop m + m.Dispose q - m.Dispose q + let (cooRes: ClMatrix<'a>) = toCOOFun q HostInterop res + let actual = cooRes.ToHost q - let (cooRes: ClMatrix<'a>) = toCOOFun q HostInterop res - let actual = cooRes.ToHost q + cooRes.Dispose q + res.Dispose q - cooRes.Dispose q - res.Dispose q + logger.debug ( + eventX "Actual is {actual}" + >> setField "actual" (sprintf "%A" actual) + ) - logger.debug ( - eventX "Actual is {actual}" - >> setField "actual" (sprintf "%A" actual) - ) - - checkResult isEqual op zero matrix actual - with - | ex when ex.Message = "InvalidBufferSize" -> () - | ex -> raise ex + checkResult isEqual op zero matrix actual + with + | ex when ex.Message = "InvalidBufferSize" -> () + | ex -> raise ex let createTestMap case (zero: 'a) (constant: 'a) binOp isEqual opQ = let getCorrectnessTestName = getCorrectnessTestName case diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs index ae5e0e22..9c1fdf6e 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs @@ -59,39 +59,41 @@ let correctnessGenericTest (case: OperationCase) (leftMatrix: 'a [,], rightMatrix: 'a [,]) = + match case.Format with // TODO(map2 on LIL) + | LIL -> () + | _ -> + let mtx1 = + Utils.createMatrixFromArray2D case.Format leftMatrix (isEqual zero) - let mtx1 = - Utils.createMatrixFromArray2D case.Format leftMatrix (isEqual zero) + let mtx2 = + Utils.createMatrixFromArray2D case.Format rightMatrix (isEqual zero) - let mtx2 = - Utils.createMatrixFromArray2D case.Format rightMatrix (isEqual zero) + if mtx1.NNZ > 0 && mtx2.NNZ > 0 then + try + let m1 = mtx1.ToDevice case.TestContext.ClContext - if mtx1.NNZ > 0 && mtx2.NNZ > 0 then - try - let m1 = mtx1.ToDevice case.TestContext.ClContext + let m2 = mtx2.ToDevice case.TestContext.ClContext - let m2 = mtx2.ToDevice case.TestContext.ClContext + let res = addFun q HostInterop m1 m2 - let res = addFun q HostInterop m1 m2 + m1.Dispose q + m2.Dispose q - m1.Dispose q - m2.Dispose q + let (cooRes: ClMatrix<'a>) = toCOOFun q HostInterop res + let actual = cooRes.ToHost q - let (cooRes: ClMatrix<'a>) = toCOOFun q HostInterop res - let actual = cooRes.ToHost q + cooRes.Dispose q + res.Dispose q - cooRes.Dispose q - res.Dispose q + logger.debug ( + eventX "Actual is {actual}" + >> setField "actual" (sprintf "%A" actual) + ) - logger.debug ( - eventX "Actual is {actual}" - >> setField "actual" (sprintf "%A" actual) - ) - - checkResult isEqual op zero leftMatrix rightMatrix actual - with - | ex when ex.Message = "InvalidBufferSize" -> () - | ex -> raise ex + checkResult isEqual op zero leftMatrix rightMatrix actual + with + | ex when ex.Message = "InvalidBufferSize" -> () + | ex -> raise ex let creatTestMap2Add case (zero: 'a) add isEqual addQ map2 = let getCorrectnessTestName = getCorrectnessTestName case diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs index bf946e4f..3081f342 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs @@ -198,6 +198,8 @@ let makeGeneralTest<'a when 'a: struct> zero isEqual opMul opAdd testFun (leftAr if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then + printfn $"left matrix rows count: %A{leftMatrix.RowCount}" + let clLeftMatrix = leftMatrix.ToDevice context let clRightMatrix = rightMatrix.ToDevice context @@ -220,7 +222,11 @@ let makeGeneralTest<'a when 'a: struct> zero isEqual opMul opAdd testFun (leftAr let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = testFun context Utils.defaultWorkGroupSize opAddQ opMulQ |> makeGeneralTest<'a> zero isEqual opMul opAdd - |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + |> testPropertyWithConfig + { config with + endSize = 1000 + maxTest = 2 } + $"test on %A{typeof<'a>}" let generalTests = [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs index fadc30df..01e78bf7 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs @@ -80,26 +80,29 @@ let checkResult areEqual zero actual (expected2D: 'a [,]) = | _ -> () // TODO() let makeTestRegular context q transposeFun hostTranspose isEqual zero case (array: 'a [,]) = - let mtx = - Utils.createMatrixFromArray2D case.Format array (isEqual zero) - - if mtx.NNZ > 0 then - let actual = - let m = mtx.ToDevice context - let (mT: ClMatrix<'a>) = transposeFun q HostInterop m - let res = mT.ToHost q - m.Dispose q - mT.Dispose q - res - - logger.debug ( - eventX "Actual is {actual}" - >> setField "actual" $"%A{actual}" - ) - - let expected2D = hostTranspose array - - checkResult isEqual zero actual expected2D + match case.Format with + | LIL -> () + | _ -> + let mtx = + Utils.createMatrixFromArray2D case.Format array (isEqual zero) + + if mtx.NNZ > 0 then + let actual = + let m = mtx.ToDevice context + let (mT: ClMatrix<'a>) = transposeFun q HostInterop m + let res = mT.ToHost q + m.Dispose q + mT.Dispose q + res + + logger.debug ( + eventX "Actual is {actual}" + >> setField "actual" $"%A{actual}" + ) + + let expected2D = hostTranspose array + + checkResult isEqual zero actual expected2D let createTest<'a when 'a: equality and 'a: struct> case (zero: 'a) isEqual = let context = case.TestContext.ClContext diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index e90d3a1f..637ca279 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -2,100 +2,100 @@ open Expecto open GraphBLAS.FSharp.Tests.Backend open GraphBLAS.FSharp.Tests -// let matrixTests = -// testList -// "Matrix tests" -// [ Matrix.Convert.tests -// Matrix.Map2.addTests -// Matrix.Map2.addAtLeastOneTests -// Matrix.Map2.mulAtLeastOneTests -// Matrix.Map2.addAtLeastOneToCOOTests -// Matrix.Map.notTests -// Matrix.Map.addTests -// Matrix.Map.mulTests -// Matrix.SpGeMM.Expand.generalTests -// Matrix.SpGeMM.Masked.tests -// Matrix.Transpose.tests -// Matrix.RowsLengths.tests ] -// |> testSequenced -// -// let commonTests = -// let scanTests = -// testList -// "Scan" -// [ Common.Scan.ByKey.sequentialSegmentsTests -// Common.Scan.PrefixSum.tests ] -// -// let reduceTests = -// testList -// "Reduce" -// [ Common.Reduce.ByKey.allTests -// Common.Reduce.Reduce.tests -// Common.Reduce.Sum.tests ] -// -// let clArrayTests = -// testList -// "ClArray" -// [ Common.ClArray.RemoveDuplicates.tests -// Common.ClArray.Copy.tests -// Common.ClArray.Replicate.tests -// Common.ClArray.Exists.tests -// Common.ClArray.Map.tests -// Common.ClArray.Map2.addTests -// Common.ClArray.Map2.mulTests -// Common.ClArray.Choose.tests -// Common.ClArray.ChunkBySize.allTests -// Common.ClArray.Assign.tests -// Common.ClArray.Concat.tests -// Common.ClArray.Fill.tests -// Common.ClArray.Pairwise.tests ] -// -// let sortTests = -// testList -// "Sort" -// [ Common.Sort.Bitonic.tests -// Common.Sort.Radix.allTests ] -// -// testList -// "Common tests" -// [ clArrayTests -// sortTests -// reduceTests -// scanTests -// Common.Scatter.tests ] -// |> testSequenced -// -// let vectorTests = -// testList -// "Vector tests" -// [ Vector.SpMV.tests -// Vector.ZeroCreate.tests -// Vector.OfList.tests -// Vector.Copy.tests -// Vector.Convert.tests -// Vector.Map2.addTests -// Vector.Map2.mulTests -// Vector.Map2.addAtLeastOneTests -// Vector.Map2.mulAtLeastOneTests -// Vector.Map2.complementedGeneralTests -// Vector.AssignByMask.tests -// Vector.AssignByMask.complementedTests -// Vector.Reduce.tests ] -// |> testSequenced -// -// let algorithmsTests = -// testList "Algorithms tests" [ Algorithms.BFS.tests ] -// |> testSequenced -// -// [] -// let allTests = -// testList -// "All tests" -// [ matrixTests -// commonTests -// vectorTests -// algorithmsTests ] -// |> testSequenced +let matrixTests = + testList + "Matrix tests" + [ Matrix.Convert.tests + Matrix.Map2.addTests + Matrix.Map2.addAtLeastOneTests + Matrix.Map2.mulAtLeastOneTests + Matrix.Map2.addAtLeastOneToCOOTests + Matrix.Map.notTests + Matrix.Map.addTests + Matrix.Map.mulTests + Matrix.SpGeMM.Expand.generalTests + Matrix.SpGeMM.Masked.tests + Matrix.Transpose.tests + Matrix.RowsLengths.tests ] + |> testSequenced + +let commonTests = + let scanTests = + testList + "Scan" + [ Common.Scan.ByKey.sequentialSegmentsTests + Common.Scan.PrefixSum.tests ] + + let reduceTests = + testList + "Reduce" + [ Common.Reduce.ByKey.allTests + Common.Reduce.Reduce.tests + Common.Reduce.Sum.tests ] + + let clArrayTests = + testList + "ClArray" + [ Common.ClArray.RemoveDuplicates.tests + Common.ClArray.Copy.tests + Common.ClArray.Replicate.tests + Common.ClArray.Exists.tests + Common.ClArray.Map.tests + Common.ClArray.Map2.addTests + Common.ClArray.Map2.mulTests + Common.ClArray.Choose.tests + Common.ClArray.ChunkBySize.allTests + Common.ClArray.Assign.tests + Common.ClArray.Concat.tests + Common.ClArray.Fill.tests + Common.ClArray.Pairwise.tests ] + + let sortTests = + testList + "Sort" + [ Common.Sort.Bitonic.tests + Common.Sort.Radix.allTests ] + + testList + "Common tests" + [ clArrayTests + sortTests + reduceTests + scanTests + Common.Scatter.tests ] + |> testSequenced + +let vectorTests = + testList + "Vector tests" + [ Vector.SpMV.tests + Vector.ZeroCreate.tests + Vector.OfList.tests + Vector.Copy.tests + Vector.Convert.tests + Vector.Map2.addTests + Vector.Map2.mulTests + Vector.Map2.addAtLeastOneTests + Vector.Map2.mulAtLeastOneTests + Vector.Map2.complementedGeneralTests + Vector.AssignByMask.tests + Vector.AssignByMask.complementedTests + Vector.Reduce.tests ] + |> testSequenced + +let algorithmsTests = + testList "Algorithms tests" [ Algorithms.BFS.tests ] + |> testSequenced + +[] +let allTests = + testList + "All tests" + [ matrixTests + commonTests + vectorTests + algorithmsTests ] + |> testSequenced [] -let main argv = Matrix.Transpose.tests |> testSequenced |> runTestsWithCLIArgs [] argv +let main argv = allTests |> runTestsWithCLIArgs [] argv diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Map.fs b/tests/GraphBLAS-sharp.Tests/Vector/Map.fs index b2ae3165..7d9a74e6 100644 --- a/tests/GraphBLAS-sharp.Tests/Vector/Map.fs +++ b/tests/GraphBLAS-sharp.Tests/Vector/Map.fs @@ -24,25 +24,31 @@ let config = Utils.defaultConfig let makeTest<'a> op isEqual zero testFun (array: 'a []) = - let vector = Vector.Sparse.FromArray(array, isEqual zero) + let vector = + Vector.Sparse.FromArray(array, isEqual zero) if vector.NNZ > 0 then let clVector = vector.ToDevice context - let (clActual: ClVector.Sparse<'a>) = - testFun processor HostInterop clVector + let (clActual: ClVector.Sparse<'a>) = testFun processor HostInterop clVector let actual = clActual.ToHost processor let expectedIndices, expectedValues = array // apply op - |> Array.map (fun item -> - if isEqual zero item then None else op <| Some item) + |> Array.map + (fun item -> + if isEqual zero item then + None + else + op <| Some item) // Dense to Sparse - |> Array.mapi (fun index -> function - | Some value -> Some (index, value) - | None -> None) + |> Array.mapi + (fun index -> + function + | Some value -> Some(index, value) + | None -> None) |> Array.choose id |> Array.unzip @@ -52,10 +58,9 @@ let makeTest<'a> op isEqual zero testFun (array: 'a []) = "Values must be the same" |> Utils.compareArrays isEqual actual.Values expectedValues -let createTest<'a when 'a : struct and 'a : equality> isEqual (zero: 'a) (opQ, op) = +let createTest<'a when 'a: struct and 'a: equality> isEqual (zero: 'a) (opQ, op) = Vector.Sparse.Map.run context Utils.defaultWorkGroupSize opQ |> makeTest<'a> op isEqual zero |> testPropertyWithConfig config $"test on %A{typeof<'a>}" -let tests = - [ createTest (=) 0 ] +let tests = [ createTest (=) 0 ] From abdd46ccd3c569699d343966d303873390fecd3a Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 21 Apr 2023 15:44:44 +0300 Subject: [PATCH 20/44] refactor: ... --- .../GraphBLAS-sharp.Backend.fsproj | 3 +- .../Vector/Sparse/Map.fs | 138 ------------------ tests/GraphBLAS-sharp.Tests/Vector/Map.fs | 66 --------- 3 files changed, 1 insertion(+), 206 deletions(-) delete mode 100644 src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs delete mode 100644 tests/GraphBLAS-sharp.Tests/Vector/Map.fs diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index cc3db014..2ccc939f 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -30,7 +30,7 @@ - + @@ -39,7 +39,6 @@ - diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs deleted file mode 100644 index 08b706c5..00000000 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map.fs +++ /dev/null @@ -1,138 +0,0 @@ -namespace GraphBLAS.FSharp.Backend.Vector.Sparse - -open Brahma.FSharp -open Microsoft.FSharp.Control -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Objects.ClVector -open GraphBLAS.FSharp.Backend.Objects.ClContext -open GraphBLAS.FSharp.Backend.Quotes -open FSharp.Quotations -open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions -open GraphBLAS.FSharp.Backend.Objects.ClCell -open GraphBLAS.FSharp.Backend.Common - -module internal Map = - let private preparePositions<'a, 'b> (clContext: ClContext) workGroupSize opAdd = - // we can decrease memory requirements by two pass map (like choose) - let preparePositions (op: Expr<'a option -> 'b option>) = - <@ fun (ndRange: Range1D) dataLength vectorLength (values: ClArray<'a>) (indices: ClArray) (resultBitmap: ClArray) (resultValues: ClArray<'b>) (resultIndices: ClArray) -> - - let gid = ndRange.GlobalID0 - - if gid < vectorLength then - - let value = - (%Search.Bin.byKey) dataLength gid indices values - - match (%op) value with - | Some resultValue -> - resultValues.[gid] <- resultValue - resultIndices.[gid] <- gid - - resultBitmap.[gid] <- 1 - | None -> resultBitmap.[gid] <- 0 @> - - let kernel = - clContext.Compile <| preparePositions opAdd - - fun (processor: MailboxProcessor<_>) (vector: ClVector.Sparse<'a>) -> - - let resultBitmap = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, vector.Size) - - let resultIndices = - clContext.CreateClArrayWithSpecificAllocationMode(DeviceOnly, vector.Size) - - let resultValues = - clContext.CreateClArrayWithSpecificAllocationMode<'b>(DeviceOnly, vector.Size) - - let ndRange = - Range1D.CreateValid(vector.Size, workGroupSize) - - let kernel = kernel.GetKernel() - - processor.Post( - Msg.MsgSetArguments - (fun () -> - kernel.KernelFunc - ndRange - vector.Values.Length - vector.Size - vector.Values - vector.Indices - resultBitmap - resultValues - resultIndices) - ) - - processor.Post(Msg.CreateRunMsg<_, _> kernel) - - resultBitmap, resultValues, resultIndices - - let run<'a, 'b when 'a: struct and 'b: struct and 'b: equality> - (clContext: ClContext) - workGroupSize - (opAdd: Expr<'a option -> 'b option>) - = - - let preparePositions = - preparePositions clContext workGroupSize opAdd - - let setPositions = - Common.setPositions<'b> clContext workGroupSize - - fun (queue: MailboxProcessor<_>) allocationMode (vector: ClVector.Sparse<'a>) -> - - let bitmap, values, indices = preparePositions queue vector - - let resultValues, resultIndices = - setPositions queue allocationMode values indices bitmap - - bitmap.Free queue - values.Free queue - indices.Free queue - - { Context = clContext - Indices = resultIndices - Values = resultValues - Size = vector.Size } - - module OnlySome = - let run (clContext: ClContext) workGroupSize op = - - let getOptionBitmap = - ClArray.map clContext workGroupSize - <| Map.chooseBitmap op - - let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize - - let scatter = - Scatter.lastOccurrence clContext workGroupSize - - let setOption = - ClArray.assignOption clContext workGroupSize op - - fun (processor: MailboxProcessor<_>) allocationMode (vector: ClVector.Sparse<'a>) -> - - let bitmap = - getOptionBitmap processor DeviceOnly vector.Values - - let resultLength = - (prefixSum processor bitmap) - .ToHostAndFree processor - - let resultValues = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - - setOption processor vector.Values bitmap resultValues - - let resultIndices = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - - scatter processor vector.Indices bitmap resultIndices - - { Context = clContext - Indices = resultIndices - Values = resultValues - Size = vector.Size } diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Map.fs b/tests/GraphBLAS-sharp.Tests/Vector/Map.fs deleted file mode 100644 index 7d9a74e6..00000000 --- a/tests/GraphBLAS-sharp.Tests/Vector/Map.fs +++ /dev/null @@ -1,66 +0,0 @@ -module GraphBLAS.FSharp.Tests.Vector.Map - -open GraphBLAS.FSharp.Objects -open GraphBLAS.FSharp.Tests -open Expecto -open Expecto.Logging -open GraphBLAS.FSharp.Backend -open GraphBLAS.FSharp.Tests -open Context -open TestCases -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Vector -open GraphBLAS.FSharp.Objects -open GraphBLAS.FSharp.Objects.ClVectorExtensions -open GraphBLAS.FSharp.Backend.Objects.ClContext -open GraphBLAS.FSharp.Backend.Quotes - -let processor = Context.defaultContext.Queue - -let context = Context.defaultContext.ClContext - - -let config = Utils.defaultConfig - -let makeTest<'a> op isEqual zero testFun (array: 'a []) = - - let vector = - Vector.Sparse.FromArray(array, isEqual zero) - - if vector.NNZ > 0 then - let clVector = vector.ToDevice context - - let (clActual: ClVector.Sparse<'a>) = testFun processor HostInterop clVector - - let actual = clActual.ToHost processor - - let expectedIndices, expectedValues = - array - // apply op - |> Array.map - (fun item -> - if isEqual zero item then - None - else - op <| Some item) - // Dense to Sparse - |> Array.mapi - (fun index -> - function - | Some value -> Some(index, value) - | None -> None) - |> Array.choose id - |> Array.unzip - - "Indices must be the same" - |> Utils.compareArrays (=) actual.Indices expectedIndices - - "Values must be the same" - |> Utils.compareArrays isEqual actual.Values expectedValues - -let createTest<'a when 'a: struct and 'a: equality> isEqual (zero: 'a) (opQ, op) = - Vector.Sparse.Map.run context Utils.defaultWorkGroupSize opQ - |> makeTest<'a> op isEqual zero - |> testPropertyWithConfig config $"test on %A{typeof<'a>}" - -let tests = [ createTest (=) 0 ] From 7bdaf88ada05931d439c6ea7f23fb0391fa73644 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 21 Apr 2023 15:52:15 +0300 Subject: [PATCH 21/44] refactor: include gather tests --- tests/GraphBLAS-sharp.Tests/Program.fs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index 637ca279..e2351bab 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -43,7 +43,7 @@ let commonTests = Common.ClArray.Map.tests Common.ClArray.Map2.addTests Common.ClArray.Map2.mulTests - Common.ClArray.Choose.tests + Common.ClArray.Choose.allTests Common.ClArray.ChunkBySize.allTests Common.ClArray.Assign.tests Common.ClArray.Concat.tests @@ -62,7 +62,8 @@ let commonTests = sortTests reduceTests scanTests - Common.Scatter.tests ] + Common.Scatter.allTests + Common.Gather.allTests ] |> testSequenced let vectorTests = From ad66391ccea97663361c0f4f4498e770871a57ff Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sat, 22 Apr 2023 00:41:13 +0300 Subject: [PATCH 22/44] refactor: ClArray.assign -> *.blit --- README.md | 15 +++--- src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs | 4 +- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 52 +++++++++++-------- .../GraphBLAS-sharp.Backend.fsproj | 4 +- .../Matrix/COO/Matrix.fs | 7 +-- .../Matrix/CSR/Map2AtLeastOne.fs | 9 ++-- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 4 +- .../Dense/{DenseVector.fs => Vector.fs} | 8 +-- .../Sparse/{SparseVector.fs => Vector.fs} | 2 +- src/GraphBLAS-sharp.Backend/Vector/Vector.fs | 24 ++++----- .../Common/ClArray/{Assign.fs => Blit.fs} | 14 ++--- tests/GraphBLAS-sharp.Tests/Generators.fs | 14 +++-- .../GraphBLAS-sharp.Tests.fsproj | 2 +- .../Matrix/SpGeMM/Expand.fs | 2 - tests/GraphBLAS-sharp.Tests/Program.fs | 2 +- 15 files changed, 88 insertions(+), 75 deletions(-) rename src/GraphBLAS-sharp.Backend/Vector/Dense/{DenseVector.fs => Vector.fs} (96%) rename src/GraphBLAS-sharp.Backend/Vector/Sparse/{SparseVector.fs => Vector.fs} (99%) rename tests/GraphBLAS-sharp.Tests/Common/ClArray/{Assign.fs => Blit.fs} (71%) diff --git a/README.md b/README.md index 964b619f..87c72287 100644 --- a/README.md +++ b/README.md @@ -25,23 +25,24 @@ GraphBLAS# is a GPGPU-based [GraphBLAS](https://graphblas.org/)-like API impleme ### Operations - **Matrix-Matrix** - - [x] COO-COO element-wize - - [x] CSR-CSR element-wize - - [ ] CSR-CSR multiplication - - [ ] COO transpose - - [ ] CSR transpose + - [x] COO-COO `map2` + - [x] CSR-CSR `map2` + - [x] CSR-CSR multiplication - **Vector-Matrix** - [x] Dense-CSR multiplication - [ ] COO-CSR multiplication - **Vector-Vector** - [x] Dense-Dense element-wise + - [x] Sparse-Sparse element-wise - [ ] ... - **Matrix** - - [ ] `map` + - [x] `map` + - [x] COO transpose + - [x] CSR transpose - [ ] `iter` - [ ] ... - **Vector** - - [ ] `map` + - [x] `map` - [ ] `iter` - [ ] `filter` - [ ] `contains` diff --git a/src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs b/src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs index 4dbb9ba4..2a38c25c 100644 --- a/src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs +++ b/src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs @@ -29,10 +29,10 @@ module BFS = let ofList = Vector.ofList clContext workGroupSize let maskComplementedTo = - DenseVector.map2Inplace clContext Mask.complementedOp workGroupSize + Vector.map2InPlace clContext Mask.complementedOp workGroupSize let fillSubVectorTo = - DenseVector.assignByMaskInplace clContext (Convert.assignToOption Mask.assign) workGroupSize + Vector.assignByMaskInPlace clContext (Convert.assignToOption Mask.assign) workGroupSize let containsNonZero = ClArray.exists clContext workGroupSize Predicates.isSome diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 211984f5..e784280e 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -559,43 +559,53 @@ module ClArray = |> Seq.map (fun lazyValue -> lazyValue.Value) |> Seq.toArray - let assign<'a> (clContext: ClContext) workGroupSize = + let blit<'a> (clContext: ClContext) workGroupSize = let assign = - <@ fun (ndRange: Range1D) targetPosition sourceArrayLength (sourceArray: ClArray<'a>) (targetArray: ClArray<'a>) -> + <@ fun (ndRange: Range1D) sourceIndex (sourceArray: ClArray<'a>) (targetArray: ClArray<'a>) targetPosition count -> let gid = ndRange.GlobalID0 - let resultPosition = gid + targetPosition - - if gid < sourceArrayLength then + if gid < count then + let readPosition = gid + sourceIndex + let writePosition = gid + targetPosition - targetArray.[resultPosition] <- sourceArray.[gid] @> + targetArray.[writePosition] <- sourceArray.[readPosition] @> let kernel = clContext.Compile assign - fun (processor: MailboxProcessor<_>) (sourceArray: ClArray<'a>) targetPosition (targetArray: ClArray<'a>) -> - if targetPosition < 0 then - failwith "The starting position cannot be less than zero" + fun (processor: MailboxProcessor<_>) (sourceArray: ClArray<'a>) sourceIndex (targetArray: ClArray<'a>) targetIndex count -> + // check count + if count < 0 then failwith "Count must be greater than zero" - if targetPosition + sourceArray.Length > targetArray.Length then - failwith "The array should fit completely" + // check sourceIndex + if sourceIndex < 0 + && sourceIndex + count >= sourceArray.Length + then failwith "The source index does not match" - let ndRange = - Range1D.CreateValid(targetArray.Length, workGroupSize) + // check targetPosition + if targetIndex < 0 + && targetIndex + count >= targetArray.Length + then failwith "The target index does not match" - let kernel = kernel.GetKernel() + if count = 0 then () + // nothing to do + else + let ndRange = + Range1D.CreateValid(targetArray.Length, workGroupSize) - processor.Post( - Msg.MsgSetArguments - (fun () -> kernel.KernelFunc ndRange targetPosition sourceArray.Length sourceArray targetArray) - ) + let kernel = kernel.GetKernel() - processor.Post(Msg.CreateRunMsg<_, _>(kernel)) + processor.Post( + Msg.MsgSetArguments + (fun () -> kernel.KernelFunc ndRange sourceIndex sourceArray targetArray targetIndex count) + ) + + processor.Post(Msg.CreateRunMsg<_, _>(kernel)) let concat (clContext: ClContext) workGroupSize = - let assign = assign clContext workGroupSize + let blit = blit clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (sourceArrays: ClArray<'a> seq) -> @@ -609,7 +619,7 @@ module ClArray = // write each array to result Seq.fold (fun previousLength (array: ClArray<_>) -> - assign processor array previousLength result + blit processor array 0 result previousLength array.Length previousLength + array.Length) 0 sourceArrays diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index 2ccc939f..7102f078 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -35,11 +35,11 @@ - + - + diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs index 2230f815..0ac34ba4 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs @@ -6,6 +6,8 @@ open GraphBLAS.FSharp.Backend.Quotes open Microsoft.FSharp.Quotations open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClMatrix +open GraphBLAS.FSharp.Backend.Objects.ClCell +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions module Matrix = let map = Map.run @@ -78,8 +80,7 @@ module Matrix = processor.Post(Msg.MsgSetArguments(fun () -> kernel.KernelFunc ndRange rowIndices nnz rowPointers)) processor.Post(Msg.CreateRunMsg<_, _> kernel) - let result = scan processor rowPointers nnz - processor.Post <| Msg.CreateFreeMsg(result) + (scan processor rowPointers nnz).Free processor rowPointers @@ -114,7 +115,7 @@ module Matrix = let rowPointers = prepare processor allocationMode matrix.Rows matrix.RowCount - processor.Post(Msg.CreateFreeMsg(matrix.Rows)) + matrix.Rows.Free processor { Context = clContext RowCount = matrix.RowCount diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs index 3ec0a7be..1f379b0b 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs @@ -9,6 +9,7 @@ open GraphBLAS.FSharp.Backend open GraphBLAS.FSharp.Backend.Matrix.COO open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClMatrix +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions module internal Map2AtLeastOne = let preparePositions<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> @@ -310,8 +311,8 @@ module internal Map2AtLeastOne = let positions, allValues = preparePositions queue allColumns leftMergedValues rightMergedValues isRowEnd isLeft - queue.Post(Msg.CreateFreeMsg<_>(leftMergedValues)) - queue.Post(Msg.CreateFreeMsg<_>(rightMergedValues)) + leftMergedValues.Free queue + rightMergedValues.Free queue let resultRows, resultColumns, resultValues, _ = setPositions queue allocationMode allRows allColumns allValues positions @@ -338,9 +339,9 @@ module internal Map2AtLeastOne = let elementwiseToCOO = runToCOO clContext opAdd workGroupSize - let toCSRInplace = + let toCSRInPlace = Matrix.toCSRInPlace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrixLeft: ClMatrix.CSR<'a>) (matrixRight: ClMatrix.CSR<'b>) -> elementwiseToCOO queue allocationMode matrixLeft matrixRight - |> toCSRInplace queue allocationMode + |> toCSRInPlace queue allocationMode diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index cc2d45ad..69fa630b 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -16,7 +16,7 @@ module Matrix = let copyData = ClArray.copy clContext workGroupSize let vectorCopy = - Vector.Sparse.SparseVector.copy clContext workGroupSize + Vector.Sparse.Vector.copy clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with @@ -237,7 +237,7 @@ module Matrix = let COOToCSR = COO.Matrix.toCSR clContext workGroupSize let transposeCSR = - CSR.Matrix.transposeInPlace clContext workGroupSize + CSR.Matrix.transpose clContext workGroupSize let CSRToLIL = CSR.Matrix.toLIL clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Vector/Dense/DenseVector.fs b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs similarity index 96% rename from src/GraphBLAS-sharp.Backend/Vector/Dense/DenseVector.fs rename to src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs index 3d37a595..813f52f6 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Dense/DenseVector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs @@ -8,8 +8,8 @@ open GraphBLAS.FSharp.Backend.Objects.ClVector open GraphBLAS.FSharp.Backend.Objects.ClContext open GraphBLAS.FSharp.Backend.Objects.ClCell -module DenseVector = - let map2Inplace<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> +module Vector = + let map2InPlace<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) workGroupSize @@ -40,7 +40,7 @@ module DenseVector = let map2AtLeastOne clContext op workGroupSize = map2 clContext (Convert.atLeastOneToOption op) workGroupSize - let assignByMaskInplace<'a, 'b when 'a: struct and 'b: struct> + let assignByMaskInPlace<'a, 'b when 'a: struct and 'b: struct> (clContext: ClContext) (maskOp: Expr<'a option -> 'b option -> 'a -> 'a option>) workGroupSize @@ -77,7 +77,7 @@ module DenseVector = = let assignByMask = - assignByMaskInplace clContext maskOp workGroupSize + assignByMaskInPlace clContext maskOp workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (leftVector: ClArray<'a option>) (maskVector: ClArray<'b option>) (value: ClCell<'a>) -> let resultVector = diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs similarity index 99% rename from src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs rename to src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs index bf0a9e1a..75cb4d7e 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/SparseVector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs @@ -8,7 +8,7 @@ open Microsoft.FSharp.Quotations open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClVector -module SparseVector = +module Vector = let copy (clContext: ClContext) workGroupSize = let copy = ClArray.copy clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Vector/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Vector.fs index f28c09ad..97a1ca08 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Vector.fs @@ -5,8 +5,6 @@ open GraphBLAS.FSharp.Backend.Quotes open Microsoft.FSharp.Control open Microsoft.FSharp.Quotations open GraphBLAS.FSharp.Backend.Common -open GraphBLAS.FSharp.Backend.Vector.Dense -open GraphBLAS.FSharp.Backend.Vector.Sparse open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClContext open GraphBLAS.FSharp.Backend.Objects.ClVector @@ -80,7 +78,7 @@ module Vector = let copy (clContext: ClContext) workGroupSize = let sparseCopy = - SparseVector.copy clContext workGroupSize + Sparse.Vector.copy clContext workGroupSize let copyOptionData = ClArray.copy clContext workGroupSize @@ -95,7 +93,7 @@ module Vector = let toSparse (clContext: ClContext) workGroupSize = let toSparse = - DenseVector.toSparse clContext workGroupSize + Dense.Vector.toSparse clContext workGroupSize let copy = copy clContext workGroupSize @@ -108,7 +106,7 @@ module Vector = let toDense (clContext: ClContext) workGroupSize = let toDense = - SparseVector.toDense clContext workGroupSize + Sparse.Vector.toDense clContext workGroupSize let copy = ClArray.copy clContext workGroupSize @@ -123,10 +121,10 @@ module Vector = let map2 (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) workGroupSize = let map2Dense = - DenseVector.map2 clContext opAdd workGroupSize + Dense.Vector.map2 clContext opAdd workGroupSize let map2Sparse = - SparseVector.map2 clContext opAdd workGroupSize + Sparse.Vector.map2 clContext opAdd workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) -> match leftVector, rightVector with @@ -140,10 +138,10 @@ module Vector = let map2AtLeastOne (clContext: ClContext) (opAdd: Expr -> 'c option>) workGroupSize = let map2Sparse = - SparseVector.map2AtLeastOne clContext opAdd workGroupSize + Sparse.Vector.map2AtLeastOne clContext opAdd workGroupSize let map2Dense = - DenseVector.map2AtLeastOne clContext opAdd workGroupSize + Dense.Vector.map2AtLeastOne clContext opAdd workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) -> match leftVector, rightVector with @@ -158,10 +156,10 @@ module Vector = let private assignByMaskGeneral<'a, 'b when 'a: struct and 'b: struct> (clContext: ClContext) op workGroupSize = let sparseFillVector = - SparseVector.assignByMask clContext op workGroupSize + Sparse.Vector.assignByMask clContext op workGroupSize let denseFillVector = - DenseVector.assignByMask clContext op workGroupSize + Dense.Vector.assignByMask clContext op workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (vector: ClVector<'a>) (mask: ClVector<'b>) (value: ClCell<'a>) -> match vector, mask with @@ -181,10 +179,10 @@ module Vector = let reduce (clContext: ClContext) workGroupSize (opAdd: Expr<'a -> 'a -> 'a>) = let sparseReduce = - SparseVector.reduce clContext workGroupSize opAdd + Sparse.Vector.reduce clContext workGroupSize opAdd let denseReduce = - DenseVector.reduce clContext workGroupSize opAdd + Dense.Vector.reduce clContext workGroupSize opAdd fun (processor: MailboxProcessor<_>) (vector: ClVector<'a>) -> match vector with diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Blit.fs similarity index 71% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs rename to tests/GraphBLAS-sharp.Tests/Common/ClArray/Blit.fs index 092e3cb8..771f3501 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Assign.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Blit.fs @@ -1,4 +1,4 @@ -module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.Assign +module GraphBLAS.FSharp.Tests.Backend.Common.ClArray.Blit open Expecto open Brahma.FSharp @@ -13,28 +13,28 @@ let processor = Context.defaultContext.Queue let config = { Utils.defaultConfig with - arbitrary = [ typeof ] } + arbitrary = [ typeof ] } -let makeTest<'a> isEqual testFun (source: 'a [], target: 'a [], targetPosition: int) = +let makeTest<'a> isEqual testFun (source: 'a [], sourceIndex, target: 'a [], targetIndex, count) = if source.Length > 0 && target.Length > 0 then let clSource = context.CreateClArray source let clTarget = context.CreateClArray target - testFun processor clSource targetPosition clTarget + testFun processor clSource sourceIndex clTarget targetIndex count clSource.Free processor let actual = clTarget.ToHostAndFree processor // write to target --- target expected - Array.blit source 0 target targetPosition source.Length + Array.blit source sourceIndex target targetIndex count "Results should be the same" |> Utils.compareArrays isEqual actual target let createTest<'a when 'a: equality> isEqual = - ClArray.assign context Utils.defaultWorkGroupSize + ClArray.blit context Utils.defaultWorkGroupSize |> makeTest<'a> isEqual |> testPropertyWithConfig config $"test on %A{typeof<'a>}" @@ -46,4 +46,4 @@ let tests = createTest Utils.float32IsEqual createTest (=) ] - |> testList "Assign" + |> testList "Blit" diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index 7616b6cd..3b737bcf 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -1012,20 +1012,24 @@ module Generators = arrayAndChunkPosition <| Arb.generate |> Arb.fromGen - type AssignArray() = + type Blit() = static let pairOfVectorsOfEqualSize (valuesGenerator: Gen<'a>) = gen { - let! targetArrayLength = Gen.sized <| fun size -> Gen.choose (2, size + 2) + let! targetArrayLength = Gen.sized <| fun size -> Gen.choose (0, size) let! targetArray = Gen.arrayOfLength targetArrayLength valuesGenerator - let! sourceArrayLength = Gen.choose (1, targetArrayLength) + let! sourceArrayLength = Gen.sized <| fun size -> Gen.choose (0, size) let! sourceArray = Gen.arrayOfLength sourceArrayLength valuesGenerator - let! startPosition = Gen.choose (0, targetArrayLength - sourceArrayLength) + let! targetIndex = Gen.choose(0, targetArrayLength) - return (sourceArray, targetArray, startPosition) + let! sourceIndex = Gen.choose (0, sourceArrayLength) + + let! count = Gen.choose(0, (min (targetArrayLength - targetIndex) (sourceArrayLength - sourceIndex))) + + return (sourceArray, sourceIndex, targetArray, targetIndex, count) } static member IntType() = diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index b397735d..ef0e76d8 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -26,7 +26,7 @@ - + diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs index 3081f342..69cda013 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs @@ -198,8 +198,6 @@ let makeGeneralTest<'a when 'a: struct> zero isEqual opMul opAdd testFun (leftAr if leftMatrix.NNZ > 0 && rightMatrix.NNZ > 0 then - printfn $"left matrix rows count: %A{leftMatrix.RowCount}" - let clLeftMatrix = leftMatrix.ToDevice context let clRightMatrix = rightMatrix.ToDevice context diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index e2351bab..b47ee325 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -45,7 +45,7 @@ let commonTests = Common.ClArray.Map2.mulTests Common.ClArray.Choose.allTests Common.ClArray.ChunkBySize.allTests - Common.ClArray.Assign.tests + Common.ClArray.Blit.tests Common.ClArray.Concat.tests Common.ClArray.Fill.tests Common.ClArray.Pairwise.tests ] From 5b9416061cef30efee7edb3e06e56ec683a48e3b Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sat, 22 Apr 2023 09:48:42 +0300 Subject: [PATCH 23/44] refactor: paths --- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 16 +++++++++------- .../GraphBLAS-sharp.Backend.fsproj | 4 ++-- tests/GraphBLAS-sharp.Tests/Generators.fs | 4 ++-- .../GraphBLAS-sharp.Tests.fsproj | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index e784280e..54b59062 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -576,20 +576,22 @@ module ClArray = fun (processor: MailboxProcessor<_>) (sourceArray: ClArray<'a>) sourceIndex (targetArray: ClArray<'a>) targetIndex count -> // check count - if count < 0 then failwith "Count must be greater than zero" + if count < 0 then + failwith "Count must be greater than zero" // check sourceIndex if sourceIndex < 0 - && sourceIndex + count >= sourceArray.Length - then failwith "The source index does not match" + && sourceIndex + count >= sourceArray.Length then + failwith "The source index does not match" // check targetPosition if targetIndex < 0 - && targetIndex + count >= targetArray.Length - then failwith "The target index does not match" + && targetIndex + count >= targetArray.Length then + failwith "The target index does not match" - if count = 0 then () - // nothing to do + if count = 0 then + () + // nothing to do else let ndRange = Range1D.CreateValid(targetArray.Length, workGroupSize) diff --git a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj index 7102f078..920a06f9 100644 --- a/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj +++ b/src/GraphBLAS-sharp.Backend/GraphBLAS-sharp.Backend.fsproj @@ -35,11 +35,11 @@ - + - + diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index 3b737bcf..738224d5 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -1023,11 +1023,11 @@ module Generators = let! sourceArray = Gen.arrayOfLength sourceArrayLength valuesGenerator - let! targetIndex = Gen.choose(0, targetArrayLength) + let! targetIndex = Gen.choose (0, targetArrayLength) let! sourceIndex = Gen.choose (0, sourceArrayLength) - let! count = Gen.choose(0, (min (targetArrayLength - targetIndex) (sourceArrayLength - sourceIndex))) + let! count = Gen.choose (0, (min (targetArrayLength - targetIndex) (sourceArrayLength - sourceIndex))) return (sourceArray, sourceIndex, targetArray, targetIndex, count) } diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index ef0e76d8..9ea04ea9 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -26,7 +26,7 @@ - + From 9cc2155ec06f6fd70199c9f7afc6e917b744d6c3 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sat, 22 Apr 2023 10:23:20 +0300 Subject: [PATCH 24/44] wip: benchmarks --- .../Algorithms/BenchmarksBFS.fs | 164 ++++++++ .../BenchmarksBFS.fs | 6 +- .../Matrix/BenchmarksEWiseAdd.fs | 307 +++++++++++++++ .../Matrix/BenchmarksMxm.fs | 299 ++++++++++++++ .../Vector/BenchmarksMxv.fs | 77 ++++ .../GraphBLAS-sharp.Benchmarks/Vector/Map2.fs | 211 ++++++++++ src/GraphBLAS-sharp/AlgebraicStructures.fs | 55 --- src/GraphBLAS-sharp/Algorithms/BFS.fs | 38 -- .../Algorithms/BetweennessCentrality.fs | 89 ----- .../Algorithms/ShortestPath.fs | 24 -- .../Algorithms/TriangleCounting.fs | 30 -- src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj | 9 - src/GraphBLAS-sharp/GraphblasEvaluation.fs | 88 ----- src/GraphBLAS-sharp/Objects/Matrix.fs | 94 +++-- src/GraphBLAS-sharp/Operations/Matrix.fs | 371 ------------------ src/GraphBLAS-sharp/Operations/Scalar.fs | 44 --- src/GraphBLAS-sharp/Operations/Vector.fs | 316 --------------- src/GraphBLAS-sharp/Predefined/Monoids/Add.fs | 32 -- src/GraphBLAS-sharp/Predefined/Monoids/Any.fs | 8 - src/GraphBLAS-sharp/Predefined/Monoids/Min.fs | 12 - .../Predefined/Semirings/AddMult.fs | 32 -- .../Predefined/Semirings/AnyAll.fs | 8 - .../Predefined/Semirings/MinAdd.fs | 8 - 23 files changed, 1117 insertions(+), 1205 deletions(-) create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BenchmarksBFS.fs create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksEWiseAdd.fs create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksMxm.fs create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Vector/BenchmarksMxv.fs create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs delete mode 100644 src/GraphBLAS-sharp/AlgebraicStructures.fs delete mode 100644 src/GraphBLAS-sharp/Algorithms/BFS.fs delete mode 100644 src/GraphBLAS-sharp/Algorithms/BetweennessCentrality.fs delete mode 100644 src/GraphBLAS-sharp/Algorithms/ShortestPath.fs delete mode 100644 src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs delete mode 100644 src/GraphBLAS-sharp/GraphblasEvaluation.fs delete mode 100644 src/GraphBLAS-sharp/Operations/Matrix.fs delete mode 100644 src/GraphBLAS-sharp/Operations/Scalar.fs delete mode 100644 src/GraphBLAS-sharp/Operations/Vector.fs delete mode 100644 src/GraphBLAS-sharp/Predefined/Monoids/Add.fs delete mode 100644 src/GraphBLAS-sharp/Predefined/Monoids/Any.fs delete mode 100644 src/GraphBLAS-sharp/Predefined/Monoids/Min.fs delete mode 100644 src/GraphBLAS-sharp/Predefined/Semirings/AddMult.fs delete mode 100644 src/GraphBLAS-sharp/Predefined/Semirings/AnyAll.fs delete mode 100644 src/GraphBLAS-sharp/Predefined/Semirings/MinAdd.fs diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BenchmarksBFS.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BenchmarksBFS.fs new file mode 100644 index 00000000..283cbcc2 --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BenchmarksBFS.fs @@ -0,0 +1,164 @@ +namespace GraphBLAS.FSharp.Benchmarks + +open System.IO +open GraphBLAS.FSharp.Backend.Quotes +open GraphBLAS.FSharp.IO +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Configs +open BenchmarkDotNet.Columns +open Brahma.FSharp +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Algorithms +open MatrixExtensions +open ArraysExtensions + +[] +[] +[] +[)>] +type BFSBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + let mutable funToBenchmark = None + let mutable matrix = Unchecked.defaultof<'matrixT> + let mutable matrixHost = Unchecked.defaultof<_> + + let source = 0 + + member val ResultVector = Unchecked.defaultof> with get,set + + [] + member val OclContextInfo = Unchecked.defaultof with get, set + + [] + member val InputMatrixReader = Unchecked.defaultof with get, set + + member this.OclContext:ClContext = (fst this.OclContextInfo).ClContext + member this.WorkGroupSize = snd this.OclContextInfo + + member this.Processor = + let p = (fst this.OclContextInfo).Queue + p.Error.Add(fun e -> failwithf "%A" e) + p + + static member AvaliableContexts = Utils.avaliableContexts + + static member InputMatricesProviderBuilder pathToConfig = + let datasetFolder = "" + pathToConfig + |> Utils.getMatricesFilenames + |> Seq.map + (fun matrixFilename -> + printfn "%A" matrixFilename + + match Path.GetExtension matrixFilename with + | ".mtx" -> + MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) + | _ -> failwith "Unsupported matrix format") + + member this.FunToBenchmark = + match funToBenchmark with + | None -> + let x = buildFunToBenchmark this.OclContext this.WorkGroupSize + funToBenchmark <- Some x + x + | Some x -> x + + member this.ReadMatrix (reader:MtxReader) = + let converter = + match reader.Field with + | Pattern -> converterBool + | _ -> converter + + reader.ReadMatrix converter + + member this.BFS() = + this.ResultVector <- this.FunToBenchmark this.Processor matrix source + + member this.ClearInputMatrix() = + (matrix :> IDeviceMemObject).Dispose this.Processor + + member this.ClearResult() = + this.ResultVector.FreeAndWait this.Processor + + member this.ReadMatrix() = + let matrixReader = this.InputMatrixReader + matrixHost <- this.ReadMatrix matrixReader + + member this.LoadMatrixToGPU() = + matrix <- buildMatrix this.OclContext matrixHost + + abstract member GlobalSetup : unit -> unit + + abstract member IterationCleanup : unit -> unit + + abstract member GlobalCleanup : unit -> unit + + abstract member Benchmark : unit -> unit + +type BFSBenchmarksWithoutDataTransfer() = + + inherit BFSBenchmarks, int>( + (fun context wgSize -> BFS.singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption wgSize), + int, + (fun _ -> Utils.nextInt (System.Random())), + Matrix.ToBackendCSR) + + static member InputMatricesProvider = + BFSBenchmarks<_,_>.InputMatricesProviderBuilder "BFSBenchmarks.txt" + + [] + override this.GlobalSetup() = + this.ReadMatrix () + this.LoadMatrixToGPU () + + [] + override this.IterationCleanup() = + this.ClearResult() + + [] + override this.GlobalCleanup() = + this.ClearInputMatrix() + + [] + override this.Benchmark() = + this.BFS() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + +type BFSBenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix, + resultToHost) = + + inherit BFSBenchmarks<'matrixT, 'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup() = + this.ReadMatrix() + + [] + override this.GlobalCleanup() = () + + [] + override this.IterationCleanup() = + this.ClearInputMatrix() + this.ClearResult() + + [] + override this.Benchmark() = + this.LoadMatrixToGPU() + this.BFS() + this.Processor.PostAndReply Msg.MsgNotifyMe + let res = resultToHost this.ResultVector this.Processor + this.Processor.PostAndReply Msg.MsgNotifyMe + diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksBFS.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksBFS.fs index 283cbcc2..93a52dba 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksBFS.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksBFS.fs @@ -31,7 +31,7 @@ type BFSBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : member val ResultVector = Unchecked.defaultof> with get,set - [] + [] member val OclContextInfo = Unchecked.defaultof with get, set [] @@ -45,7 +45,7 @@ type BFSBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : p.Error.Add(fun e -> failwithf "%A" e) p - static member AvaliableContexts = Utils.avaliableContexts + static member AvailableContexts = Utils.avaliableContexts static member InputMatricesProviderBuilder pathToConfig = let datasetFolder = "" @@ -159,6 +159,6 @@ type BFSBenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemOb this.LoadMatrixToGPU() this.BFS() this.Processor.PostAndReply Msg.MsgNotifyMe - let res = resultToHost this.ResultVector this.Processor + resultToHost this.ResultVector this.Processor this.Processor.PostAndReply Msg.MsgNotifyMe diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksEWiseAdd.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksEWiseAdd.fs new file mode 100644 index 00000000..18aa2cdd --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksEWiseAdd.fs @@ -0,0 +1,307 @@ +namespace GraphBLAS.FSharp.Benchmarks + +open System.IO +open GraphBLAS.FSharp.Backend.Quotes +open GraphBLAS.FSharp.IO +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Configs +open BenchmarkDotNet.Columns +open Brahma.FSharp +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Matrix +open GraphBLAS.FSharp.Objects.Matrix +open GraphBLAS.FSharp.Benchmarks.MatrixExtensions +open GraphBLAS.FSharp.Backend.Objects.ClContext + +[] +[] +[] +[)>] +type EWiseAddBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + let mutable funToBenchmark = None + let mutable firstMatrix = Unchecked.defaultof<'matrixT> + let mutable secondMatrix = Unchecked.defaultof<'matrixT> + let mutable firstMatrixHost = Unchecked.defaultof<_> + let mutable secondMatrixHost = Unchecked.defaultof<_> + + member val ResultMatrix = Unchecked.defaultof<'matrixT> with get,set + + [] + member val OclContextInfo = Unchecked.defaultof with get, set + + [] + member val InputMatrixReader = Unchecked.defaultof with get, set + + member this.OclContext:ClContext = (fst this.OclContextInfo).ClContext + member this.WorkGroupSize = snd this.OclContextInfo + + member this.Processor = + let p = (fst this.OclContextInfo).Queue + p.Error.Add(fun e -> failwithf "%A" e) + p + + static member AvaliableContexts = Utils.avaliableContexts + + static member InputMatricesProviderBuilder pathToConfig = + let datasetFolder = "EWiseAdd" + pathToConfig + |> Utils.getMatricesFilenames + |> Seq.map + (fun matrixFilename -> + printfn "%A" matrixFilename + + match Path.GetExtension matrixFilename with + | ".mtx" -> + MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) + , MtxReader(Utils.getFullPathToMatrix datasetFolder ("squared_" + matrixFilename)) + | _ -> failwith "Unsupported matrix format") + + member this.FunToBenchmark = + match funToBenchmark with + | None -> + let x = buildFunToBenchmark this.OclContext this.WorkGroupSize + funToBenchmark <- Some x + x + | Some x -> x + + member this.ReadMatrix (reader:MtxReader) = + let converter = + match reader.Field with + | Pattern -> converterBool + | _ -> converter + + reader.ReadMatrix converter + + member this.EWiseAddition() = + this.ResultMatrix <- this.FunToBenchmark this.Processor HostInterop firstMatrix secondMatrix + + member this.ClearInputMatrices() = + (firstMatrix :> IDeviceMemObject).Dispose this.Processor + (secondMatrix :> IDeviceMemObject).Dispose this.Processor + + member this.ClearResult() = + (this.ResultMatrix :> IDeviceMemObject).Dispose this.Processor + + member this.ReadMatrices() = + let leftMatrixReader = fst this.InputMatrixReader + let rightMatrixReader = snd this.InputMatrixReader + firstMatrixHost <- this.ReadMatrix leftMatrixReader + secondMatrixHost <- this.ReadMatrix rightMatrixReader + + member this.LoadMatricesToGPU () = + firstMatrix <- buildMatrix this.OclContext firstMatrixHost + secondMatrix <- buildMatrix this.OclContext secondMatrixHost + + abstract member GlobalSetup : unit -> unit + + abstract member IterationCleanup : unit -> unit + + abstract member GlobalCleanup : unit -> unit + + abstract member Benchmark : unit -> unit + +type EWiseAddBenchmarksWithoutDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + inherit EWiseAddBenchmarks<'matrixT, 'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup() = + this.ReadMatrices () + this.LoadMatricesToGPU () + + [] + override this.IterationCleanup () = + this.ClearResult() + + [] + override this.GlobalCleanup () = + this.ClearInputMatrices() + + [] + override this.Benchmark () = + this.EWiseAddition() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + +type EWiseAddBenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix, + resultToHost) = + + inherit EWiseAddBenchmarks<'matrixT, 'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup () = + this.ReadMatrices () + + [] + override this.GlobalCleanup () = () + + [] + override this.IterationCleanup () = + this.ClearInputMatrices() + this.ClearResult() + + [] + override this.Benchmark () = + this.LoadMatricesToGPU() + this.EWiseAddition() + this.Processor.PostAndReply Msg.MsgNotifyMe + let res = resultToHost this.ResultMatrix this.Processor + this.Processor.PostAndReply Msg.MsgNotifyMe + +module M = + let resultToHostCOO (resultMatrix: ClMatrix.COO<'a>) (processor :MailboxProcessor<_>) = + let cols = + let a = Array.zeroCreate resultMatrix.ColumnCount + processor.Post(Msg.CreateToHostMsg<_>(resultMatrix.Columns,a)) + a + let rows = + let a = Array.zeroCreate resultMatrix.RowCount + processor.Post(Msg.CreateToHostMsg(resultMatrix.Rows,a)) + a + let vals = + let a = Array.zeroCreate resultMatrix.Values.Length + processor.Post(Msg.CreateToHostMsg(resultMatrix.Values,a)) + a + { + RowCount = resultMatrix.RowCount + ColumnCount = resultMatrix.ColumnCount + Rows = rows + Columns = cols + Values = vals + } + + +type EWiseAddBenchmarks4Float32COOWithoutDataTransfer() = + + inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( + (fun context wgSize -> COO.Matrix.map2 context ArithmeticOperations.float32SumOption wgSize), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.ToBackendCOO + ) + + static member InputMatricesProvider = + EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + +type EWiseAddBenchmarks4Float32COOWithDataTransfer() = + + inherit EWiseAddBenchmarksWithDataTransfer,float32>( + (fun context wgSize -> COO.Matrix.map2 context ArithmeticOperations.float32SumOption wgSize), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.ToBackendCOO, + M.resultToHostCOO + ) + + static member InputMatricesProvider = + EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + + +type EWiseAddBenchmarks4BoolCOOWithoutDataTransfer() = + + inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( + (fun context wgSize -> COO.Matrix.map2 context ArithmeticOperations.boolSum wgSize), + (fun _ -> true), + (fun _ -> true), + Matrix.ToBackendCOO + ) + + static member InputMatricesProvider = + EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCOO.txt" + + +type EWiseAddBenchmarks4Float32CSRWithoutDataTransfer() = + + inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( + (fun context wgSize -> CSR.Matrix.map2 context ArithmeticOperations.float32SumOption wgSize), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.ToBackendCSR + ) + + static member InputMatricesProvider = + EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32CSR.txt" + + +type EWiseAddBenchmarks4BoolCSRWithoutDataTransfer() = + + inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( + (fun context wgSize -> CSR.Matrix.map2 context ArithmeticOperations.boolSum wgSize), + (fun _ -> true), + (fun _ -> true), + Matrix.ToBackendCSR + ) + + static member InputMatricesProvider = + EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + +// With AtLeastOne + +type EWiseAddAtLeastOneBenchmarks4BoolCOOWithoutDataTransfer() = + + inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( + (fun context wgSize -> COO.Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne wgSize), + (fun _ -> true), + (fun _ -> true), + Matrix.ToBackendCOO + ) + + static member InputMatricesProvider = + EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + +type EWiseAddAtLeastOneBenchmarks4BoolCSRWithoutDataTransfer() = + + inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( + (fun context wgSize -> CSR.Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne wgSize), + (fun _ -> true), + (fun _ -> true), + Matrix.ToBackendCSR + ) + + static member InputMatricesProvider = + EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + +type EWiseAddAtLeastOneBenchmarks4Float32COOWithoutDataTransfer() = + + inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( + (fun context wgSize -> COO.Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne wgSize), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.ToBackendCOO + ) + + static member InputMatricesProvider = + EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + +type EWiseAddAtLeastOneBenchmarks4Float32CSRWithoutDataTransfer() = + + inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( + (fun context wgSize -> CSR.Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne wgSize), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.ToBackendCSR + ) + + static member InputMatricesProvider = + EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksMxm.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksMxm.fs new file mode 100644 index 00000000..efbe86c9 --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksMxm.fs @@ -0,0 +1,299 @@ +namespace GraphBLAS.FSharp.Benchmarks + +open System.IO +open GraphBLAS.FSharp.IO +open BenchmarkDotNet.Attributes +open Brahma.FSharp +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Matrix +open GraphBLAS.FSharp.Benchmarks.MatrixExtensions +open GraphBLAS.FSharp.Backend.Objects.ClContext + +[] +[] +[] +[)>] +type MxmBenchmarks<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + let mutable funToBenchmark = None + let mutable funCSR2CSC = None + let mutable funCSC2CSR = None + + let mutable firstMatrix = Unchecked.defaultof> + let mutable secondMatrix = Unchecked.defaultof> + let mutable mask = Unchecked.defaultof> + + let mutable firstMatrixHost = Unchecked.defaultof<_> + let mutable secondMatrixHost = Unchecked.defaultof<_> + let mutable maskHost = Unchecked.defaultof> + + member val ResultMatrix = Unchecked.defaultof> with get, set + + [] + member val OclContextInfo = Unchecked.defaultof with get, set + + [] + member val InputMatrixReader = Unchecked.defaultof with get, set + + member this.OclContext:ClContext = (fst this.OclContextInfo).ClContext + member this.WorkGroupSize = snd this.OclContextInfo + + member this.Processor = + let p = (fst this.OclContextInfo).Queue + p.Error.Add(fun e -> failwithf "%A" e) + p + + static member AvaliableContexts = Utils.avaliableContexts + + static member InputMatrixProviderBuilder pathToConfig = + let datasetFolder = "Mxm" + pathToConfig + |> Utils.getMatricesFilenames + |> Seq.map + (fun matrixFilename -> + printfn "%A" matrixFilename + + match Path.GetExtension matrixFilename with + | ".mtx" -> + MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) + , MtxReader(Utils.getFullPathToMatrix datasetFolder ("squared_" + matrixFilename)) + | _ -> failwith "Unsupported matrix format") + + member this.FunToBenchmark = + match funToBenchmark with + | None -> + let x = buildFunToBenchmark this.OclContext this.WorkGroupSize + funToBenchmark <- Some x + x + | Some x -> x + + member this.FunCSR2CSC = + match funCSR2CSC with + | None -> + let x = Matrix.toCSCInPlace this.OclContext this.WorkGroupSize + funCSR2CSC <- Some x + x + | Some x -> x + + member this.FunCSC2CSR = + match funCSC2CSR with + | None -> + let x = Matrix.toCSRInPlace this.OclContext this.WorkGroupSize + funCSC2CSR <- Some x + x + | Some x -> x + + member this.ReadMatrix (reader:MtxReader) = + let converter = + match reader.Field with + | Pattern -> converterBool + | _ -> converter + + reader.ReadMatrix converter + + member this.Mxm() = + this.ResultMatrix <- this.FunToBenchmark this.Processor firstMatrix secondMatrix mask + + member this.ClearInputMatrices() = + firstMatrix.Dispose this.Processor + secondMatrix.Dispose this.Processor + mask.Dispose this.Processor + + member this.ClearResult() = + this.ResultMatrix.Dispose this.Processor + + member this.ReadMask(maskReader) = + maskHost <- this.ReadMatrix maskReader + + member this.ReadMatrices() = + let matrixReader, maskReader = this.InputMatrixReader + firstMatrixHost <- this.ReadMatrix matrixReader + secondMatrixHost <- this.ReadMatrix matrixReader + this.ReadMask(maskReader) + + member this.LoadMatricesToGPU () = + firstMatrix <- buildMatrix this.OclContext firstMatrixHost + secondMatrix <- buildMatrix this.OclContext secondMatrixHost + mask <- maskHost.ToDevice this.OclContext + + member this.ConvertSecondMatrixToCSC() = + secondMatrix <- this.FunCSR2CSC this.Processor HostInterop secondMatrix + + member this.ConvertSecondMatrixToCSR() = + secondMatrix <- this.FunCSC2CSR this.Processor HostInterop secondMatrix + + abstract member GlobalSetup : unit -> unit + + abstract member IterationCleanup : unit -> unit + + abstract member GlobalCleanup : unit -> unit + + abstract member Benchmark : unit -> unit + +type MxmBenchmarksMultiplicationOnly<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + inherit MxmBenchmarks<'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup() = + this.ReadMatrices () + this.LoadMatricesToGPU () + this.ConvertSecondMatrixToCSC() + + [] + override this.IterationCleanup () = + this.ClearResult() + + [] + override this.GlobalCleanup () = + this.ClearInputMatrices() + + [] + override this.Benchmark () = + this.Mxm() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + +type MxmBenchmarksWithTransposing<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + inherit MxmBenchmarks<'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup () = + this.ReadMatrices () + this.LoadMatricesToGPU () + + [] + override this.GlobalCleanup () = + this.ClearInputMatrices() + + [] + override this.IterationCleanup () = + this.ClearResult() + this.ConvertSecondMatrixToCSR() + + [] + override this.Benchmark () = + this.ConvertSecondMatrixToCSC() + this.Mxm() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + +module Operations = + let add = <@ fun x y -> Some (x + y) @> + + let addWithFilter = <@ fun x y -> + let res = x + y + if abs res < 1e-8f then None else Some res + @> + + let mult = <@ fun x y -> Some (x * y) @> + + let logicalOr = <@ fun x y -> + let mutable res = None + + match x, y with + | false, false -> res <- None + | _ -> res <- Some true + + res @> + + let logicalAnd = <@ fun x y -> + let mutable res = None + + match x, y with + | true, true -> res <- Some true + | _ -> res <- None + + res @> + +type MxmBenchmarks4Float32MultiplicationOnly() = + + inherit MxmBenchmarksMultiplicationOnly( + (Matrix.SpGeMM.masked Operations.add Operations.mult), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + ) + + static member InputMatrixProvider = + MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" + +type MxmBenchmarks4Float32WithTransposing() = + + inherit MxmBenchmarksWithTransposing( + (Matrix.SpGeMM.masked Operations.add Operations.mult), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + ) + + static member InputMatrixProvider = + MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" + +type MxmBenchmarks4BoolMultiplicationOnly() = + + inherit MxmBenchmarksMultiplicationOnly( + (Matrix.SpGeMM.masked Operations.logicalOr Operations.logicalAnd), + (fun _ -> true), + (fun _ -> true), + (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + ) + + static member InputMatrixProvider = + MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" + +type MxmBenchmarks4BoolWithTransposing() = + + inherit MxmBenchmarksWithTransposing( + (Matrix.SpGeMM.masked Operations.logicalOr Operations.logicalAnd), + (fun _ -> true), + (fun _ -> true), + (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + ) + + static member InputMatrixProvider = + MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" + +type MxmBenchmarks4Float32MultiplicationOnlyWithZerosFilter() = + + inherit MxmBenchmarksMultiplicationOnly( + (Matrix.SpGeMM.masked Operations.addWithFilter Operations.mult), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + ) + + static member InputMatrixProvider = + MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" + +type MxmBenchmarks4Float32WithTransposingWithZerosFilter() = + + inherit MxmBenchmarksWithTransposing( + (Matrix.SpGeMM.masked Operations.addWithFilter Operations.mult), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + ) + + static member InputMatrixProvider = + MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/BenchmarksMxv.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/BenchmarksMxv.fs new file mode 100644 index 00000000..62dade8a --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/BenchmarksMxv.fs @@ -0,0 +1,77 @@ +namespace GraphBLAS.FSharp.Benchmarks + +open GraphBLAS.FSharp +open GraphBLAS.FSharp.Backend +open BenchmarkDotNet.Attributes +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Objects + +[)>] +type MxvBenchmarks() = + let rand = System.Random() + + let mutable matrix = Unchecked.defaultof> + let mutable vector = Unchecked.defaultof> + let semiring = Predefined.AddMult.float + + //TODO fix me + (*[] + member val OclContext = Unchecked.defaultof with get, set + member this.Context = + let (ClContext context) = this.OclContext + context + + [] + member val InputMatrixReader = Unchecked.defaultof with get, set + + [] + member this.BuildMatrix() = + let inputMatrix = this.InputMatrixReader.ReadMatrixReal(float) + + matrix <- + graphblas { + return! Matrix.switch CSR inputMatrix + >>= Matrix.synchronizeAndReturn + } + |> EvalGB.withClContext this.Context + |> EvalGB.runSync + + [] + member this.BuildVector() = + vector <- + graphblas { + return! + [ for i = 0 to matrix.ColumnCount - 1 do if rand.Next() % 2 = 0 then yield (i, 1.) ] + |> Vector.ofList matrix.ColumnCount + // >>= Vector.synchronizeAndReturn + } + |> EvalGB.withClContext this.Context + |> EvalGB.runSync + + [] + member this.Mxv() = + Matrix.mxv semiring matrix vector + |> EvalGB.withClContext this.Context + |> EvalGB.runSync + + [] + member this.ClearBuffers() = + this.Context.Provider.CloseAllBuffers() + + [] + member this.ClearContext() = + let (ClContext context) = this.OclContext + context.Provider.Dispose() + + static member AvaliableContextsProvider = Utils.avaliableContexts + + static member InputMatricesProvider = + "Common.txt" + |> Utils.getMatricesFilenames + |> Seq.map + (fun matrixFilename -> + match Path.GetExtension matrixFilename with + | ".mtx" -> MtxReader(Utils.getFullPathToMatrix "Common" matrixFilename) + | _ -> failwith "Unsupported matrix format" + ) +*) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs new file mode 100644 index 00000000..97d75077 --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs @@ -0,0 +1,211 @@ +namespace GraphBLAS.FSharp.Benchmarks + +open Expecto +open FsCheck +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Configs +open BenchmarkDotNet.Columns +open Brahma.FSharp +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Quotes +open GraphBLAS.FSharp.Tests +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Objects.ClVectorExtensions +open GraphBLAS.FSharp.Backend.Vector +open GraphBLAS.FSharp.Backend.Objects.ClContext + +type VectorConfig() = + inherit ManualConfig() + + do + base.AddColumn( + StatisticColumn.Min, + StatisticColumn.Max + ) + |> ignore + +[] +[] +[] +[)>] +type VectorEWiseBenchmarks<'elem when 'elem : struct>( + buildFunToBenchmark, + generator: Gen * Vector<'elem>>) = + + let mutable funToBenchmark = None + + let mutable firstVector = Unchecked.defaultof> + + let mutable secondVector = Unchecked.defaultof> + + member val HostVectorPair = Unchecked.defaultof * Vector<'elem>> with get, set + + member val ResultVector = Unchecked.defaultof> with get,set + + [] + member val OclContextInfo = Unchecked.defaultof with get, set + + [] + member val Size = Unchecked.defaultof with get, set + + member this.OclContext: ClContext = (fst this.OclContextInfo).ClContext + member this.WorkGroupSize = snd this.OclContextInfo + + member this.Processor = + let p = (fst this.OclContextInfo).Queue + p.Error.Add(fun e -> failwithf "%A" e) + p + + static member AvaliableContexts = Utils.avaliableContexts + + member this.FunToBenchmark = + match funToBenchmark with + | None -> + let x = buildFunToBenchmark this.OclContext this.WorkGroupSize + funToBenchmark <- Some x + x + | Some x -> x + + member this.EWiseAddition() = + this.ResultVector <- this.FunToBenchmark this.Processor HostInterop firstVector secondVector + + member this.ClearInputVectors()= + firstVector.Dispose this.Processor + secondVector.Dispose this.Processor + + member this.ClearResult() = + this.ResultVector.Dispose this.Processor + + member this.CreateVectors() = + this.HostVectorPair <- List.last (Gen.sample this.Size 1 generator) + + member this.LoadVectorsToGPU() = + firstVector <- (fst this.HostVectorPair).ToDevice this.OclContext + secondVector <- (snd this.HostVectorPair).ToDevice this.OclContext + + abstract member GlobalSetup : unit -> unit + + abstract member IterationSetup: unit -> unit + + abstract member Benchmark : unit -> unit + + abstract member IterationCleanup : unit -> unit + + abstract member GlobalCleanup : unit -> unit + + +type VectorEWiseBenchmarksWithoutDataTransfer<'elem when 'elem : struct>( + buildFunToBenchmark, + generator) = + + inherit VectorEWiseBenchmarks<'elem>( + buildFunToBenchmark, + generator) + + [] + override this.GlobalSetup() = () + + [] + override this.IterationSetup() = + this.CreateVectors () + this.LoadVectorsToGPU () + + [] + override this.Benchmark () = + this.EWiseAddition() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + + [] + override this.IterationCleanup () = + this.ClearResult() + this.ClearInputVectors() + + [] + override this.GlobalCleanup() = () + +type VectorEWiseBenchmarksWithDataTransfer<'elem when 'elem : struct>( + buildFunToBenchmark, + generator) = + + inherit VectorEWiseBenchmarks<'elem>( + buildFunToBenchmark, + generator) + + [] + override this.GlobalSetup() = () + + [] + override this.IterationSetup() = + this.CreateVectors() + + [] + override this.Benchmark () = + this.LoadVectorsToGPU() + this.EWiseAddition() + this.Processor.PostAndReply Msg.MsgNotifyMe + this.ResultVector.ToHost this.Processor |> ignore + this.Processor.PostAndReply Msg.MsgNotifyMe + + [] + override this.IterationCleanup () = + this.ClearInputVectors() + this.ClearResult() + + [] + override this.GlobalCleanup() = () + +/// Without data transfer +/// AtLeastOne +type VectorEWiseBenchmarks4FloatSparseWithoutDataTransfer() = + + inherit VectorEWiseBenchmarksWithoutDataTransfer( + (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), + VectorGenerator.floatPair Sparse) + +type VectorEWiseBenchmarks4Int32SparseWithoutDataTransfer() = + + inherit VectorEWiseBenchmarksWithoutDataTransfer( + (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), + VectorGenerator.intPair Sparse) + +/// General + +type VectorEWiseGeneralBenchmarks4FloatSparseWithoutDataTransfer() = + + inherit VectorEWiseBenchmarksWithoutDataTransfer( + (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), + VectorGenerator.floatPair Sparse) + +type VectorEWiseGeneralBenchmarks4Int32SparseWithoutDataTransfer() = + + inherit VectorEWiseBenchmarksWithoutDataTransfer( + (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), + VectorGenerator.intPair Sparse) + +/// With data transfer + +type VectorEWiseBenchmarks4FloatSparseWithDataTransfer() = + + inherit VectorEWiseBenchmarksWithDataTransfer( + (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), + VectorGenerator.floatPair Sparse) + +type VectorEWiseBenchmarks4Int32SparseWithDataTransfer() = + + inherit VectorEWiseBenchmarksWithDataTransfer( + (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), + VectorGenerator.intPair Sparse) + +/// General with data transfer + +type VectorEWiseGeneralBenchmarks4FloatSparseWithDataTransfer() = + + inherit VectorEWiseBenchmarksWithDataTransfer( + (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), + VectorGenerator.floatPair Sparse) + +type VectorEWiseGeneralBenchmarks4Int32SparseWithDataTransfer() = + + inherit VectorEWiseBenchmarksWithDataTransfer( + (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), + VectorGenerator.intPair Sparse) diff --git a/src/GraphBLAS-sharp/AlgebraicStructures.fs b/src/GraphBLAS-sharp/AlgebraicStructures.fs deleted file mode 100644 index 8a048043..00000000 --- a/src/GraphBLAS-sharp/AlgebraicStructures.fs +++ /dev/null @@ -1,55 +0,0 @@ -namespace GraphBLAS.FSharp - -open Microsoft.FSharp.Quotations - -type UnaryOp<'a, 'b> = UnaryOp of Expr<'a -> 'b> -type BinaryOp<'a, 'b, 'c> = BinaryOp of Expr<'a -> 'b -> 'c> - -type ClosedUnaryOp<'a> = ClosedUnaryOp of Expr<'a -> 'a> -type ClosedBinaryOp<'a> = ClosedBinaryOp of Expr<'a -> 'a -> 'a> - -/// Magma with associative (magma is set with closed binary operator) -type ISemigroup<'a> = - abstract Op : ClosedBinaryOp<'a> - -/// Semigroup with identity -type IMonoid<'a> = - abstract Plus : ClosedBinaryOp<'a> - abstract Zero : 'a - -/// Monoid with associative binary operator, -/// for wich Zero is annihilator -type ISemiring<'a> = - abstract Zero : 'a - abstract Plus : ClosedBinaryOp<'a> - abstract Times : ClosedBinaryOp<'a> - -type Semigroup<'a> = - { AssociativeOp: ClosedBinaryOp<'a> } - - interface ISemigroup<'a> with - member this.Op = this.AssociativeOp - -type Monoid<'a> = - { AssociativeOp: ClosedBinaryOp<'a> - Identity: 'a } - - interface ISemigroup<'a> with - member this.Op = this.AssociativeOp - - interface IMonoid<'a> with - member this.Plus = this.AssociativeOp - member this.Zero = this.Identity - -type Semiring<'a> = - { PlusMonoid: Monoid<'a> - TimesSemigroup: Semigroup<'a> } - - interface IMonoid<'a> with - member this.Zero = this.PlusMonoid.Identity - member this.Plus = this.PlusMonoid.AssociativeOp - - interface ISemiring<'a> with - member this.Times = this.TimesSemigroup.AssociativeOp - member this.Zero = this.PlusMonoid.Identity - member this.Plus = this.PlusMonoid.AssociativeOp diff --git a/src/GraphBLAS-sharp/Algorithms/BFS.fs b/src/GraphBLAS-sharp/Algorithms/BFS.fs deleted file mode 100644 index 5972939b..00000000 --- a/src/GraphBLAS-sharp/Algorithms/BFS.fs +++ /dev/null @@ -1,38 +0,0 @@ -namespace GraphBLAS.FSharp.Algorithms - -open GraphBLAS.FSharp.Predefined -open GraphBLAS.FSharp - -module BFS = - let levelSingleSource (matrix: Matrix) (source: int) = - graphblas { - let vertexCount = Matrix.rowCount matrix - let! levels = Vector.zeroCreate vertexCount // v - let! frontier = Vector.ofList vertexCount [ source, 1 ] // q[s] = true - let! transposed = Matrix.transpose matrix // A' - - let mutable currentLevel = 0 - let mutable break' = false - - while not break' do - currentLevel <- currentLevel + 1 - - let! currentLevelScalar = Scalar.create currentLevel - - let! frontierMask = Vector.mask frontier - do! Vector.fillSubVector levels frontierMask currentLevelScalar // v[q] = d - - let! levelsComplemented = Vector.complemented levels - - do! - Matrix.mxvWithMask AddMult.int levelsComplemented transposed frontier // q[!v] = (A' ||.&& q)' = q' ||.&& A -- replace + comp - >>= Vector.assignVector frontier - - let! succ = - Vector.reduce AddMult.int frontier - >>= Scalar.exportValue - - break' <- succ = 0 - - return levels - } diff --git a/src/GraphBLAS-sharp/Algorithms/BetweennessCentrality.fs b/src/GraphBLAS-sharp/Algorithms/BetweennessCentrality.fs deleted file mode 100644 index f07c1ebc..00000000 --- a/src/GraphBLAS-sharp/Algorithms/BetweennessCentrality.fs +++ /dev/null @@ -1,89 +0,0 @@ -namespace GraphBLAS.FSharp.Algorithms - -open GraphBLAS.FSharp.Predefined -open GraphBLAS.FSharp - -module BetweennessCentrality = - // NOTE matrix of bool? - let metric (matrix: Matrix) (source: int) = - graphblas { - let n = Matrix.rowCount matrix - let! delta = Vector.zeroCreate n - let! sigma = Matrix.zeroCreate n n - let! q = Vector.ofList n [ source, 1 ] - let! p = Vector.copy q - - let! pMask = Vector.complemented p - - do! - Matrix.vxmWithMask AddMult.int pMask q matrix - >>= Vector.assignVector q - - let mutable d = 0 - let mutable sum = 0 - let mutable break' = false - - while not break' || sum <> 0 do - break' <- true - - do! Matrix.assignRow sigma d q - - do! - Vector.eWiseAdd Add.int p q - >>= Vector.assignVector p // ? - - let! pMask = Vector.complemented p - - do! - Matrix.vxmWithMask AddMult.int pMask q matrix - >>= Vector.assignVector q - - let! sum' = Vector.reduce Add.int q >>= Scalar.exportValue - - sum <- sum' - d <- d + 1 - - let! t1 = Vector.zeroCreate n - let! t2 = Vector.zeroCreate n - let! t3 = Vector.zeroCreate n - let! t4 = Vector.zeroCreate n - - for i = d - 1 downto 1 do - // t1 <- 1 + delta - do! - Vector.apply (UnaryOp <@ (+) 1.f @>) delta - >>= Vector.assignVector t1 - - // t2 <- sigma.[i, *] - do! - Matrix.extractRow sigma i - >>= Vector.apply (UnaryOp <@ float32 @>) - >>= Vector.assignVector t2 - - // t2 <- t1 / t2 - let! qMask = Vector.mask q - - do! - Vector.apply (UnaryOp <@ (/) 1.f @>) t2 - >>= fun x -> Vector.eWiseMultWithMask AddMult.float32 qMask t1 x - >>= Vector.assignVector t2 - - do! - Matrix.apply (UnaryOp <@ float32 @>) matrix - >>= fun matrix -> Matrix.mxv AddMult.float32 matrix t2 - >>= Vector.assignVector t3 - - // t4 <- sigma.[i - 1, *] * t3 - do! - Matrix.extractRow sigma (i - 1) - >>= Vector.apply (UnaryOp <@ float32 @>) - >>= fun x -> Vector.eWiseMult AddMult.float32 x t3 - >>= Vector.assignVector t4 - - // delta <- delta + t4 - do! - Vector.eWiseAdd Add.float32 delta t4 - >>= Vector.assignVector delta - - return delta - } diff --git a/src/GraphBLAS-sharp/Algorithms/ShortestPath.fs b/src/GraphBLAS-sharp/Algorithms/ShortestPath.fs deleted file mode 100644 index 4fa82474..00000000 --- a/src/GraphBLAS-sharp/Algorithms/ShortestPath.fs +++ /dev/null @@ -1,24 +0,0 @@ -namespace GraphBLAS.FSharp.Algorithms - -open GraphBLAS.FSharp.Predefined -open GraphBLAS.FSharp -open Brahma.FSharp.OpenCL - -module ShortestPath = - // FIXME Unsupported call: min - let singleSource (matrix: Matrix) (source: int) = - graphblas { - let vertexCount = Matrix.rowCount matrix - let! distance = Vector.ofList vertexCount [ source, 0. ] - - let! transposed = Matrix.transpose matrix // A' - - // TODO terminate earlier if we reach a fixed point - for _ = 1 to vertexCount - 1 do - failwith "FIX ME! And rewrite." - //do! - // Matrix.mxv MinAdd.float transposed distance - // >>= Vector.assignVector distance - - return distance - } diff --git a/src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs b/src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs deleted file mode 100644 index e04a97a4..00000000 --- a/src/GraphBLAS-sharp/Algorithms/TriangleCounting.fs +++ /dev/null @@ -1,30 +0,0 @@ -namespace GraphBLAS.FSharp.Algorithms - -open GraphBLAS.FSharp.Predefined -open GraphBLAS.FSharp - -module TriangleCounting = - let sandia (matrix: Matrix) = - graphblas { - let! lowerTriangular = - matrix - |> Matrix.select (UnaryOp <@ fun (i, j, _) -> i <= j @>) - - let! matrix' = - lowerTriangular - |> Matrix.apply ( - UnaryOp - <@ function - | true -> 1 - | false -> 0 @> - ) - - let! transposed = matrix' |> Matrix.transpose - - let! lowerTriangularMask = lowerTriangular |> Matrix.mask - - return! - Matrix.mxmWithMask AddMult.int lowerTriangularMask matrix' transposed - >>= Matrix.reduce Add.int - >>= Scalar.exportValue - } diff --git a/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj b/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj index 6e3620cf..698b8a17 100644 --- a/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj +++ b/src/GraphBLAS-sharp/GraphBLAS-sharp.fsproj @@ -16,21 +16,12 @@ - - - - - - - - - Always diff --git a/src/GraphBLAS-sharp/GraphblasEvaluation.fs b/src/GraphBLAS-sharp/GraphblasEvaluation.fs deleted file mode 100644 index 4997a79a..00000000 --- a/src/GraphBLAS-sharp/GraphblasEvaluation.fs +++ /dev/null @@ -1,88 +0,0 @@ -namespace GraphBLAS.FSharp -// -//open Brahma.FSharp.ClTaskImpl -//open Brahma.FSharp.ClTask -//open Brahma.FSharp -// -//type GraphblasContext = { ClContext: ClContext } -// -//type GraphblasEvaluation<'a> = EvalGB of (GraphblasContext -> 'a) -// -//module EvalGB = -// let defaultEnv = { ClContext = ClContext() } -// -// let private runCl env (ClTask f) = f env -// -// let run env (EvalGB action) = action env -// -// let ask = EvalGB id -// -// let asks f = EvalGB f -// -// let bind f reader = -// EvalGB -// <| fun env -> -// let x = run env reader -// run env (f x) -// -// let (>>=) x f = bind f x -// -// let return' x = EvalGB <| fun _ -> x -// -// let returnFrom x = x -// -// let fromCl clEvaluation = -// EvalGB -// <| fun env -> runCl env.ClContext clEvaluation -// -// let withClContext clContext (EvalGB action) = -// ask -// >>= fun env -> -// return' -// <| action { env with ClContext = clContext } -// -// let runSync (EvalGB action) = -// let result = action defaultEnv -// result -// -//type GraphblasBuilder() = -// member this.Bind(x, f) = EvalGB.bind f x -// member this.Return x = EvalGB.return' x -// member this.ReturnFrom x = x -// -// member this.Zero() = EvalGB.return' () -// -// member this.Combine(m1, m2) = -// EvalGB -// <| fun env -> -// EvalGB.run env m1 -// EvalGB.run env m2 -// -// member this.Delay rest = -// EvalGB <| fun env -> EvalGB.run env <| rest () -// -// member this.While(predicate, body) = -// EvalGB -// <| fun env -> -// while predicate () do -// EvalGB.run env body -// -// member this.For(sequence, f) = -// EvalGB -// <| fun env -> -// for elem in sequence do -// EvalGB.run env (f elem) -// -// member this.TryWith(tryBlock, handler) = -// EvalGB -// <| fun env -> -// try -// EvalGB.run env tryBlock -// with -// | e -> EvalGB.run env (handler e) -// -//[] -//module GraphblasBuilder = -// let graphblas = GraphblasBuilder() -// -// let (>>=) x f = EvalGB.bind f x diff --git a/src/GraphBLAS-sharp/Objects/Matrix.fs b/src/GraphBLAS-sharp/Objects/Matrix.fs index fd7dcadc..e0724e8e 100644 --- a/src/GraphBLAS-sharp/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp/Objects/Matrix.fs @@ -5,6 +5,50 @@ open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClMatrix module Matrix = + type CSR<'a when 'a: struct> = + { RowCount: int + ColumnCount: int + RowPointers: int [] + ColumnIndices: int [] + Values: 'a [] } + + static member FromArray2D(array: 'a [,], isZero: 'a -> bool) = + let rowsCount = array |> Array2D.length1 + let columnsCount = array |> Array2D.length2 + + let convertedMatrix = + [ for i in 0 .. rowsCount - 1 -> array.[i, *] |> List.ofArray ] + |> List.map + (fun row -> + row + |> List.mapi (fun i x -> (x, i)) + |> List.filter (fun pair -> not <| isZero (fst pair))) + |> List.fold + (fun (rowPtrs, valueInx) row -> ((rowPtrs.Head + row.Length) :: rowPtrs), valueInx @ row) + ([ 0 ], []) + + { Values = + convertedMatrix + |> (snd >> List.unzip >> fst) + |> List.toArray + ColumnIndices = + convertedMatrix + |> (snd >> List.unzip >> snd) + |> List.toArray + RowPointers = convertedMatrix |> fst |> List.rev |> List.toArray + RowCount = rowsCount + ColumnCount = columnsCount } + + member this.NNZ = this.Values.Length + + member this.ToDevice(context: ClContext) = + { Context = context + RowCount = this.RowCount + ColumnCount = this.ColumnCount + RowPointers = context.CreateClArray this.RowPointers + Columns = context.CreateClArray this.ColumnIndices + Values = context.CreateClArray this.Values } + type COO<'a when 'a: struct> = { RowCount: int ColumnCount: int @@ -47,49 +91,23 @@ module Matrix = Columns = context.CreateClArray this.Columns Values = context.CreateClArray this.Values } - type CSR<'a when 'a: struct> = - { RowCount: int - ColumnCount: int - RowPointers: int [] - ColumnIndices: int [] - Values: 'a [] } + member this.toCSR = + let rowPointers = + let nnzPerRow = Array.zeroCreate this.RowCount + let rowPointers = Array.zeroCreate this.RowCount - static member FromArray2D(array: 'a [,], isZero: 'a -> bool) = - let rowsCount = array |> Array2D.length1 - let columnsCount = array |> Array2D.length2 + Array.iter (fun rowIndex -> nnzPerRow.[rowIndex] <- nnzPerRow.[rowIndex] + 1) this.Rows - let convertedMatrix = - [ for i in 0 .. rowsCount - 1 -> array.[i, *] |> List.ofArray ] - |> List.map - (fun row -> - row - |> List.mapi (fun i x -> (x, i)) - |> List.filter (fun pair -> not <| isZero (fst pair))) - |> List.fold - (fun (rowPtrs, valueInx) row -> ((rowPtrs.Head + row.Length) :: rowPtrs), valueInx @ row) - ([ 0 ], []) - - { Values = - convertedMatrix - |> (snd >> List.unzip >> fst) - |> List.toArray - ColumnIndices = - convertedMatrix - |> (snd >> List.unzip >> snd) - |> List.toArray - RowPointers = convertedMatrix |> fst |> List.rev |> List.toArray - RowCount = rowsCount - ColumnCount = columnsCount } + for i in 1 .. this.RowCount - 1 do + rowPointers.[i] <- rowPointers.[i - 1] + nnzPerRow.[i - 1] - member this.NNZ = this.Values.Length + rowPointers - member this.ToDevice(context: ClContext) = - { Context = context - RowCount = this.RowCount + { RowCount = this.RowCount ColumnCount = this.ColumnCount - RowPointers = context.CreateClArray this.RowPointers - Columns = context.CreateClArray this.ColumnIndices - Values = context.CreateClArray this.Values } + RowPointers = rowPointers + ColumnIndices = this.Columns + Values = this.Values } type CSC<'a when 'a: struct> = { RowCount: int diff --git a/src/GraphBLAS-sharp/Operations/Matrix.fs b/src/GraphBLAS-sharp/Operations/Matrix.fs deleted file mode 100644 index c36c7973..00000000 --- a/src/GraphBLAS-sharp/Operations/Matrix.fs +++ /dev/null @@ -1,371 +0,0 @@ -namespace GraphBLAS.FSharp - -open Brahma.FSharp.OpenCL -open GraphBLAS.FSharp.Backend - -[] -module Matrix = - - (* - constructors - *) - - let build - (rowCount: int) - (columnCount: int) - (rows: int []) - (columns: int []) - (values: 'a []) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let ofTuples (rowCount: int) (columnCount: int) (tuples: MatrixTuples<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let ofList (rowCount: int) (columnCount: int) (elements: (int * int * 'a) list) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - // можно оставить, но с условием, что будет создаваться full matrix, - // которую можно будет проредить потом (но вообще это initом эмулируется) - // let ofArray2D (array: 'a[,]) : GraphblasEvaluation> = - // failwith "Not Implemented yet"" - - let init (rowCount: int) (columnCount: int) (initializer: int -> int -> 'a) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let create (rowCount: int) (columnCount: int) (value: 'a) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let zeroCreate<'a when 'a: struct> (rowCount: int) (columnCount: int) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - (* - methods - *) - - let rowCount (matrix: Matrix<'a>) : int = matrix.RowCount - let columnCount (matrix: Matrix<'a>) : int = matrix.ColumnCount - - let copy (matrix: Matrix<'a>) : GraphblasEvaluation> = failwith "Not Implemented yet" - - let resize (rowCount: int) (columnCount: int) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - // NOTE int cant be sync - let nnz (matrix: Matrix<'a>) : GraphblasEvaluation = failwith "Not Implemented yet" - - let tuples (matrix: Matrix<'a>) : GraphblasEvaluation> = - match matrix with - | MatrixCOO matrix -> COOMatrix.GetTuples.fromMatrix matrix - | MatrixCSR matrix -> CSRMatrix.GetTuples.fromMatrix matrix - |> EvalGB.fromCl - - let mask (matrix: Matrix<'a>) : GraphblasEvaluation = failwith "Not Implemented yet" - let complemented (matrix: Matrix<'a>) : GraphblasEvaluation = failwith "Not Implemented yet" - - let switch (matrixFormat: MatrixFromat) (matrix: Matrix<'a>) : GraphblasEvaluation> = - match matrix, matrixFormat with - | MatrixCOO matrix, CSR -> - opencl { - let! result = CSRMatrix.Convert.fromCoo matrix - return MatrixCSR result - } - | _ -> failwith "Not Implemented" - |> EvalGB.fromCl - - let synchronize (matrix: Matrix<'a>) : GraphblasEvaluation = failwith "Not Implemented yet" - - let synchronizeAndReturn (matrix: Matrix<'a>) : GraphblasEvaluation> = - match matrix with - | MatrixCSR matrix -> - opencl { - let! _ = - if matrix.RowPointers.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME! And rewrite." - //ToHost matrix.RowPointers - - let! _ = - if matrix.ColumnIndices.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME! And rewrite." - //ToHost matrix.ColumnIndices - - let! _ = - if matrix.Values.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME! And rewrite." - //ToHost matrix.Values - - return MatrixCSR matrix - } - | _ -> failwith "Not Implemented" - |> EvalGB.fromCl - - (* - assignment, extraction and filling - *) - - /// mat.[mask] - let extractSubMatrix (matrix: Matrix<'a>) (mask: Mask2D) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - /// mat.[rowIdx. *] - let extractRow (matrix: Matrix<'a>) (rowIdx: int) : GraphblasEvaluation> = failwith "Not Implemented yet" - - /// mat.[rowIdx, mask] - let extractSubRow (matrix: Matrix<'a>) (rowIdx: int) (mask: Mask2D) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - /// mat.[*, colIdx] - let extractCol (matrix: Matrix<'a>) (colIdx: int) : GraphblasEvaluation> = failwith "Not Implemented yet" - - /// mat.[mask. colIdx] - let extractSubCol (matrix: Matrix<'a>) (mask: Mask2D) (colIdx: int) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - /// mat.[rowIdx, colIdx] - let extractValue (matrix: Matrix<'a>) (rowIdx: int) (colIdx: int) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - /// t <- s - let assignMatrix (target: Matrix<'a>) (source: Matrix<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// t.[mask] <- s - let assignSubMatrix (target: Matrix<'a>) (mask: Mask2D) (source: Matrix<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// t.[rowIdx, *] <- s - let assignRow (target: Matrix<'a>) (rowIdx: int) (source: Vector<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// t.[rowIdx, mask] <- s - let assignSubRow - (target: Matrix<'a>) - (rowIdx: int) - (mask: Mask1D) - (source: Vector<'a>) - : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// t.[*, colIdx] <- s - let assignCol (target: Matrix<'a>) (colIdx: int) (source: Vector<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// t.[mask, colIdx] <- s - let assignSubCol - (target: Matrix<'a>) - (colIdx: int) - (mask: Mask1D) - (source: Vector<'a>) - : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// mat.[*, *] <- value - let fillMatrix (value: Scalar<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation = failwith "Not Implemented yet" - - /// mat.[mask] <- value - let fillSubMatrix (mask: Mask2D) (value: Scalar<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// mat.[rowIdx, *] <- value - let fillRow (rowIdx: int) (value: Scalar<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// mat.[rowIdx, mask] <- value - let fillSubRow (rowIdx: int) (mask: Mask1D) (value: Scalar<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// mat.[*, colIdx] <- value - let fillCol (colIdx: int) (value: Scalar<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// mat.[mask, colIdx] <- value - let fillSubCol (colIdx: int) (mask: Mask1D) (value: Scalar<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - (* - closed unmasked operations - *) - - let mxm - (semiring: ISemiring<'a>) - (leftMatrix: Matrix<'a>) - (rightMatrix: Matrix<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented" - - let mxv (semiring: ISemiring<'a>) (matrix: Matrix<'a>) (vector: Vector<'a>) : GraphblasEvaluation> = - match matrix, vector with - | MatrixCSR matrix, VectorCOO vector -> - opencl { - let! result = CSRMatrix.SpMSpV.unmasked matrix vector semiring - return VectorCOO result - } - | _ -> failwith "Not Implemented" - |> EvalGB.fromCl - - let vxm (semiring: ISemiring<'a>) (vector: Vector<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented" - - let eWiseAdd - (monoid: IMonoid<'a>) - (leftMatrix: Matrix<'a>) - (rightMatrix: Matrix<'a>) - : GraphblasEvaluation> = - match leftMatrix, rightMatrix with - | MatrixCOO left, MatrixCOO right -> failwith "FIX ME! And rewrite." - //opencl { - // let! result = COOMatrix.EWiseAdd.run left right None monoid - // return MatrixCOO result - //} - | _ -> failwith "Not Implemented" - |> EvalGB.fromCl - - let eWiseMult - (semiring: ISemiring<'a>) - (leftMatrix: Matrix<'a>) - (rightMatrix: Matrix<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let apply (mapper: UnaryOp<'a, 'b>) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let select (predicate: UnaryOp) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let reduceRows (monoid: IMonoid<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let reduceCols (monoid: IMonoid<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let reduce (monoid: IMonoid<'a>) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let transpose (matrix: Matrix<'a>) : GraphblasEvaluation> = - match matrix with - | MatrixCSR matrix -> - // map - opencl { - let! transposed = CSRMatrix.Transpose.transposeMatrix matrix - return MatrixCSR transposed - } - | _ -> failwith "Not Implemented" - |> EvalGB.fromCl - - let kronecker - (semiring: ISemiring<'a>) - (leftMatrix: Matrix<'a>) - (rightMatrix: Matrix<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - (* - closed masked operations - *) - - let mxmWithMask - (semiring: ISemiring<'a>) - (mask: Mask2D) - (leftMatrix: Matrix<'a>) - (rightMatrix: Matrix<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let mxvWithMask - (semiring: ISemiring<'a>) - (mask: Mask1D) - (matrix: Matrix<'a>) - (vector: Vector<'a>) - : GraphblasEvaluation> = - match matrix, vector, mask with - | MatrixCSR matrix, VectorCOO vector, mask when not mask.IsComplemented -> - opencl { - let! result = CSRMatrix.SpMSpV.masked matrix vector semiring mask - return VectorCOO result - } - | _ -> failwith "Not Implemented" - |> EvalGB.fromCl - - let vxmWithMask - (semiring: ISemiring<'a>) - (mask: Mask1D) - (vector: Vector<'a>) - (matrix: Matrix<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let eWiseAddWithMask - (monoid: IMonoid<'a>) - (mask: Mask2D) - (leftMatrix: Matrix<'a>) - (rightMatrix: Matrix<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let eWiseMultWithMask - (semiring: ISemiring<'a>) - (mask: Mask2D) - (leftMatrix: Matrix<'a>) - (rightMatrix: Matrix<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let applyWithMask (mapper: UnaryOp<'a, 'b>) (mask: Mask2D) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let selectWithMask - (predicate: UnaryOp) - (mask: Mask2D) - (matrix: Matrix<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let reduceRowsWithMask (monoid: IMonoid<'a>) (mask: Mask1D) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let reduceColsWithMask (monoid: IMonoid<'a>) (mask: Mask1D) (matrix: Matrix<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let kroneckerWithMask - (semiring: ISemiring<'a>) - (mask: Mask2D) - (leftMatrix: Matrix<'a>) - (rightMatrix: Matrix<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - -[] -module MatrixTuples = - let synchronize (matrixTuples: MatrixTuples<'a>) = - opencl { - let! _ = - if matrixTuples.RowIndices.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost matrixTuples.RowIndices - - let! _ = - if matrixTuples.ColumnIndices.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost matrixTuples.ColumnIndices - - let! _ = - if matrixTuples.Values.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost matrixTuples.Values - - return () - } - |> EvalGB.fromCl diff --git a/src/GraphBLAS-sharp/Operations/Scalar.fs b/src/GraphBLAS-sharp/Operations/Scalar.fs deleted file mode 100644 index 4c39d1da..00000000 --- a/src/GraphBLAS-sharp/Operations/Scalar.fs +++ /dev/null @@ -1,44 +0,0 @@ -namespace GraphBLAS.FSharp -// -//open Brahma.FSharp -// -//[] -//module Scalar = -// -// (* -// constructors -// *) -// -// let create (value: 'a) : GraphblasEvaluation> = -// graphblas { return ScalarWrapped { Value = [| value |] } } -// -// (* -// methods -// *) -// -// let copy (scalar: Scalar<'a>) : GraphblasEvaluation> = failwith "Not Implemented yet" -// -// let synchronize (scalar: Scalar<'a>) : GraphblasEvaluation = -// match scalar with -// | ScalarWrapped scalar -> -// opencl { -// failwith "FIX ME!" -// //let! _ = ToHost scalar.Value -// return () -// } -// |> EvalGB.fromCl -// -// (* -// assignment and extraction -// *) -// -// let exportValue (scalar: Scalar<'a>) : GraphblasEvaluation<'a> = -// graphblas { -// do! synchronize scalar -// -// match scalar with -// | ScalarWrapped scalar -> return scalar.Value.[0] -// } -// -// let assignValue (scalar: Scalar<'a>) (target: Scalar<'a>) : GraphblasEvaluation = -// failwith "Not Implemented yet" diff --git a/src/GraphBLAS-sharp/Operations/Vector.fs b/src/GraphBLAS-sharp/Operations/Vector.fs deleted file mode 100644 index 072ddfca..00000000 --- a/src/GraphBLAS-sharp/Operations/Vector.fs +++ /dev/null @@ -1,316 +0,0 @@ -namespace GraphBLAS.FSharp - -open Brahma.FSharp.OpenCL -open GraphBLAS.FSharp.Backend -open GraphBLAS.FSharp.Backend.Common - -[] -module Vector = - - (* - constructors - *) - - let build (size: int) (indices: int []) (values: 'a []) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let ofTuples (size: int) (tuples: VectorTuples<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let ofList (size: int) (elements: (int * 'a) list) : GraphblasEvaluation> = - let (indices, values) = - elements - |> Array.ofList - |> Array.sortBy fst - |> Array.unzip - - graphblas { - return - VectorCOO - <| COOVector.FromTuples(size, indices, values) - } - - // можно оставить, но с условием, что будет создаваться full vector - // let ofArray (array: 'a[]) : GraphblasEvaluation> = - // failwith "Not Implemented yet" - - let init (size: int) (initializer: int -> 'a) : GraphblasEvaluation> = failwith "Not Implemented yet" - - let create (size: int) (value: 'a) : GraphblasEvaluation> = failwith "Not Implemented yet" - - let zeroCreate<'a when 'a: struct> (size: int) : GraphblasEvaluation> = - graphblas { - return - VectorCOO - <| COOVector.FromTuples(size, [||], [||]) - } - - (* - methods - *) - - let size (vector: Vector<'a>) : int = failwith "Not Implemented yet" - let copy (vector: Vector<'a>) : GraphblasEvaluation> = failwith "Not Implemented yet" - let resize (size: int) (vector: Vector<'a>) : GraphblasEvaluation> = failwith "Not Implemented yet" - - // NOTE int cant be sync - let nnz (vector: Vector<'a>) : GraphblasEvaluation = failwith "Not Implemented yet" - - let tuples (vector: Vector<'a>) : GraphblasEvaluation> = - match vector with - | VectorCOO vector -> - opencl { - if vector.Values.Length = 0 then - return { Indices = [||]; Values = [||] } - else - failwith "FIX ME!" - let ind = [||] //let! ind = Copy.copyArray vector.Indices - let vals = [||] //let! vals = Copy.copyArray vector.Values - - return { Indices = ind; Values = vals } - } - |> EvalGB.fromCl - - let mask (vector: Vector<'a>) : GraphblasEvaluation = - match vector with - | VectorCOO vector -> - opencl { - failwith "FIX ME!" - let indices = [||] //let! indices = Copy.copyArray vector.Indices - return Mask1D(indices, vector.Size, false) - } - |> EvalGB.fromCl - - let complemented (vector: Vector<'a>) : GraphblasEvaluation = - match vector with - | VectorCOO vector -> - opencl { - failwith "FIX ME!" - let indices = [||] //let! indices = Copy.copyArray vector.Indices - - let! complementedMask = - Mask.GetComplemented.mask1D - <| Mask1D(indices, vector.Size, true) - - return complementedMask - } - |> EvalGB.fromCl - - let switch (vectorFormat: VectorFormat) (vector: Vector<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let synchronize (vector: Vector<'a>) : GraphblasEvaluation = - match vector with - | VectorCOO vector -> - opencl { - let! _ = - if vector.Indices.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost vector.Indices - - let! _ = - if vector.Values.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost vector.Values - - return () - } - |> EvalGB.fromCl - - let synchronizeAndReturn (vector: Vector<'a>) : GraphblasEvaluation> = - match vector with - | VectorCOO vector -> - opencl { - let! _ = - if vector.Indices.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost vector.Indices - - let! _ = - if vector.Values.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost vector.Values - - return VectorCOO vector - } - |> EvalGB.fromCl - - (* - assignment, extraction and filling - *) - - /// vec.[mask] - let extractSubVector (vector: Vector<'a>) (mask: Mask1D) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - /// vec.[idx] - let extractValue (vector: Vector<'a>) (idx: int) : GraphblasEvaluation> = failwith "Not Implemented yet" - - // assignToVector - /// t <- vec - let assignVector (target: Vector<'a>) (source: Vector<'a>) : GraphblasEvaluation = - if target.Size <> source.Size then - invalidArg "source" - <| sprintf "The size of source vector must be %A. Received: %A" target.Size source.Size - - match source, target with - | VectorCOO source, VectorCOO target -> - opencl { - target.Indices <- source.Indices - target.Values <- source.Values - } - |> EvalGB.fromCl - - /// t.[mask] <- vec - let assignSubVector (target: Vector<'a>) (mask: Mask1D) (source: Vector<'a>) : GraphblasEvaluation = - if target.Size <> mask.Size then - invalidArg "mask" - <| sprintf "The size of mask must be %A. Received: %A" target.Size mask.Size - - if target.Size <> source.Size then - invalidArg "source" - <| sprintf "The size of source vector must be %A. Received: %A" target.Size source.Size - - match source, target, mask with - | VectorCOO source, VectorCOO target, mask when not mask.IsComplemented -> - opencl { - let! (resultIndices, resultValues) = - COOVector.AssignSubVector.run target.Indices target.Values source.Indices source.Values mask.Indices - - target.Indices <- resultIndices - target.Values <- resultValues - } - | _ -> failwith "Not Implemented" - |> EvalGB.fromCl - - /// t.[idx] <- value - let assignValue (target: Vector<'a>) (idx: int) (value: Scalar<'a>) : GraphblasEvaluation = - failwith "Not Implemented yet" - - /// vec.[*] <- value - let fillVector (vector: Vector<'a>) (value: Scalar<'a>) : GraphblasEvaluation = failwith "Not Implemented yet" - - /// vec.[mask] <- value - let fillSubVector (vector: Vector<'a>) (mask: Mask1D) (value: Scalar<'a>) : GraphblasEvaluation = - match vector, value, mask with - | VectorCOO vector, ScalarWrapped scalar, mask when not mask.IsComplemented -> - opencl { - let! (resultIndices, resultValues) = - COOVector.FillSubVector.run vector.Indices vector.Values mask.Indices scalar.Value - - vector.Indices <- resultIndices - vector.Values <- resultValues - } - | _ -> failwith "Not Implemented" - |> EvalGB.fromCl - - (* - operations - *) - - let eWiseAdd - (monoid: IMonoid<'a>) - (leftVector: Vector<'a>) - (rightVector: Vector<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let eWiseMult - (semiring: ISemiring<'a>) - (leftVector: Vector<'a>) - (rightVector: Vector<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let apply (mapper: UnaryOp<'a, 'b>) (vector: Vector<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let select (predicate: UnaryOp<'a, bool>) (vector: Vector<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let reduce (monoid: IMonoid<'a>) (vector: Vector<'a>) : GraphblasEvaluation> = - let (ClosedBinaryOp plus) = monoid.Plus - - match vector with - | VectorCOO vector -> - opencl { - let! result = Sum.run vector.Values plus monoid.Zero - return ScalarWrapped { Value = result } - } - |> EvalGB.fromCl - - let eWiseAddWithMask - (monoid: IMonoid<'a>) - (mask: Mask1D) - (leftVector: Vector<'a>) - (rightVector: Vector<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let eWiseMultWithMask - (semiring: ISemiring<'a>) - (mask: Mask1D) - (leftVector: Vector<'a>) - (rightVector: Vector<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let applyWithMask (mapper: UnaryOp<'a, 'b>) (mask: Mask1D) (vector: Vector<'a>) : GraphblasEvaluation> = - failwith "Not Implemented yet" - - let selectWithMask - (predicate: UnaryOp<'a, bool>) - (mask: Mask1D) - (vector: Vector<'a>) - : GraphblasEvaluation> = - failwith "Not Implemented yet" - -[] -module VectorTuples = - let synchronize (vectorTuples: VectorTuples<'a>) = - opencl { - let! _ = - if vectorTuples.Indices.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost vectorTuples.Indices - - let! _ = - if vectorTuples.Values.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost vectorTuples.Values - - return () - } - |> EvalGB.fromCl - - let synchronizeAndReturn (vectorTuples: VectorTuples<'a>) = - opencl { - let! _ = - if vectorTuples.Indices.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost vectorTuples.Indices - - let! _ = - if vectorTuples.Values.Length = 0 then - opencl { return [||] } - else - failwith "FIX ME!" - //ToHost vectorTuples.Values - - return vectorTuples - } - |> EvalGB.fromCl diff --git a/src/GraphBLAS-sharp/Predefined/Monoids/Add.fs b/src/GraphBLAS-sharp/Predefined/Monoids/Add.fs deleted file mode 100644 index 24af1458..00000000 --- a/src/GraphBLAS-sharp/Predefined/Monoids/Add.fs +++ /dev/null @@ -1,32 +0,0 @@ -namespace GraphBLAS.FSharp.Predefined - -open GraphBLAS.FSharp - -module Add = - let int: Monoid = - { AssociativeOp = ClosedBinaryOp <@ (+) @> - Identity = 0 } - - let float: Monoid = - { AssociativeOp = ClosedBinaryOp <@ (+) @> - Identity = 0. } - - let float32: Monoid = - { AssociativeOp = ClosedBinaryOp <@ (+) @> - Identity = 0.f } - - let sbyte: Monoid = - { AssociativeOp = ClosedBinaryOp <@ (+) @> - Identity = 0y } - - let byte: Monoid = - { AssociativeOp = ClosedBinaryOp <@ (+) @> - Identity = 0uy } - - let int16: Monoid = - { AssociativeOp = ClosedBinaryOp <@ (+) @> - Identity = 0s } - - let uint16: Monoid = - { AssociativeOp = ClosedBinaryOp <@ (+) @> - Identity = 0us } diff --git a/src/GraphBLAS-sharp/Predefined/Monoids/Any.fs b/src/GraphBLAS-sharp/Predefined/Monoids/Any.fs deleted file mode 100644 index 3cbfa8d3..00000000 --- a/src/GraphBLAS-sharp/Predefined/Monoids/Any.fs +++ /dev/null @@ -1,8 +0,0 @@ -namespace GraphBLAS.FSharp.Predefined - -open GraphBLAS.FSharp - -module Any = - let bool: Monoid = - { AssociativeOp = ClosedBinaryOp <@ (||) @> - Identity = false } diff --git a/src/GraphBLAS-sharp/Predefined/Monoids/Min.fs b/src/GraphBLAS-sharp/Predefined/Monoids/Min.fs deleted file mode 100644 index 9249925d..00000000 --- a/src/GraphBLAS-sharp/Predefined/Monoids/Min.fs +++ /dev/null @@ -1,12 +0,0 @@ -namespace GraphBLAS.FSharp.Predefined - -open GraphBLAS.FSharp - -module Min = - let int: Monoid = - { AssociativeOp = ClosedBinaryOp <@ fun x y -> System.Math.Min(x, y) @> - Identity = System.Int32.MaxValue } - - let float: Monoid = - { AssociativeOp = ClosedBinaryOp <@ fun x y -> System.Math.Min(x, y) @> - Identity = System.Double.PositiveInfinity } diff --git a/src/GraphBLAS-sharp/Predefined/Semirings/AddMult.fs b/src/GraphBLAS-sharp/Predefined/Semirings/AddMult.fs deleted file mode 100644 index 4253e33f..00000000 --- a/src/GraphBLAS-sharp/Predefined/Semirings/AddMult.fs +++ /dev/null @@ -1,32 +0,0 @@ -namespace GraphBLAS.FSharp.Predefined - -open GraphBLAS.FSharp - -module AddMult = - let int: Semiring = - { PlusMonoid = Add.int - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (*) @> } } - - let float: Semiring = - { PlusMonoid = Add.float - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (*) @> } } - - let float32: Semiring = - { PlusMonoid = Add.float32 - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (*) @> } } - - let sbyte: Semiring = - { PlusMonoid = Add.sbyte - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (*) @> } } - - let byte: Semiring = - { PlusMonoid = Add.byte - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (*) @> } } - - let int16: Semiring = - { PlusMonoid = Add.int16 - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (*) @> } } - - let uint16: Semiring = - { PlusMonoid = Add.uint16 - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (*) @> } } diff --git a/src/GraphBLAS-sharp/Predefined/Semirings/AnyAll.fs b/src/GraphBLAS-sharp/Predefined/Semirings/AnyAll.fs deleted file mode 100644 index ea0d532b..00000000 --- a/src/GraphBLAS-sharp/Predefined/Semirings/AnyAll.fs +++ /dev/null @@ -1,8 +0,0 @@ -namespace GraphBLAS.FSharp.Predefined - -open GraphBLAS.FSharp - -module AnyAll = - let bool: Semiring = - { PlusMonoid = Any.bool - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (&&) @> } } diff --git a/src/GraphBLAS-sharp/Predefined/Semirings/MinAdd.fs b/src/GraphBLAS-sharp/Predefined/Semirings/MinAdd.fs deleted file mode 100644 index fd23eb3f..00000000 --- a/src/GraphBLAS-sharp/Predefined/Semirings/MinAdd.fs +++ /dev/null @@ -1,8 +0,0 @@ -namespace GraphBLAS.FSharp.Predefined - -open GraphBLAS.FSharp - -module MinAdd = - let float: Semiring = - { PlusMonoid = Min.float - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (+) @> } } From 9e8b9bc5fef06bac0628607fce68826072c7cb95 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sat, 22 Apr 2023 11:20:07 +0300 Subject: [PATCH 25/44] refactor: benchmarks --- .../{BenchmarksBFS.fs => Algorithms/BFS.fs} | 140 ++++---- .../Algorithms/BenchmarksBFS.fs | 164 ---------- .../BenchmarksEWiseAdd.fs | 307 ------------------ .../BenchmarksMxm.fs | 299 ----------------- .../BenchmarksMxv.fs | 77 ----- .../Matrix/BenchmarksEWiseAdd.fs | 307 ------------------ .../Matrix/Map2/Map2.fs | 281 ++++++++++++++++ .../Map2/MathNET.fs} | 13 +- .../{BenchmarksMxm.fs => SpGeMM/Masked.fs} | 102 +++--- .../MatrixExtensions.fs | 91 ------ .../Vector/BenchmarksMxv.fs | 77 ----- .../GraphBLAS-sharp.Benchmarks/Vector/Map2.fs | 75 ++--- .../VectorEWiseAddGen.fs | 211 ------------ 13 files changed, 437 insertions(+), 1707 deletions(-) rename benchmarks/GraphBLAS-sharp.Benchmarks/{BenchmarksBFS.fs => Algorithms/BFS.fs} (50%) delete mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BenchmarksBFS.fs delete mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksEWiseAdd.fs delete mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs delete mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxv.fs delete mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksEWiseAdd.fs create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs rename benchmarks/GraphBLAS-sharp.Benchmarks/{BenchmarksMathNET.fs => Matrix/Map2/MathNET.fs} (88%) rename benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/{BenchmarksMxm.fs => SpGeMM/Masked.fs} (78%) delete mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/MatrixExtensions.fs delete mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Vector/BenchmarksMxv.fs delete mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/VectorEWiseAddGen.fs diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksBFS.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs similarity index 50% rename from benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksBFS.fs rename to benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs index 93a52dba..1b4c06c3 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksBFS.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs @@ -1,43 +1,41 @@ namespace GraphBLAS.FSharp.Benchmarks open System.IO +open BenchmarkDotNet.Attributes +open GraphBLAS.FSharp open GraphBLAS.FSharp.Backend.Quotes open GraphBLAS.FSharp.IO -open BenchmarkDotNet.Attributes -open BenchmarkDotNet.Configs -open BenchmarkDotNet.Columns open Brahma.FSharp -open GraphBLAS.FSharp.Objects +open Backend.Algorithms.BFS +open Microsoft.FSharp.Core +open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions +open GraphBLAS.FSharp.Benchmarks open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Algorithms -open MatrixExtensions -open ArraysExtensions [] -[] -[] -[)>] -type BFSBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = +[] +[] +[)>] +type BFSBenchmarks<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + binaryConverter, + vertex: int) + = let mutable funToBenchmark = None - let mutable matrix = Unchecked.defaultof<'matrixT> + let mutable matrix = Unchecked.defaultof> let mutable matrixHost = Unchecked.defaultof<_> - let source = 0 - - member val ResultVector = Unchecked.defaultof> with get,set + member val ResultLevels = Unchecked.defaultof> with get,set [] member val OclContextInfo = Unchecked.defaultof with get, set - [] + [] member val InputMatrixReader = Unchecked.defaultof with get, set - member this.OclContext:ClContext = (fst this.OclContextInfo).ClContext + member this.OclContext = (fst this.OclContextInfo).ClContext member this.WorkGroupSize = snd this.OclContextInfo member this.Processor = @@ -47,8 +45,8 @@ type BFSBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : static member AvailableContexts = Utils.avaliableContexts - static member InputMatricesProviderBuilder pathToConfig = - let datasetFolder = "" + static member InputMatrixProviderBuilder pathToConfig = + let datasetFolder = "BFS" pathToConfig |> Utils.getMatricesFilenames |> Seq.map @@ -56,8 +54,7 @@ type BFSBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : printfn "%A" matrixFilename match Path.GetExtension matrixFilename with - | ".mtx" -> - MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) + | ".mtx" -> MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) | _ -> failwith "Unsupported matrix format") member this.FunToBenchmark = @@ -68,29 +65,24 @@ type BFSBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : x | Some x -> x - member this.ReadMatrix (reader:MtxReader) = - let converter = - match reader.Field with - | Pattern -> converterBool - | _ -> converter - - reader.ReadMatrix converter - member this.BFS() = - this.ResultVector <- this.FunToBenchmark this.Processor matrix source + this.ResultLevels <- this.FunToBenchmark this.Processor matrix vertex member this.ClearInputMatrix() = (matrix :> IDeviceMemObject).Dispose this.Processor - member this.ClearResult() = - this.ResultVector.FreeAndWait this.Processor + member this.ClearResult() = this.ResultLevels.FreeAndWait this.Processor member this.ReadMatrix() = - let matrixReader = this.InputMatrixReader - matrixHost <- this.ReadMatrix matrixReader + let converter = + match this.InputMatrixReader.Field with + | Pattern -> binaryConverter + | _ -> converter + + matrixHost <- this.InputMatrixReader.ReadMatrix converter member this.LoadMatrixToGPU() = - matrix <- buildMatrix this.OclContext matrixHost + matrix <- matrixHost.ToCSR.ToDevice this.OclContext abstract member GlobalSetup : unit -> unit @@ -100,21 +92,22 @@ type BFSBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : abstract member Benchmark : unit -> unit -type BFSBenchmarksWithoutDataTransfer() = +type BFSBenchmarksWithoutDataTransfer<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + boolConverter, + vertex) = - inherit BFSBenchmarks, int>( - (fun context wgSize -> BFS.singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption wgSize), - int, - (fun _ -> Utils.nextInt (System.Random())), - Matrix.ToBackendCSR) - - static member InputMatricesProvider = - BFSBenchmarks<_,_>.InputMatricesProviderBuilder "BFSBenchmarks.txt" + inherit BFSBenchmarks<'elem>( + buildFunToBenchmark, + converter, + boolConverter, + vertex) [] override this.GlobalSetup() = - this.ReadMatrix () - this.LoadMatrixToGPU () + this.ReadMatrix() + this.LoadMatrixToGPU() [] override this.IterationCleanup() = @@ -127,27 +120,27 @@ type BFSBenchmarksWithoutDataTransfer() = [] override this.Benchmark() = this.BFS() - this.Processor.PostAndReply(Msg.MsgNotifyMe) + this.Processor.PostAndReply Msg.MsgNotifyMe -type BFSBenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix, - resultToHost) = +type BFSBenchmarksWithTransfer<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + boolConverter, + vertex) = - inherit BFSBenchmarks<'matrixT, 'elem>( + inherit BFSBenchmarks<'elem>( buildFunToBenchmark, converter, - converterBool, - buildMatrix) + boolConverter, + vertex) [] override this.GlobalSetup() = this.ReadMatrix() [] - override this.GlobalCleanup() = () + override this.GlobalCleanup() = + this.ClearResult() [] override this.IterationCleanup() = @@ -158,7 +151,28 @@ type BFSBenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemOb override this.Benchmark() = this.LoadMatrixToGPU() this.BFS() + this.ResultLevels.ToHost this.Processor |> ignore this.Processor.PostAndReply Msg.MsgNotifyMe - resultToHost this.ResultVector this.Processor - this.Processor.PostAndReply Msg.MsgNotifyMe + +type BFSIntWithoutTransferBenchmark() = + + inherit BFSBenchmarksWithoutDataTransfer( + (fun context -> singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), + int32, + (fun _ -> Utils.nextInt (System.Random())), + 0) + + static member InputMatrixProvider = + BFSBenchmarks<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" + +type BFSIntWithTransferBenchmark() = + + inherit BFSBenchmarksWithTransfer( + (fun context -> singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), + int32, + (fun _ -> Utils.nextInt (System.Random())), + 0) + + static member InputMatrixProvider = + BFSBenchmarks<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BenchmarksBFS.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BenchmarksBFS.fs deleted file mode 100644 index 283cbcc2..00000000 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BenchmarksBFS.fs +++ /dev/null @@ -1,164 +0,0 @@ -namespace GraphBLAS.FSharp.Benchmarks - -open System.IO -open GraphBLAS.FSharp.Backend.Quotes -open GraphBLAS.FSharp.IO -open BenchmarkDotNet.Attributes -open BenchmarkDotNet.Configs -open BenchmarkDotNet.Columns -open Brahma.FSharp -open GraphBLAS.FSharp.Objects -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Algorithms -open MatrixExtensions -open ArraysExtensions - -[] -[] -[] -[)>] -type BFSBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - let mutable funToBenchmark = None - let mutable matrix = Unchecked.defaultof<'matrixT> - let mutable matrixHost = Unchecked.defaultof<_> - - let source = 0 - - member val ResultVector = Unchecked.defaultof> with get,set - - [] - member val OclContextInfo = Unchecked.defaultof with get, set - - [] - member val InputMatrixReader = Unchecked.defaultof with get, set - - member this.OclContext:ClContext = (fst this.OclContextInfo).ClContext - member this.WorkGroupSize = snd this.OclContextInfo - - member this.Processor = - let p = (fst this.OclContextInfo).Queue - p.Error.Add(fun e -> failwithf "%A" e) - p - - static member AvaliableContexts = Utils.avaliableContexts - - static member InputMatricesProviderBuilder pathToConfig = - let datasetFolder = "" - pathToConfig - |> Utils.getMatricesFilenames - |> Seq.map - (fun matrixFilename -> - printfn "%A" matrixFilename - - match Path.GetExtension matrixFilename with - | ".mtx" -> - MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) - | _ -> failwith "Unsupported matrix format") - - member this.FunToBenchmark = - match funToBenchmark with - | None -> - let x = buildFunToBenchmark this.OclContext this.WorkGroupSize - funToBenchmark <- Some x - x - | Some x -> x - - member this.ReadMatrix (reader:MtxReader) = - let converter = - match reader.Field with - | Pattern -> converterBool - | _ -> converter - - reader.ReadMatrix converter - - member this.BFS() = - this.ResultVector <- this.FunToBenchmark this.Processor matrix source - - member this.ClearInputMatrix() = - (matrix :> IDeviceMemObject).Dispose this.Processor - - member this.ClearResult() = - this.ResultVector.FreeAndWait this.Processor - - member this.ReadMatrix() = - let matrixReader = this.InputMatrixReader - matrixHost <- this.ReadMatrix matrixReader - - member this.LoadMatrixToGPU() = - matrix <- buildMatrix this.OclContext matrixHost - - abstract member GlobalSetup : unit -> unit - - abstract member IterationCleanup : unit -> unit - - abstract member GlobalCleanup : unit -> unit - - abstract member Benchmark : unit -> unit - -type BFSBenchmarksWithoutDataTransfer() = - - inherit BFSBenchmarks, int>( - (fun context wgSize -> BFS.singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption wgSize), - int, - (fun _ -> Utils.nextInt (System.Random())), - Matrix.ToBackendCSR) - - static member InputMatricesProvider = - BFSBenchmarks<_,_>.InputMatricesProviderBuilder "BFSBenchmarks.txt" - - [] - override this.GlobalSetup() = - this.ReadMatrix () - this.LoadMatrixToGPU () - - [] - override this.IterationCleanup() = - this.ClearResult() - - [] - override this.GlobalCleanup() = - this.ClearInputMatrix() - - [] - override this.Benchmark() = - this.BFS() - this.Processor.PostAndReply(Msg.MsgNotifyMe) - -type BFSBenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix, - resultToHost) = - - inherit BFSBenchmarks<'matrixT, 'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup() = - this.ReadMatrix() - - [] - override this.GlobalCleanup() = () - - [] - override this.IterationCleanup() = - this.ClearInputMatrix() - this.ClearResult() - - [] - override this.Benchmark() = - this.LoadMatrixToGPU() - this.BFS() - this.Processor.PostAndReply Msg.MsgNotifyMe - let res = resultToHost this.ResultVector this.Processor - this.Processor.PostAndReply Msg.MsgNotifyMe - diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksEWiseAdd.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksEWiseAdd.fs deleted file mode 100644 index 18aa2cdd..00000000 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksEWiseAdd.fs +++ /dev/null @@ -1,307 +0,0 @@ -namespace GraphBLAS.FSharp.Benchmarks - -open System.IO -open GraphBLAS.FSharp.Backend.Quotes -open GraphBLAS.FSharp.IO -open BenchmarkDotNet.Attributes -open BenchmarkDotNet.Configs -open BenchmarkDotNet.Columns -open Brahma.FSharp -open GraphBLAS.FSharp.Objects -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Matrix -open GraphBLAS.FSharp.Objects.Matrix -open GraphBLAS.FSharp.Benchmarks.MatrixExtensions -open GraphBLAS.FSharp.Backend.Objects.ClContext - -[] -[] -[] -[)>] -type EWiseAddBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - let mutable funToBenchmark = None - let mutable firstMatrix = Unchecked.defaultof<'matrixT> - let mutable secondMatrix = Unchecked.defaultof<'matrixT> - let mutable firstMatrixHost = Unchecked.defaultof<_> - let mutable secondMatrixHost = Unchecked.defaultof<_> - - member val ResultMatrix = Unchecked.defaultof<'matrixT> with get,set - - [] - member val OclContextInfo = Unchecked.defaultof with get, set - - [] - member val InputMatrixReader = Unchecked.defaultof with get, set - - member this.OclContext:ClContext = (fst this.OclContextInfo).ClContext - member this.WorkGroupSize = snd this.OclContextInfo - - member this.Processor = - let p = (fst this.OclContextInfo).Queue - p.Error.Add(fun e -> failwithf "%A" e) - p - - static member AvaliableContexts = Utils.avaliableContexts - - static member InputMatricesProviderBuilder pathToConfig = - let datasetFolder = "EWiseAdd" - pathToConfig - |> Utils.getMatricesFilenames - |> Seq.map - (fun matrixFilename -> - printfn "%A" matrixFilename - - match Path.GetExtension matrixFilename with - | ".mtx" -> - MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) - , MtxReader(Utils.getFullPathToMatrix datasetFolder ("squared_" + matrixFilename)) - | _ -> failwith "Unsupported matrix format") - - member this.FunToBenchmark = - match funToBenchmark with - | None -> - let x = buildFunToBenchmark this.OclContext this.WorkGroupSize - funToBenchmark <- Some x - x - | Some x -> x - - member this.ReadMatrix (reader:MtxReader) = - let converter = - match reader.Field with - | Pattern -> converterBool - | _ -> converter - - reader.ReadMatrix converter - - member this.EWiseAddition() = - this.ResultMatrix <- this.FunToBenchmark this.Processor HostInterop firstMatrix secondMatrix - - member this.ClearInputMatrices() = - (firstMatrix :> IDeviceMemObject).Dispose this.Processor - (secondMatrix :> IDeviceMemObject).Dispose this.Processor - - member this.ClearResult() = - (this.ResultMatrix :> IDeviceMemObject).Dispose this.Processor - - member this.ReadMatrices() = - let leftMatrixReader = fst this.InputMatrixReader - let rightMatrixReader = snd this.InputMatrixReader - firstMatrixHost <- this.ReadMatrix leftMatrixReader - secondMatrixHost <- this.ReadMatrix rightMatrixReader - - member this.LoadMatricesToGPU () = - firstMatrix <- buildMatrix this.OclContext firstMatrixHost - secondMatrix <- buildMatrix this.OclContext secondMatrixHost - - abstract member GlobalSetup : unit -> unit - - abstract member IterationCleanup : unit -> unit - - abstract member GlobalCleanup : unit -> unit - - abstract member Benchmark : unit -> unit - -type EWiseAddBenchmarksWithoutDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - inherit EWiseAddBenchmarks<'matrixT, 'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup() = - this.ReadMatrices () - this.LoadMatricesToGPU () - - [] - override this.IterationCleanup () = - this.ClearResult() - - [] - override this.GlobalCleanup () = - this.ClearInputMatrices() - - [] - override this.Benchmark () = - this.EWiseAddition() - this.Processor.PostAndReply(Msg.MsgNotifyMe) - -type EWiseAddBenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix, - resultToHost) = - - inherit EWiseAddBenchmarks<'matrixT, 'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup () = - this.ReadMatrices () - - [] - override this.GlobalCleanup () = () - - [] - override this.IterationCleanup () = - this.ClearInputMatrices() - this.ClearResult() - - [] - override this.Benchmark () = - this.LoadMatricesToGPU() - this.EWiseAddition() - this.Processor.PostAndReply Msg.MsgNotifyMe - let res = resultToHost this.ResultMatrix this.Processor - this.Processor.PostAndReply Msg.MsgNotifyMe - -module M = - let resultToHostCOO (resultMatrix: ClMatrix.COO<'a>) (processor :MailboxProcessor<_>) = - let cols = - let a = Array.zeroCreate resultMatrix.ColumnCount - processor.Post(Msg.CreateToHostMsg<_>(resultMatrix.Columns,a)) - a - let rows = - let a = Array.zeroCreate resultMatrix.RowCount - processor.Post(Msg.CreateToHostMsg(resultMatrix.Rows,a)) - a - let vals = - let a = Array.zeroCreate resultMatrix.Values.Length - processor.Post(Msg.CreateToHostMsg(resultMatrix.Values,a)) - a - { - RowCount = resultMatrix.RowCount - ColumnCount = resultMatrix.ColumnCount - Rows = rows - Columns = cols - Values = vals - } - - -type EWiseAddBenchmarks4Float32COOWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( - (fun context wgSize -> COO.Matrix.map2 context ArithmeticOperations.float32SumOption wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - -type EWiseAddBenchmarks4Float32COOWithDataTransfer() = - - inherit EWiseAddBenchmarksWithDataTransfer,float32>( - (fun context wgSize -> COO.Matrix.map2 context ArithmeticOperations.float32SumOption wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCOO, - M.resultToHostCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - - -type EWiseAddBenchmarks4BoolCOOWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( - (fun context wgSize -> COO.Matrix.map2 context ArithmeticOperations.boolSum wgSize), - (fun _ -> true), - (fun _ -> true), - Matrix.ToBackendCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCOO.txt" - - -type EWiseAddBenchmarks4Float32CSRWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( - (fun context wgSize -> CSR.Matrix.map2 context ArithmeticOperations.float32SumOption wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCSR - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32CSR.txt" - - -type EWiseAddBenchmarks4BoolCSRWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( - (fun context wgSize -> CSR.Matrix.map2 context ArithmeticOperations.boolSum wgSize), - (fun _ -> true), - (fun _ -> true), - Matrix.ToBackendCSR - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" - -// With AtLeastOne - -type EWiseAddAtLeastOneBenchmarks4BoolCOOWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( - (fun context wgSize -> COO.Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne wgSize), - (fun _ -> true), - (fun _ -> true), - Matrix.ToBackendCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" - -type EWiseAddAtLeastOneBenchmarks4BoolCSRWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( - (fun context wgSize -> CSR.Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne wgSize), - (fun _ -> true), - (fun _ -> true), - Matrix.ToBackendCSR - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" - -type EWiseAddAtLeastOneBenchmarks4Float32COOWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( - (fun context wgSize -> COO.Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - -type EWiseAddAtLeastOneBenchmarks4Float32CSRWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( - (fun context wgSize -> CSR.Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCSR - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs deleted file mode 100644 index efbe86c9..00000000 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxm.fs +++ /dev/null @@ -1,299 +0,0 @@ -namespace GraphBLAS.FSharp.Benchmarks - -open System.IO -open GraphBLAS.FSharp.IO -open BenchmarkDotNet.Attributes -open Brahma.FSharp -open GraphBLAS.FSharp.Objects -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Matrix -open GraphBLAS.FSharp.Benchmarks.MatrixExtensions -open GraphBLAS.FSharp.Backend.Objects.ClContext - -[] -[] -[] -[)>] -type MxmBenchmarks<'elem when 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - let mutable funToBenchmark = None - let mutable funCSR2CSC = None - let mutable funCSC2CSR = None - - let mutable firstMatrix = Unchecked.defaultof> - let mutable secondMatrix = Unchecked.defaultof> - let mutable mask = Unchecked.defaultof> - - let mutable firstMatrixHost = Unchecked.defaultof<_> - let mutable secondMatrixHost = Unchecked.defaultof<_> - let mutable maskHost = Unchecked.defaultof> - - member val ResultMatrix = Unchecked.defaultof> with get, set - - [] - member val OclContextInfo = Unchecked.defaultof with get, set - - [] - member val InputMatrixReader = Unchecked.defaultof with get, set - - member this.OclContext:ClContext = (fst this.OclContextInfo).ClContext - member this.WorkGroupSize = snd this.OclContextInfo - - member this.Processor = - let p = (fst this.OclContextInfo).Queue - p.Error.Add(fun e -> failwithf "%A" e) - p - - static member AvaliableContexts = Utils.avaliableContexts - - static member InputMatrixProviderBuilder pathToConfig = - let datasetFolder = "Mxm" - pathToConfig - |> Utils.getMatricesFilenames - |> Seq.map - (fun matrixFilename -> - printfn "%A" matrixFilename - - match Path.GetExtension matrixFilename with - | ".mtx" -> - MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) - , MtxReader(Utils.getFullPathToMatrix datasetFolder ("squared_" + matrixFilename)) - | _ -> failwith "Unsupported matrix format") - - member this.FunToBenchmark = - match funToBenchmark with - | None -> - let x = buildFunToBenchmark this.OclContext this.WorkGroupSize - funToBenchmark <- Some x - x - | Some x -> x - - member this.FunCSR2CSC = - match funCSR2CSC with - | None -> - let x = Matrix.toCSCInPlace this.OclContext this.WorkGroupSize - funCSR2CSC <- Some x - x - | Some x -> x - - member this.FunCSC2CSR = - match funCSC2CSR with - | None -> - let x = Matrix.toCSRInPlace this.OclContext this.WorkGroupSize - funCSC2CSR <- Some x - x - | Some x -> x - - member this.ReadMatrix (reader:MtxReader) = - let converter = - match reader.Field with - | Pattern -> converterBool - | _ -> converter - - reader.ReadMatrix converter - - member this.Mxm() = - this.ResultMatrix <- this.FunToBenchmark this.Processor firstMatrix secondMatrix mask - - member this.ClearInputMatrices() = - firstMatrix.Dispose this.Processor - secondMatrix.Dispose this.Processor - mask.Dispose this.Processor - - member this.ClearResult() = - this.ResultMatrix.Dispose this.Processor - - member this.ReadMask(maskReader) = - maskHost <- this.ReadMatrix maskReader - - member this.ReadMatrices() = - let matrixReader, maskReader = this.InputMatrixReader - firstMatrixHost <- this.ReadMatrix matrixReader - secondMatrixHost <- this.ReadMatrix matrixReader - this.ReadMask(maskReader) - - member this.LoadMatricesToGPU () = - firstMatrix <- buildMatrix this.OclContext firstMatrixHost - secondMatrix <- buildMatrix this.OclContext secondMatrixHost - mask <- maskHost.ToDevice this.OclContext - - member this.ConvertSecondMatrixToCSC() = - secondMatrix <- this.FunCSR2CSC this.Processor HostInterop secondMatrix - - member this.ConvertSecondMatrixToCSR() = - secondMatrix <- this.FunCSC2CSR this.Processor HostInterop secondMatrix - - abstract member GlobalSetup : unit -> unit - - abstract member IterationCleanup : unit -> unit - - abstract member GlobalCleanup : unit -> unit - - abstract member Benchmark : unit -> unit - -type MxmBenchmarksMultiplicationOnly<'elem when 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - inherit MxmBenchmarks<'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup() = - this.ReadMatrices () - this.LoadMatricesToGPU () - this.ConvertSecondMatrixToCSC() - - [] - override this.IterationCleanup () = - this.ClearResult() - - [] - override this.GlobalCleanup () = - this.ClearInputMatrices() - - [] - override this.Benchmark () = - this.Mxm() - this.Processor.PostAndReply(Msg.MsgNotifyMe) - -type MxmBenchmarksWithTransposing<'elem when 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - inherit MxmBenchmarks<'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup () = - this.ReadMatrices () - this.LoadMatricesToGPU () - - [] - override this.GlobalCleanup () = - this.ClearInputMatrices() - - [] - override this.IterationCleanup () = - this.ClearResult() - this.ConvertSecondMatrixToCSR() - - [] - override this.Benchmark () = - this.ConvertSecondMatrixToCSC() - this.Mxm() - this.Processor.PostAndReply(Msg.MsgNotifyMe) - -module Operations = - let add = <@ fun x y -> Some (x + y) @> - - let addWithFilter = <@ fun x y -> - let res = x + y - if abs res < 1e-8f then None else Some res - @> - - let mult = <@ fun x y -> Some (x * y) @> - - let logicalOr = <@ fun x y -> - let mutable res = None - - match x, y with - | false, false -> res <- None - | _ -> res <- Some true - - res @> - - let logicalAnd = <@ fun x y -> - let mutable res = None - - match x, y with - | true, true -> res <- Some true - | _ -> res <- None - - res @> - -type MxmBenchmarks4Float32MultiplicationOnly() = - - inherit MxmBenchmarksMultiplicationOnly( - (Matrix.SpGeMM.masked Operations.add Operations.mult), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) - ) - - static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" - -type MxmBenchmarks4Float32WithTransposing() = - - inherit MxmBenchmarksWithTransposing( - (Matrix.SpGeMM.masked Operations.add Operations.mult), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) - ) - - static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" - -type MxmBenchmarks4BoolMultiplicationOnly() = - - inherit MxmBenchmarksMultiplicationOnly( - (Matrix.SpGeMM.masked Operations.logicalOr Operations.logicalAnd), - (fun _ -> true), - (fun _ -> true), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) - ) - - static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" - -type MxmBenchmarks4BoolWithTransposing() = - - inherit MxmBenchmarksWithTransposing( - (Matrix.SpGeMM.masked Operations.logicalOr Operations.logicalAnd), - (fun _ -> true), - (fun _ -> true), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) - ) - - static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" - -type MxmBenchmarks4Float32MultiplicationOnlyWithZerosFilter() = - - inherit MxmBenchmarksMultiplicationOnly( - (Matrix.SpGeMM.masked Operations.addWithFilter Operations.mult), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) - ) - - static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" - -type MxmBenchmarks4Float32WithTransposingWithZerosFilter() = - - inherit MxmBenchmarksWithTransposing( - (Matrix.SpGeMM.masked Operations.addWithFilter Operations.mult), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) - ) - - static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxv.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxv.fs deleted file mode 100644 index 62dade8a..00000000 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMxv.fs +++ /dev/null @@ -1,77 +0,0 @@ -namespace GraphBLAS.FSharp.Benchmarks - -open GraphBLAS.FSharp -open GraphBLAS.FSharp.Backend -open BenchmarkDotNet.Attributes -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Objects - -[)>] -type MxvBenchmarks() = - let rand = System.Random() - - let mutable matrix = Unchecked.defaultof> - let mutable vector = Unchecked.defaultof> - let semiring = Predefined.AddMult.float - - //TODO fix me - (*[] - member val OclContext = Unchecked.defaultof with get, set - member this.Context = - let (ClContext context) = this.OclContext - context - - [] - member val InputMatrixReader = Unchecked.defaultof with get, set - - [] - member this.BuildMatrix() = - let inputMatrix = this.InputMatrixReader.ReadMatrixReal(float) - - matrix <- - graphblas { - return! Matrix.switch CSR inputMatrix - >>= Matrix.synchronizeAndReturn - } - |> EvalGB.withClContext this.Context - |> EvalGB.runSync - - [] - member this.BuildVector() = - vector <- - graphblas { - return! - [ for i = 0 to matrix.ColumnCount - 1 do if rand.Next() % 2 = 0 then yield (i, 1.) ] - |> Vector.ofList matrix.ColumnCount - // >>= Vector.synchronizeAndReturn - } - |> EvalGB.withClContext this.Context - |> EvalGB.runSync - - [] - member this.Mxv() = - Matrix.mxv semiring matrix vector - |> EvalGB.withClContext this.Context - |> EvalGB.runSync - - [] - member this.ClearBuffers() = - this.Context.Provider.CloseAllBuffers() - - [] - member this.ClearContext() = - let (ClContext context) = this.OclContext - context.Provider.Dispose() - - static member AvaliableContextsProvider = Utils.avaliableContexts - - static member InputMatricesProvider = - "Common.txt" - |> Utils.getMatricesFilenames - |> Seq.map - (fun matrixFilename -> - match Path.GetExtension matrixFilename with - | ".mtx" -> MtxReader(Utils.getFullPathToMatrix "Common" matrixFilename) - | _ -> failwith "Unsupported matrix format" - ) -*) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksEWiseAdd.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksEWiseAdd.fs deleted file mode 100644 index 18aa2cdd..00000000 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksEWiseAdd.fs +++ /dev/null @@ -1,307 +0,0 @@ -namespace GraphBLAS.FSharp.Benchmarks - -open System.IO -open GraphBLAS.FSharp.Backend.Quotes -open GraphBLAS.FSharp.IO -open BenchmarkDotNet.Attributes -open BenchmarkDotNet.Configs -open BenchmarkDotNet.Columns -open Brahma.FSharp -open GraphBLAS.FSharp.Objects -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Matrix -open GraphBLAS.FSharp.Objects.Matrix -open GraphBLAS.FSharp.Benchmarks.MatrixExtensions -open GraphBLAS.FSharp.Backend.Objects.ClContext - -[] -[] -[] -[)>] -type EWiseAddBenchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - let mutable funToBenchmark = None - let mutable firstMatrix = Unchecked.defaultof<'matrixT> - let mutable secondMatrix = Unchecked.defaultof<'matrixT> - let mutable firstMatrixHost = Unchecked.defaultof<_> - let mutable secondMatrixHost = Unchecked.defaultof<_> - - member val ResultMatrix = Unchecked.defaultof<'matrixT> with get,set - - [] - member val OclContextInfo = Unchecked.defaultof with get, set - - [] - member val InputMatrixReader = Unchecked.defaultof with get, set - - member this.OclContext:ClContext = (fst this.OclContextInfo).ClContext - member this.WorkGroupSize = snd this.OclContextInfo - - member this.Processor = - let p = (fst this.OclContextInfo).Queue - p.Error.Add(fun e -> failwithf "%A" e) - p - - static member AvaliableContexts = Utils.avaliableContexts - - static member InputMatricesProviderBuilder pathToConfig = - let datasetFolder = "EWiseAdd" - pathToConfig - |> Utils.getMatricesFilenames - |> Seq.map - (fun matrixFilename -> - printfn "%A" matrixFilename - - match Path.GetExtension matrixFilename with - | ".mtx" -> - MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) - , MtxReader(Utils.getFullPathToMatrix datasetFolder ("squared_" + matrixFilename)) - | _ -> failwith "Unsupported matrix format") - - member this.FunToBenchmark = - match funToBenchmark with - | None -> - let x = buildFunToBenchmark this.OclContext this.WorkGroupSize - funToBenchmark <- Some x - x - | Some x -> x - - member this.ReadMatrix (reader:MtxReader) = - let converter = - match reader.Field with - | Pattern -> converterBool - | _ -> converter - - reader.ReadMatrix converter - - member this.EWiseAddition() = - this.ResultMatrix <- this.FunToBenchmark this.Processor HostInterop firstMatrix secondMatrix - - member this.ClearInputMatrices() = - (firstMatrix :> IDeviceMemObject).Dispose this.Processor - (secondMatrix :> IDeviceMemObject).Dispose this.Processor - - member this.ClearResult() = - (this.ResultMatrix :> IDeviceMemObject).Dispose this.Processor - - member this.ReadMatrices() = - let leftMatrixReader = fst this.InputMatrixReader - let rightMatrixReader = snd this.InputMatrixReader - firstMatrixHost <- this.ReadMatrix leftMatrixReader - secondMatrixHost <- this.ReadMatrix rightMatrixReader - - member this.LoadMatricesToGPU () = - firstMatrix <- buildMatrix this.OclContext firstMatrixHost - secondMatrix <- buildMatrix this.OclContext secondMatrixHost - - abstract member GlobalSetup : unit -> unit - - abstract member IterationCleanup : unit -> unit - - abstract member GlobalCleanup : unit -> unit - - abstract member Benchmark : unit -> unit - -type EWiseAddBenchmarksWithoutDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - inherit EWiseAddBenchmarks<'matrixT, 'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup() = - this.ReadMatrices () - this.LoadMatricesToGPU () - - [] - override this.IterationCleanup () = - this.ClearResult() - - [] - override this.GlobalCleanup () = - this.ClearInputMatrices() - - [] - override this.Benchmark () = - this.EWiseAddition() - this.Processor.PostAndReply(Msg.MsgNotifyMe) - -type EWiseAddBenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix, - resultToHost) = - - inherit EWiseAddBenchmarks<'matrixT, 'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup () = - this.ReadMatrices () - - [] - override this.GlobalCleanup () = () - - [] - override this.IterationCleanup () = - this.ClearInputMatrices() - this.ClearResult() - - [] - override this.Benchmark () = - this.LoadMatricesToGPU() - this.EWiseAddition() - this.Processor.PostAndReply Msg.MsgNotifyMe - let res = resultToHost this.ResultMatrix this.Processor - this.Processor.PostAndReply Msg.MsgNotifyMe - -module M = - let resultToHostCOO (resultMatrix: ClMatrix.COO<'a>) (processor :MailboxProcessor<_>) = - let cols = - let a = Array.zeroCreate resultMatrix.ColumnCount - processor.Post(Msg.CreateToHostMsg<_>(resultMatrix.Columns,a)) - a - let rows = - let a = Array.zeroCreate resultMatrix.RowCount - processor.Post(Msg.CreateToHostMsg(resultMatrix.Rows,a)) - a - let vals = - let a = Array.zeroCreate resultMatrix.Values.Length - processor.Post(Msg.CreateToHostMsg(resultMatrix.Values,a)) - a - { - RowCount = resultMatrix.RowCount - ColumnCount = resultMatrix.ColumnCount - Rows = rows - Columns = cols - Values = vals - } - - -type EWiseAddBenchmarks4Float32COOWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( - (fun context wgSize -> COO.Matrix.map2 context ArithmeticOperations.float32SumOption wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - -type EWiseAddBenchmarks4Float32COOWithDataTransfer() = - - inherit EWiseAddBenchmarksWithDataTransfer,float32>( - (fun context wgSize -> COO.Matrix.map2 context ArithmeticOperations.float32SumOption wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCOO, - M.resultToHostCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - - -type EWiseAddBenchmarks4BoolCOOWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( - (fun context wgSize -> COO.Matrix.map2 context ArithmeticOperations.boolSum wgSize), - (fun _ -> true), - (fun _ -> true), - Matrix.ToBackendCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCOO.txt" - - -type EWiseAddBenchmarks4Float32CSRWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( - (fun context wgSize -> CSR.Matrix.map2 context ArithmeticOperations.float32SumOption wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCSR - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32CSR.txt" - - -type EWiseAddBenchmarks4BoolCSRWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( - (fun context wgSize -> CSR.Matrix.map2 context ArithmeticOperations.boolSum wgSize), - (fun _ -> true), - (fun _ -> true), - Matrix.ToBackendCSR - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" - -// With AtLeastOne - -type EWiseAddAtLeastOneBenchmarks4BoolCOOWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( - (fun context wgSize -> COO.Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne wgSize), - (fun _ -> true), - (fun _ -> true), - Matrix.ToBackendCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" - -type EWiseAddAtLeastOneBenchmarks4BoolCSRWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,bool>( - (fun context wgSize -> CSR.Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne wgSize), - (fun _ -> true), - (fun _ -> true), - Matrix.ToBackendCSR - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" - -type EWiseAddAtLeastOneBenchmarks4Float32COOWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( - (fun context wgSize -> COO.Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCOO - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - -type EWiseAddAtLeastOneBenchmarks4Float32CSRWithoutDataTransfer() = - - inherit EWiseAddBenchmarksWithoutDataTransfer,float32>( - (fun context wgSize -> CSR.Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne wgSize), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.ToBackendCSR - ) - - static member InputMatricesProvider = - EWiseAddBenchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs new file mode 100644 index 00000000..da62a739 --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs @@ -0,0 +1,281 @@ +namespace GraphBLAS.FSharp.Benchmarks + +open System.IO +open GraphBLAS.FSharp.Backend.Quotes +open GraphBLAS.FSharp.IO +open BenchmarkDotNet.Attributes +open Brahma.FSharp +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Objects.MatrixExtensions +open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Backend.Matrix +open GraphBLAS.FSharp.Benchmarks + +[] +[] +[] +[)>] +type Map2Benchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix: Matrix.COO<_> -> Matrix<_>) = + + let mutable funToBenchmark = None + let mutable firstMatrix = Unchecked.defaultof> + let mutable secondMatrix = Unchecked.defaultof> + let mutable firstMatrixHost = Unchecked.defaultof<_> + let mutable secondMatrixHost = Unchecked.defaultof<_> + + member val ResultMatrix = Unchecked.defaultof> with get,set + + [] + member val OclContextInfo = Unchecked.defaultof with get, set + + [] + member val InputMatrixReader = Unchecked.defaultof with get, set + + member this.OclContext: ClContext = (fst this.OclContextInfo).ClContext + member this.WorkGroupSize = snd this.OclContextInfo + + member this.Processor = + let p = (fst this.OclContextInfo).Queue + p.Error.Add(fun e -> failwithf "%A" e) + p + + static member AvailableContexts = Utils.avaliableContexts + + static member InputMatricesProviderBuilder pathToConfig = + let datasetFolder = "EWiseAdd" + pathToConfig + |> Utils.getMatricesFilenames + |> Seq.map + (fun matrixFilename -> + printfn "%A" matrixFilename + + match Path.GetExtension matrixFilename with + | ".mtx" -> + MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) + , MtxReader(Utils.getFullPathToMatrix datasetFolder ("squared_" + matrixFilename)) + | _ -> failwith "Unsupported matrix format") + + member this.FunToBenchmark = + match funToBenchmark with + | None -> + let x = buildFunToBenchmark this.OclContext this.WorkGroupSize + funToBenchmark <- Some x + x + | Some x -> x + + member this.ReadMatrix (reader: MtxReader) = + let converter = + match reader.Field with + | Pattern -> converterBool + | _ -> converter + + reader.ReadMatrix converter + + member this.EWiseAddition() = + this.ResultMatrix <- this.FunToBenchmark this.Processor HostInterop firstMatrix secondMatrix + + member this.ClearInputMatrices() = + firstMatrix.Dispose this.Processor + secondMatrix.Dispose this.Processor + + member this.ClearResult() = + this.ResultMatrix.Dispose this.Processor + + member this.ReadMatrices() = + firstMatrixHost <- this.ReadMatrix <| fst this.InputMatrixReader + secondMatrixHost <- this.ReadMatrix <| snd this.InputMatrixReader + + member this.LoadMatricesToGPU () = + firstMatrix <- (buildMatrix firstMatrixHost).ToDevice this.OclContext + secondMatrix <- (buildMatrix secondMatrixHost).ToDevice this.OclContext + + abstract member GlobalSetup: unit -> unit + + abstract member Benchmark: unit -> unit + + abstract member IterationCleanup: unit -> unit + + abstract member GlobalCleanup: unit -> unit + +type Map2BenchmarksWithoutDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + inherit Map2Benchmarks<'matrixT, 'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup() = + this.ReadMatrices () + this.LoadMatricesToGPU () + this.Processor.PostAndReply(Msg.MsgNotifyMe) + + [] + override this.Benchmark () = + this.EWiseAddition() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + + [] + override this.IterationCleanup () = + this.ClearResult() + + [] + override this.GlobalCleanup () = + this.ClearInputMatrices() + +type Map2BenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix, + resultToHost) = + + inherit Map2Benchmarks<'matrixT, 'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup() = + this.ReadMatrices() + + [] + override this.GlobalCleanup() = () + + [] + override this.IterationCleanup() = + this.ClearInputMatrices() + this.ClearResult() + + [] + override this.Benchmark() = + this.LoadMatricesToGPU() + this.EWiseAddition() + this.Processor.PostAndReply Msg.MsgNotifyMe + resultToHost this.ResultMatrix this.Processor |> ignore + this.Processor.PostAndReply Msg.MsgNotifyMe + +type MatrixCOOMap2Float32WithoutTransferBenchmark() = + + inherit Map2BenchmarksWithoutDataTransfer,float32>( + (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.COO + ) + + static member InputMatricesProvider = + Map2Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + +type MatrixCOOMap2Float32WithTransferBenchmark() = + + inherit Map2BenchmarksWithDataTransfer,float32>( + (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.COO, + (fun matrix -> matrix.ToHost) + ) + + static member InputMatricesProvider = + Map2Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + + +type MatrixCOOMap2BoolWithoutTransferBenchmark() = + + inherit Map2BenchmarksWithoutDataTransfer,bool>( + (fun context -> Matrix.map2 context ArithmeticOperations.boolSumOption), + (fun _ -> true), + (fun _ -> true), + Matrix.COO + ) + + static member InputMatricesProvider = + Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCOO.txt" + + +type MatrixCSRMap2Float32WithoutTransferBenchmark() = + + inherit Map2BenchmarksWithoutDataTransfer,float32>( + (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + (fun matrix -> Matrix.CSR matrix.ToCSR) + ) + + static member InputMatricesProvider = + Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32CSR.txt" + + +type MatrixCSRMap2BoolWithoutTransferBenchmark() = + + inherit Map2BenchmarksWithoutDataTransfer,bool>( + (fun context -> Matrix.map2 context ArithmeticOperations.boolSumOption), + (fun _ -> true), + (fun _ -> true), + (fun matrix -> Matrix.CSR matrix.ToCSR) + ) + + static member InputMatricesProvider = + Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + +// AtLeastOne + +type MatrixCOOMap2AtLeastOne4BoolWithoutTransferBenchmark() = + + inherit Map2BenchmarksWithoutDataTransfer,bool>( + (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne), + (fun _ -> true), + (fun _ -> true), + Matrix.COO + ) + + static member InputMatricesProvider = + Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + +type MatrixCSRMap2AtLeastOne4BoolWithoutTransferBenchmark() = + + inherit Map2BenchmarksWithoutDataTransfer,bool>( + (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne), + (fun _ -> true), + (fun _ -> true), + (fun matrix -> Matrix.CSR matrix.ToCSR) + ) + + static member InputMatricesProvider = + Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + +type MatrixCOOMap2AtLeastOne4Float32WithoutTransferBenchmark() = + + inherit Map2BenchmarksWithoutDataTransfer,float32>( + (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.COO + ) + + static member InputMatricesProvider = + Map2Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + +type MatrixCSRMap2AtLeastOne4Float32CSRWithoutTransferBenchmark() = + + inherit Map2BenchmarksWithoutDataTransfer,float32>( + (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + (fun matrix -> Matrix.CSR matrix.ToCSR) + ) + + static member InputMatricesProvider = + Map2Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMathNET.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/MathNET.fs similarity index 88% rename from benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMathNET.fs rename to benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/MathNET.fs index a2d8a564..b0577154 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksMathNET.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/MathNET.fs @@ -1,4 +1,4 @@ -namespace GraphBLAS.FSharp.Benchmarks +namespace GraphBLAS.FSharp.Benchmarks.Matrix.Map2 open System.IO open GraphBLAS.FSharp.Objects @@ -7,12 +7,13 @@ open BenchmarkDotNet.Attributes open MathNet.Numerics.LinearAlgebra open MathNet.Numerics open Microsoft.FSharp.Core +open GraphBLAS.FSharp.Benchmarks [] [] [] -[)>] -type MathNETBenchmark<'elem when 'elem: struct and 'elem :> System.IEquatable<'elem> and 'elem :> System.IFormattable and 'elem :> System.ValueType and 'elem: (new : +[)>] +type MathNET<'elem when 'elem: struct and 'elem :> System.IEquatable<'elem> and 'elem :> System.IFormattable and 'elem :> System.ValueType and 'elem: (new : unit -> 'elem)>(converter: string -> 'elem, converterBool) = do Control.UseNativeMKL() @@ -35,8 +36,8 @@ type MathNETBenchmark<'elem when 'elem: struct and 'elem :> System.IEquatable<'e | Pattern -> converterBool | _ -> converter - let gbMatrix = reader.ReadMatrix converter - MathNETBenchmark<_>.COOMatrixToMathNETSparse gbMatrix + Matrix.COO (reader.ReadMatrix converter) + |> MathNET<_>.COOMatrixToMathNETSparse abstract member GlobalSetup : unit -> unit @@ -46,7 +47,7 @@ type MathNETBenchmark<'elem when 'elem: struct and 'elem :> System.IEquatable<'e type BinOpMathNETBenchmark<'elem when 'elem: struct and 'elem :> System.IEquatable<'elem> and 'elem :> System.IFormattable and 'elem :> System.ValueType and 'elem: (new : unit -> 'elem)>(funToBenchmark, converter: string -> 'elem, converterBool) = - inherit MathNETBenchmark<'elem>(converter, converterBool) + inherit MathNET<'elem>(converter, converterBool) let mutable firstMatrix = Unchecked.defaultof> let mutable secondMatrix = Unchecked.defaultof> diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksMxm.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs similarity index 78% rename from benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksMxm.fs rename to benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs index efbe86c9..133d1d6c 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/BenchmarksMxm.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs @@ -7,13 +7,14 @@ open Brahma.FSharp open GraphBLAS.FSharp.Objects open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Matrix -open GraphBLAS.FSharp.Benchmarks.MatrixExtensions open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Benchmarks +open GraphBLAS.FSharp.Backend [] [] [] -[)>] +[)>] type MxmBenchmarks<'elem when 'elem : struct>( buildFunToBenchmark, converter: string -> 'elem, @@ -88,7 +89,7 @@ type MxmBenchmarks<'elem when 'elem : struct>( x | Some x -> x - member this.ReadMatrix (reader:MtxReader) = + member this.ReadMatrix (reader: MtxReader) = let converter = match reader.Field with | Pattern -> converterBool @@ -108,7 +109,7 @@ type MxmBenchmarks<'elem when 'elem : struct>( this.ResultMatrix.Dispose this.Processor member this.ReadMask(maskReader) = - maskHost <- this.ReadMatrix maskReader + maskHost <- Matrix.COO <| this.ReadMatrix maskReader member this.ReadMatrices() = let matrixReader, maskReader = this.InputMatrixReader @@ -129,12 +130,12 @@ type MxmBenchmarks<'elem when 'elem : struct>( abstract member GlobalSetup : unit -> unit + abstract member Benchmark : unit -> unit + abstract member IterationCleanup : unit -> unit abstract member GlobalCleanup : unit -> unit - abstract member Benchmark : unit -> unit - type MxmBenchmarksMultiplicationOnly<'elem when 'elem : struct>( buildFunToBenchmark, converter: string -> 'elem, @@ -153,6 +154,11 @@ type MxmBenchmarksMultiplicationOnly<'elem when 'elem : struct>( this.LoadMatricesToGPU () this.ConvertSecondMatrixToCSC() + [] + override this.Benchmark () = + this.Mxm() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + [] override this.IterationCleanup () = this.ClearResult() @@ -161,11 +167,6 @@ type MxmBenchmarksMultiplicationOnly<'elem when 'elem : struct>( override this.GlobalCleanup () = this.ClearInputMatrices() - [] - override this.Benchmark () = - this.Mxm() - this.Processor.PostAndReply(Msg.MsgNotifyMe) - type MxmBenchmarksWithTransposing<'elem when 'elem : struct>( buildFunToBenchmark, converter: string -> 'elem, @@ -179,120 +180,93 @@ type MxmBenchmarksWithTransposing<'elem when 'elem : struct>( buildMatrix) [] - override this.GlobalSetup () = - this.ReadMatrices () + override this.GlobalSetup() = + this.ReadMatrices() this.LoadMatricesToGPU () - [] - override this.GlobalCleanup () = - this.ClearInputMatrices() - - [] - override this.IterationCleanup () = - this.ClearResult() - this.ConvertSecondMatrixToCSR() - [] - override this.Benchmark () = + override this.Benchmark() = this.ConvertSecondMatrixToCSC() this.Mxm() this.Processor.PostAndReply(Msg.MsgNotifyMe) -module Operations = - let add = <@ fun x y -> Some (x + y) @> - - let addWithFilter = <@ fun x y -> - let res = x + y - if abs res < 1e-8f then None else Some res - @> - - let mult = <@ fun x y -> Some (x * y) @> - let logicalOr = <@ fun x y -> - let mutable res = None - - match x, y with - | false, false -> res <- None - | _ -> res <- Some true - - res @> - - let logicalAnd = <@ fun x y -> - let mutable res = None - - match x, y with - | true, true -> res <- Some true - | _ -> res <- None + [] + override this.IterationCleanup() = + this.ClearResult() + this.ConvertSecondMatrixToCSR() - res @> + [] + override this.GlobalCleanup() = + this.ClearInputMatrices() -type MxmBenchmarks4Float32MultiplicationOnly() = +type Mxm4Float32MultiplicationOnlyBenchmark() = inherit MxmBenchmarksMultiplicationOnly( - (Matrix.SpGeMM.masked Operations.add Operations.mult), + Matrix.SpGeMM.masked (Operations.add ()) (Operations.mult ()), float32, (fun _ -> Utils.nextSingle (System.Random())), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) ) static member InputMatrixProvider = MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" -type MxmBenchmarks4Float32WithTransposing() = +type Mxm4Float32WithTransposingBenchmark() = inherit MxmBenchmarksWithTransposing( - (Matrix.SpGeMM.masked Operations.add Operations.mult), + Matrix.SpGeMM.masked (Operations.add ()) (Operations.mult ()), float32, (fun _ -> Utils.nextSingle (System.Random())), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) ) static member InputMatrixProvider = MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" -type MxmBenchmarks4BoolMultiplicationOnly() = +type Mxm4BoolMultiplicationOnlyBenchmark() = inherit MxmBenchmarksMultiplicationOnly( (Matrix.SpGeMM.masked Operations.logicalOr Operations.logicalAnd), (fun _ -> true), (fun _ -> true), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) ) static member InputMatrixProvider = MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" -type MxmBenchmarks4BoolWithTransposing() = +type Mxm4BoolWithTransposingBenchmark() = inherit MxmBenchmarksWithTransposing( (Matrix.SpGeMM.masked Operations.logicalOr Operations.logicalAnd), (fun _ -> true), (fun _ -> true), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) ) static member InputMatrixProvider = MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" -type MxmBenchmarks4Float32MultiplicationOnlyWithZerosFilter() = +type Mxm4Float32MultiplicationOnlyWithZerosFilterBenchmark() = inherit MxmBenchmarksMultiplicationOnly( - (Matrix.SpGeMM.masked Operations.addWithFilter Operations.mult), + (Matrix.SpGeMM.masked Operations.addWithFilter (Operations.mult ())), float32, (fun _ -> Utils.nextSingle (System.Random())), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) ) static member InputMatrixProvider = MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" -type MxmBenchmarks4Float32WithTransposingWithZerosFilter() = +type Mxm4Float32WithTransposingWithZerosFilterBenchmark() = inherit MxmBenchmarksWithTransposing( - (Matrix.SpGeMM.masked Operations.addWithFilter Operations.mult), + Matrix.SpGeMM.masked Operations.addWithFilter (Operations.mult ()), float32, (fun _ -> Utils.nextSingle (System.Random())), - (fun context matrix -> ClMatrix.CSR (Matrix.ToBackendCSR context matrix)) + (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) ) static member InputMatrixProvider = diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/MatrixExtensions.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/MatrixExtensions.fs deleted file mode 100644 index ed84bcee..00000000 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/MatrixExtensions.fs +++ /dev/null @@ -1,91 +0,0 @@ -namespace GraphBLAS.FSharp.Benchmarks - -open GraphBLAS.FSharp.Objects -open Brahma.FSharp -open GraphBLAS.FSharp.Backend.Objects.ClMatrix - -module MatrixExtensions = - type Matrix<'a when 'a : struct> with - static member ToBackendCOO (context: ClContext) matrix = - match matrix with - | Matrix.COO m -> - let rows = - context.CreateClArray( - m.Rows, - hostAccessMode = HostAccessMode.ReadOnly, - deviceAccessMode = DeviceAccessMode.ReadOnly, - allocationMode = AllocationMode.CopyHostPtr - ) - - let cols = - context.CreateClArray( - m.Columns, - hostAccessMode = HostAccessMode.ReadOnly, - deviceAccessMode = DeviceAccessMode.ReadOnly, - allocationMode = AllocationMode.CopyHostPtr - ) - - let vals = - context.CreateClArray( - m.Values, - hostAccessMode = HostAccessMode.ReadOnly, - deviceAccessMode = DeviceAccessMode.ReadOnly, - allocationMode = AllocationMode.CopyHostPtr - ) - - { Context = context - RowCount = m.RowCount - ColumnCount = m.ColumnCount - Rows = rows - Columns = cols - Values = vals } - - | _ -> failwith "Unsupported matrix format: %A" - - static member ToBackendCSR (context: ClContext) matrix = - let rowIndices2rowPointers (rowIndices: int []) rowCount = - let nnzPerRow = Array.zeroCreate rowCount - let rowPointers = Array.zeroCreate rowCount - - Array.iter (fun rowIndex -> nnzPerRow.[rowIndex] <- nnzPerRow.[rowIndex] + 1) rowIndices - - for i in 1 .. rowCount - 1 do - rowPointers.[i] <- rowPointers.[i - 1] + nnzPerRow.[i - 1] - - rowPointers - - match matrix with - | Matrix.COO m -> - let rowPointers = - context.CreateClArray( - rowIndices2rowPointers m.Rows m.RowCount, - hostAccessMode = HostAccessMode.ReadOnly, - deviceAccessMode = DeviceAccessMode.ReadOnly, - allocationMode = AllocationMode.CopyHostPtr - ) - - let cols = - context.CreateClArray( - m.Columns, - hostAccessMode = HostAccessMode.ReadOnly, - deviceAccessMode = DeviceAccessMode.ReadOnly, - allocationMode = AllocationMode.CopyHostPtr - ) - - let vals = - context.CreateClArray( - m.Values, - hostAccessMode = HostAccessMode.ReadOnly, - deviceAccessMode = DeviceAccessMode.ReadOnly, - allocationMode = AllocationMode.CopyHostPtr - ) - - { Context = context - RowCount = m.RowCount - ColumnCount = m.ColumnCount - RowPointers = rowPointers - Columns = cols - Values = vals } - - | _ -> failwith "Unsupported matrix format: %A" - diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/BenchmarksMxv.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/BenchmarksMxv.fs deleted file mode 100644 index 62dade8a..00000000 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/BenchmarksMxv.fs +++ /dev/null @@ -1,77 +0,0 @@ -namespace GraphBLAS.FSharp.Benchmarks - -open GraphBLAS.FSharp -open GraphBLAS.FSharp.Backend -open BenchmarkDotNet.Attributes -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Objects - -[)>] -type MxvBenchmarks() = - let rand = System.Random() - - let mutable matrix = Unchecked.defaultof> - let mutable vector = Unchecked.defaultof> - let semiring = Predefined.AddMult.float - - //TODO fix me - (*[] - member val OclContext = Unchecked.defaultof with get, set - member this.Context = - let (ClContext context) = this.OclContext - context - - [] - member val InputMatrixReader = Unchecked.defaultof with get, set - - [] - member this.BuildMatrix() = - let inputMatrix = this.InputMatrixReader.ReadMatrixReal(float) - - matrix <- - graphblas { - return! Matrix.switch CSR inputMatrix - >>= Matrix.synchronizeAndReturn - } - |> EvalGB.withClContext this.Context - |> EvalGB.runSync - - [] - member this.BuildVector() = - vector <- - graphblas { - return! - [ for i = 0 to matrix.ColumnCount - 1 do if rand.Next() % 2 = 0 then yield (i, 1.) ] - |> Vector.ofList matrix.ColumnCount - // >>= Vector.synchronizeAndReturn - } - |> EvalGB.withClContext this.Context - |> EvalGB.runSync - - [] - member this.Mxv() = - Matrix.mxv semiring matrix vector - |> EvalGB.withClContext this.Context - |> EvalGB.runSync - - [] - member this.ClearBuffers() = - this.Context.Provider.CloseAllBuffers() - - [] - member this.ClearContext() = - let (ClContext context) = this.OclContext - context.Provider.Dispose() - - static member AvaliableContextsProvider = Utils.avaliableContexts - - static member InputMatricesProvider = - "Common.txt" - |> Utils.getMatricesFilenames - |> Seq.map - (fun matrixFilename -> - match Path.GetExtension matrixFilename with - | ".mtx" -> MtxReader(Utils.getFullPathToMatrix "Common" matrixFilename) - | _ -> failwith "Unsupported matrix format" - ) -*) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs index 97d75077..0ca9069a 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs @@ -1,33 +1,24 @@ namespace GraphBLAS.FSharp.Benchmarks -open Expecto +namespace GraphBLAS.FSharp.Benchmarks.Synthetic + open FsCheck open BenchmarkDotNet.Attributes -open BenchmarkDotNet.Configs -open BenchmarkDotNet.Columns + open Brahma.FSharp open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Quotes +open GraphBLAS.FSharp.Benchmarks open GraphBLAS.FSharp.Tests open GraphBLAS.FSharp.Objects open GraphBLAS.FSharp.Objects.ClVectorExtensions open GraphBLAS.FSharp.Backend.Vector open GraphBLAS.FSharp.Backend.Objects.ClContext -type VectorConfig() = - inherit ManualConfig() - - do - base.AddColumn( - StatisticColumn.Min, - StatisticColumn.Max - ) - |> ignore - [] [] [] -[)>] +[)>] type VectorEWiseBenchmarks<'elem when 'elem : struct>( buildFunToBenchmark, generator: Gen * Vector<'elem>>) = @@ -45,7 +36,7 @@ type VectorEWiseBenchmarks<'elem when 'elem : struct>( [] member val OclContextInfo = Unchecked.defaultof with get, set - [] + [] member val Size = Unchecked.defaultof with get, set member this.OclContext: ClContext = (fst this.OclContextInfo).ClContext @@ -66,9 +57,15 @@ type VectorEWiseBenchmarks<'elem when 'elem : struct>( x | Some x -> x - member this.EWiseAddition() = + member this.Map2() = + try + this.ResultVector <- this.FunToBenchmark this.Processor HostInterop firstVector secondVector + with + | ex when ex.Message = "InvalidBufferSize" -> () + | ex -> raise ex + member this.ClearInputVectors()= firstVector.Dispose this.Processor secondVector.Dispose this.Processor @@ -83,15 +80,15 @@ type VectorEWiseBenchmarks<'elem when 'elem : struct>( firstVector <- (fst this.HostVectorPair).ToDevice this.OclContext secondVector <- (snd this.HostVectorPair).ToDevice this.OclContext - abstract member GlobalSetup : unit -> unit + abstract member GlobalSetup: unit -> unit abstract member IterationSetup: unit -> unit - abstract member Benchmark : unit -> unit + abstract member Benchmark: unit -> unit - abstract member IterationCleanup : unit -> unit + abstract member IterationCleanup: unit -> unit - abstract member GlobalCleanup : unit -> unit + abstract member GlobalCleanup: unit -> unit type VectorEWiseBenchmarksWithoutDataTransfer<'elem when 'elem : struct>( @@ -107,16 +104,17 @@ type VectorEWiseBenchmarksWithoutDataTransfer<'elem when 'elem : struct>( [] override this.IterationSetup() = - this.CreateVectors () - this.LoadVectorsToGPU () + this.CreateVectors() + this.LoadVectorsToGPU() + this.Processor.PostAndReply Msg.MsgNotifyMe [] - override this.Benchmark () = - this.EWiseAddition() - this.Processor.PostAndReply(Msg.MsgNotifyMe) + override this.Benchmark() = + this.Map2() + this.Processor.PostAndReply Msg.MsgNotifyMe [] - override this.IterationCleanup () = + override this.IterationCleanup() = this.ClearResult() this.ClearInputVectors() @@ -141,8 +139,7 @@ type VectorEWiseBenchmarksWithDataTransfer<'elem when 'elem : struct>( [] override this.Benchmark () = this.LoadVectorsToGPU() - this.EWiseAddition() - this.Processor.PostAndReply Msg.MsgNotifyMe + this.Map2() this.ResultVector.ToHost this.Processor |> ignore this.Processor.PostAndReply Msg.MsgNotifyMe @@ -155,56 +152,52 @@ type VectorEWiseBenchmarksWithDataTransfer<'elem when 'elem : struct>( override this.GlobalCleanup() = () /// Without data transfer -/// AtLeastOne -type VectorEWiseBenchmarks4FloatSparseWithoutDataTransfer() = +type VectorSparseMap2FloatWithoutTransferBenchmark() = inherit VectorEWiseBenchmarksWithoutDataTransfer( (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), VectorGenerator.floatPair Sparse) -type VectorEWiseBenchmarks4Int32SparseWithoutDataTransfer() = +type VectorSparseMap2Int32WithoutTransferBenchmark() = inherit VectorEWiseBenchmarksWithoutDataTransfer( (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), VectorGenerator.intPair Sparse) /// General - -type VectorEWiseGeneralBenchmarks4FloatSparseWithoutDataTransfer() = +type VectorSparseMap2GeneralFloatWithoutTransferBenchmark() = inherit VectorEWiseBenchmarksWithoutDataTransfer( (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), VectorGenerator.floatPair Sparse) -type VectorEWiseGeneralBenchmarks4Int32SparseWithoutDataTransfer() = +type VectorSparseMap2GeneralInt32WithoutTransferBenchmark() = inherit VectorEWiseBenchmarksWithoutDataTransfer( (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), VectorGenerator.intPair Sparse) /// With data transfer - -type VectorEWiseBenchmarks4FloatSparseWithDataTransfer() = +type VectorSparseMap2FloatWithTransferBenchmark() = inherit VectorEWiseBenchmarksWithDataTransfer( (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), VectorGenerator.floatPair Sparse) -type VectorEWiseBenchmarks4Int32SparseWithDataTransfer() = +type VectorSparseMap2Int32WithTransferBenchmark() = inherit VectorEWiseBenchmarksWithDataTransfer( (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), VectorGenerator.intPair Sparse) -/// General with data transfer - -type VectorEWiseGeneralBenchmarks4FloatSparseWithDataTransfer() = +/// Map2 with data transfer +type VectorMap2GeneralFloatSparseWithTransferBenchmark() = inherit VectorEWiseBenchmarksWithDataTransfer( (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), VectorGenerator.floatPair Sparse) -type VectorEWiseGeneralBenchmarks4Int32SparseWithDataTransfer() = +type VectorMap2GeneralInt32SparseWithTransferBenchmark() = inherit VectorEWiseBenchmarksWithDataTransfer( (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/VectorEWiseAddGen.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/VectorEWiseAddGen.fs deleted file mode 100644 index 97d75077..00000000 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/VectorEWiseAddGen.fs +++ /dev/null @@ -1,211 +0,0 @@ -namespace GraphBLAS.FSharp.Benchmarks - -open Expecto -open FsCheck -open BenchmarkDotNet.Attributes -open BenchmarkDotNet.Configs -open BenchmarkDotNet.Columns -open Brahma.FSharp -open GraphBLAS.FSharp.Backend.Objects -open GraphBLAS.FSharp.Backend.Quotes -open GraphBLAS.FSharp.Tests -open GraphBLAS.FSharp.Objects -open GraphBLAS.FSharp.Objects.ClVectorExtensions -open GraphBLAS.FSharp.Backend.Vector -open GraphBLAS.FSharp.Backend.Objects.ClContext - -type VectorConfig() = - inherit ManualConfig() - - do - base.AddColumn( - StatisticColumn.Min, - StatisticColumn.Max - ) - |> ignore - -[] -[] -[] -[)>] -type VectorEWiseBenchmarks<'elem when 'elem : struct>( - buildFunToBenchmark, - generator: Gen * Vector<'elem>>) = - - let mutable funToBenchmark = None - - let mutable firstVector = Unchecked.defaultof> - - let mutable secondVector = Unchecked.defaultof> - - member val HostVectorPair = Unchecked.defaultof * Vector<'elem>> with get, set - - member val ResultVector = Unchecked.defaultof> with get,set - - [] - member val OclContextInfo = Unchecked.defaultof with get, set - - [] - member val Size = Unchecked.defaultof with get, set - - member this.OclContext: ClContext = (fst this.OclContextInfo).ClContext - member this.WorkGroupSize = snd this.OclContextInfo - - member this.Processor = - let p = (fst this.OclContextInfo).Queue - p.Error.Add(fun e -> failwithf "%A" e) - p - - static member AvaliableContexts = Utils.avaliableContexts - - member this.FunToBenchmark = - match funToBenchmark with - | None -> - let x = buildFunToBenchmark this.OclContext this.WorkGroupSize - funToBenchmark <- Some x - x - | Some x -> x - - member this.EWiseAddition() = - this.ResultVector <- this.FunToBenchmark this.Processor HostInterop firstVector secondVector - - member this.ClearInputVectors()= - firstVector.Dispose this.Processor - secondVector.Dispose this.Processor - - member this.ClearResult() = - this.ResultVector.Dispose this.Processor - - member this.CreateVectors() = - this.HostVectorPair <- List.last (Gen.sample this.Size 1 generator) - - member this.LoadVectorsToGPU() = - firstVector <- (fst this.HostVectorPair).ToDevice this.OclContext - secondVector <- (snd this.HostVectorPair).ToDevice this.OclContext - - abstract member GlobalSetup : unit -> unit - - abstract member IterationSetup: unit -> unit - - abstract member Benchmark : unit -> unit - - abstract member IterationCleanup : unit -> unit - - abstract member GlobalCleanup : unit -> unit - - -type VectorEWiseBenchmarksWithoutDataTransfer<'elem when 'elem : struct>( - buildFunToBenchmark, - generator) = - - inherit VectorEWiseBenchmarks<'elem>( - buildFunToBenchmark, - generator) - - [] - override this.GlobalSetup() = () - - [] - override this.IterationSetup() = - this.CreateVectors () - this.LoadVectorsToGPU () - - [] - override this.Benchmark () = - this.EWiseAddition() - this.Processor.PostAndReply(Msg.MsgNotifyMe) - - [] - override this.IterationCleanup () = - this.ClearResult() - this.ClearInputVectors() - - [] - override this.GlobalCleanup() = () - -type VectorEWiseBenchmarksWithDataTransfer<'elem when 'elem : struct>( - buildFunToBenchmark, - generator) = - - inherit VectorEWiseBenchmarks<'elem>( - buildFunToBenchmark, - generator) - - [] - override this.GlobalSetup() = () - - [] - override this.IterationSetup() = - this.CreateVectors() - - [] - override this.Benchmark () = - this.LoadVectorsToGPU() - this.EWiseAddition() - this.Processor.PostAndReply Msg.MsgNotifyMe - this.ResultVector.ToHost this.Processor |> ignore - this.Processor.PostAndReply Msg.MsgNotifyMe - - [] - override this.IterationCleanup () = - this.ClearInputVectors() - this.ClearResult() - - [] - override this.GlobalCleanup() = () - -/// Without data transfer -/// AtLeastOne -type VectorEWiseBenchmarks4FloatSparseWithoutDataTransfer() = - - inherit VectorEWiseBenchmarksWithoutDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), - VectorGenerator.floatPair Sparse) - -type VectorEWiseBenchmarks4Int32SparseWithoutDataTransfer() = - - inherit VectorEWiseBenchmarksWithoutDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), - VectorGenerator.intPair Sparse) - -/// General - -type VectorEWiseGeneralBenchmarks4FloatSparseWithoutDataTransfer() = - - inherit VectorEWiseBenchmarksWithoutDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), - VectorGenerator.floatPair Sparse) - -type VectorEWiseGeneralBenchmarks4Int32SparseWithoutDataTransfer() = - - inherit VectorEWiseBenchmarksWithoutDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), - VectorGenerator.intPair Sparse) - -/// With data transfer - -type VectorEWiseBenchmarks4FloatSparseWithDataTransfer() = - - inherit VectorEWiseBenchmarksWithDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), - VectorGenerator.floatPair Sparse) - -type VectorEWiseBenchmarks4Int32SparseWithDataTransfer() = - - inherit VectorEWiseBenchmarksWithDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), - VectorGenerator.intPair Sparse) - -/// General with data transfer - -type VectorEWiseGeneralBenchmarks4FloatSparseWithDataTransfer() = - - inherit VectorEWiseBenchmarksWithDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), - VectorGenerator.floatPair Sparse) - -type VectorEWiseGeneralBenchmarks4Int32SparseWithDataTransfer() = - - inherit VectorEWiseBenchmarksWithDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), - VectorGenerator.intPair Sparse) From b25bc9722e6df32cc8fe72cb05870842d2fa956b Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sat, 22 Apr 2023 11:20:33 +0300 Subject: [PATCH 26/44] refactor: benchmarks --- .../Algorithms/BFS.fs | 14 +- .../GraphBLAS-sharp.Benchmarks/Columns.fs | 41 ++++ .../GraphBLAS-sharp.Benchmarks/Configs.fs | 77 ++++++ .../GraphBLAS-sharp.Benchmarks.fsproj | 14 +- .../GraphBLAS-sharp.Benchmarks/Helpers.fs | 224 +++++++----------- .../Matrix/Map2/Map2.fs | 26 +- .../Matrix/SpGeMM/Masked.fs | 22 +- .../GraphBLAS-sharp.Benchmarks/Program.fs | 2 +- .../GraphBLAS-sharp.Benchmarks/Vector/Map2.fs | 16 +- .../Quotes/Arithmetic.fs | 2 +- src/GraphBLAS-sharp/IO/MtxReader.fs | 13 +- src/GraphBLAS-sharp/Objects/Matrix.fs | 6 +- tests/GraphBLAS-sharp.Tests/Generators.fs | 32 --- tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs | 2 +- tests/GraphBLAS-sharp.Tests/Vector/Map2.fs | 2 +- tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs | 2 +- 16 files changed, 265 insertions(+), 230 deletions(-) create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Columns.fs create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Configs.fs diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs index 1b4c06c3..365db3df 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs @@ -1,4 +1,4 @@ -namespace GraphBLAS.FSharp.Benchmarks +namespace GraphBLAS.FSharp.Benchmarks.Algorithms open System.IO open BenchmarkDotNet.Attributes @@ -15,8 +15,8 @@ open GraphBLAS.FSharp.Backend.Objects [] [] [] -[)>] -type BFSBenchmarks<'elem when 'elem : struct>( +[)>] +type BFS<'elem when 'elem : struct>( buildFunToBenchmark, converter: string -> 'elem, binaryConverter, @@ -98,7 +98,7 @@ type BFSBenchmarksWithoutDataTransfer<'elem when 'elem : struct>( boolConverter, vertex) = - inherit BFSBenchmarks<'elem>( + inherit BFS<'elem>( buildFunToBenchmark, converter, boolConverter, @@ -128,7 +128,7 @@ type BFSBenchmarksWithTransfer<'elem when 'elem : struct>( boolConverter, vertex) = - inherit BFSBenchmarks<'elem>( + inherit BFS<'elem>( buildFunToBenchmark, converter, boolConverter, @@ -163,7 +163,7 @@ type BFSIntWithoutTransferBenchmark() = 0) static member InputMatrixProvider = - BFSBenchmarks<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" + BFS<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" type BFSIntWithTransferBenchmark() = @@ -174,5 +174,5 @@ type BFSIntWithTransferBenchmark() = 0) static member InputMatrixProvider = - BFSBenchmarks<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" + BFS<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Columns.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Columns.fs new file mode 100644 index 00000000..2851fac4 --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Columns.fs @@ -0,0 +1,41 @@ +namespace GraphBLAS.FSharp.Benchmarks.Columns + +open BenchmarkDotNet.Columns +open BenchmarkDotNet.Reports +open BenchmarkDotNet.Running +open GraphBLAS.FSharp.IO + +type CommonColumn<'a>(benchmarkCaseConvert, columnName: string, getShape: 'a -> 'b) = + interface IColumn with + member this.AlwaysShow = true + member this.Category = ColumnCategory.Params + member this.ColumnName = columnName + + member this.GetValue(_: Summary, benchmarkCase: BenchmarkCase) = + benchmarkCaseConvert benchmarkCase + |> getShape + |> sprintf "%A" + + member this.GetValue(summary: Summary, benchmarkCase: BenchmarkCase, _: SummaryStyle) = + (this :> IColumn).GetValue(summary, benchmarkCase) + + member this.Id = sprintf $"%s{columnName}" + + member this.IsAvailable(_: Summary) = true + member this.IsDefault(_: Summary, _: BenchmarkCase) = false + member this.IsNumeric = true + member this.Legend = sprintf $"%s{columnName}" + member this.PriorityInCategory = 1 + member this.UnitType = UnitType.Size + +type MatrixColumn(name, getShape) = + inherit CommonColumn( + (fun benchmarkCase -> benchmarkCase.Parameters.["InputMatrixReader"] :?> MtxReader), + name, + getShape) + +type Matrix2Column(name, getShape) = + inherit CommonColumn( + (fun benchmarkCase -> benchmarkCase.Parameters.["InputMatrixReader"] :?> MtxReader * MtxReader), + name, + getShape) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Configs.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs.fs new file mode 100644 index 00000000..0d1c51d0 --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs.fs @@ -0,0 +1,77 @@ +module GraphBLAS.FSharp.Benchmarks.Configs + +open BenchmarkDotNet.Columns +open BenchmarkDotNet.Toolchains.InProcess.Emit +open GraphBLAS.FSharp.IO +open BenchmarkDotNet.Configs +open BenchmarkDotNet.Jobs +open GraphBLAS.FSharp.Benchmarks.Columns + +type Matrix2() = + inherit ManualConfig() + + do + base.AddColumn( + Matrix2Column("RowCount", (fun (matrix,_) -> matrix.ReadMatrixShape().RowCount)) :> IColumn, + Matrix2Column("ColumnCount", (fun (matrix,_) -> matrix.ReadMatrixShape().ColumnCount)) :> IColumn, + Matrix2Column( + "NNZ", + fun (matrix,_) -> + match matrix.Format with + | Coordinate -> matrix.ReadMatrixShape().Nnz + | Array -> 0 + ) + :> IColumn, + Matrix2Column( + "SqrNNZ", + fun (_,matrix) -> + match matrix.Format with + | Coordinate -> matrix.ReadMatrixShape().Nnz + | Array -> 0 + ) + :> IColumn, + StatisticColumn.Min, + StatisticColumn.Max + ) + |> ignore + +type Matrix() = + inherit ManualConfig() + + do + base.AddColumn( + MatrixColumn("RowCount", (fun matrix -> matrix.ReadMatrixShape().RowCount)) :> IColumn, + MatrixColumn("ColumnCount", (fun matrix -> matrix.ReadMatrixShape().ColumnCount)) :> IColumn, + MatrixColumn( + "NNZ", + fun matrix -> + match matrix.Format with + | Coordinate -> matrix.ReadMatrixShape().Nnz + | Array -> 0 + ) + :> IColumn, + StatisticColumn.Min, + StatisticColumn.Max + ) + |> ignore + + base.AddJob( + Job + .Dry + .WithToolchain(InProcessEmitToolchain.Instance) + .WithWarmupCount(3) + .WithIterationCount(10) + .WithInvocationCount(3) + ) + |> ignore + +type MinMaxMean() = + inherit ManualConfig() + + do + base.AddColumn( + StatisticColumn.Min, + StatisticColumn.Max, + StatisticColumn.Mean + ) + |> ignore diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj b/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj index 689d84c0..e3a8d920 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj @@ -16,15 +16,15 @@ - - - - - + + - - + + + + + diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs index 734d9b15..4183e1d1 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs @@ -1,135 +1,19 @@ namespace rec GraphBLAS.FSharp.Benchmarks -open BenchmarkDotNet.Columns -open BenchmarkDotNet.Reports -open BenchmarkDotNet.Running +namespace GraphBLAS.FSharp.Benchmarks + open Brahma.FSharp open Brahma.FSharp.OpenCL.Translator +open Brahma.FSharp.OpenCL.Translator.QuotationTransformers +open GraphBLAS.FSharp.Backend.Objects open OpenCL.Net -open GraphBLAS.FSharp.IO open System.IO open System.Text.RegularExpressions -open BenchmarkDotNet.Configs -open BenchmarkDotNet.Jobs open GraphBLAS.FSharp.Tests open FsCheck open Expecto open GraphBLAS.FSharp.Test -type CommonConfig() = - inherit ManualConfig() - - do - base.AddColumn( - MatrixShapeColumn("RowCount", (fun (mtxReader, _) -> mtxReader.ReadMatrixShape().RowCount)) :> IColumn, - MatrixShapeColumn("ColumnCount", (fun (mtxReader, _) -> mtxReader.ReadMatrixShape().ColumnCount)) :> IColumn, - MatrixShapeColumn("NNZ", (fun (mtxReader, _) -> mtxReader.ReadMatrixShape().Nnz)) :> IColumn, - MatrixShapeColumn("SqrNNZ", (fun (_, mtxReader) -> mtxReader.ReadMatrixShape().Nnz)) :> IColumn, - TEPSColumn(fun (parameters: obj) -> parameters :?> MtxReader * MtxReader |> fst) :> IColumn, - StatisticColumn.Min, - StatisticColumn.Max - ) - |> ignore - - base.AddJob( - Job - .Dry - .WithWarmupCount(3) - .WithIterationCount(10) - .WithInvocationCount(3) - ) - |> ignore - -type AlgorithmConfig() = - inherit ManualConfig() - - do - base.AddColumn( - MatrixShapeColumn("RowCount", (fun (mtxReader) -> mtxReader.ReadMatrixShape().RowCount)) :> IColumn, - MatrixShapeColumn("ColumnCount", (fun (mtxReader) -> mtxReader.ReadMatrixShape().ColumnCount)) :> IColumn, - MatrixShapeColumn("NNZ", (fun (mtxReader) -> mtxReader.ReadMatrixShape().Nnz)) :> IColumn, - TEPSColumn(fun (parameters: obj) -> parameters :?> MtxReader) :> IColumn, - StatisticColumn.Min, - StatisticColumn.Max - ) - |> ignore - - base.AddJob( - Job - .Dry - .WithWarmupCount(3) - .WithIterationCount(10) - .WithInvocationCount(3) - ) - |> ignore - -type MatrixShapeColumn<'shape>(columnName: string, getShape: 'shape -> int) = - interface IColumn with - member this.AlwaysShow: bool = true - member this.Category: ColumnCategory = ColumnCategory.Params - member this.ColumnName: string = columnName - - member this.GetValue(summary: Summary, benchmarkCase: BenchmarkCase) : string = - let inputMatrix = - benchmarkCase.Parameters.["InputMatrixReader"] :?> 'shape - - sprintf "%i" <| getShape inputMatrix - - member this.GetValue(summary: Summary, benchmarkCase: BenchmarkCase, style: SummaryStyle) : string = - (this :> IColumn).GetValue(summary, benchmarkCase) - - member this.Id: string = - sprintf "%s.%s" "MatrixShapeColumn" columnName - - member this.IsAvailable(summary: Summary) : bool = true - member this.IsDefault(summary: Summary, benchmarkCase: BenchmarkCase) : bool = false - member this.IsNumeric: bool = true - member this.Legend: string = sprintf "%s of input matrix" columnName - member this.PriorityInCategory: int = 1 - member this.UnitType: UnitType = UnitType.Size - -type TEPSColumn(getMtxReader: obj -> MtxReader) = - interface IColumn with - member this.AlwaysShow: bool = true - member this.Category: ColumnCategory = ColumnCategory.Statistics - member this.ColumnName: string = "TEPS" - - member this.GetValue(summary: Summary, benchmarkCase: BenchmarkCase) : string = - let inputMatrixReader = getMtxReader benchmarkCase.Parameters.["InputMatrixReader"] - - let matrixShape = inputMatrixReader.ReadMatrixShape() - - let (nrows, ncols) = - matrixShape.RowCount, matrixShape.ColumnCount - - let (vertices, edges) = - match inputMatrixReader.Format with - | Coordinate -> - if nrows = ncols then - (nrows, matrixShape.Nnz) - else - (ncols, nrows) - | _ -> failwith "Unsupported" - - if isNull summary.[benchmarkCase].ResultStatistics then - "NA" - else - let meanTime = - summary.[benchmarkCase].ResultStatistics.Mean - - sprintf "%f" <| float edges / (meanTime * 1e-6) - - member this.GetValue(summary: Summary, benchmarkCase: BenchmarkCase, style: SummaryStyle) : string = - (this :> IColumn).GetValue(summary, benchmarkCase) - - member this.Id: string = "TEPSColumn" - member this.IsAvailable(summary: Summary) : bool = true - member this.IsDefault(summary: Summary, benchmarkCase: BenchmarkCase) : bool = false - member this.IsNumeric: bool = true - member this.Legend: string = "Traversed edges per second" - member this.PriorityInCategory: int = 0 - member this.UnitType: UnitType = UnitType.Dimensionless - module Utils = type BenchmarkContext = { ClContext: Brahma.FSharp.ClContext @@ -218,7 +102,7 @@ module Utils = .GetDeviceInfo(device, DeviceInfo.Type, &e) .CastTo() - let clDeviceType = + let _ = match deviceType with | DeviceType.Cpu -> ClDeviceType.Cpu | DeviceType.Gpu -> ClDeviceType.Gpu @@ -248,9 +132,44 @@ module Utils = random.NextBytes buffer System.BitConverter.ToSingle(buffer, 0) + let normalFloatGenerator = + (Arb.Default.NormalFloat() + |> Arb.toGen + |> Gen.map float) + + let fIsEqual x y = abs (x - y) < Accuracy.medium.absolute || x.Equals y + let nextInt (random: System.Random) = random.Next() +module Operations = + let inline add () = <@ fun x y -> Some(x + y) @> + + let addWithFilter = <@ fun x y -> + let res = x + y + if abs res < 1e-8f then None else Some res + @> + + let inline mult () = <@ fun x y -> Some <|x * y @> + + let logicalOr = <@ fun x y -> + let mutable res = None + + match x, y with + | false, false -> res <- None + | _ -> res <- Some true + + res @> + + let logicalAnd = <@ fun x y -> + let mutable res = None + + match x, y with + | true, true -> res <- Some true + | _ -> res <- None + + res @> + module VectorGenerator = let private pairOfVectorsOfEqualSize (valuesGenerator: Gen<'a>) createVector = gen { @@ -268,23 +187,19 @@ module VectorGenerator = |> pairOfVectorsOfEqualSize Arb.generate let floatPair format = - let normalFloatGenerator = - (Arb.Default.NormalFloat() - |> Arb.toGen - |> Gen.map float) - let fIsEqual x y = abs (x - y) < Accuracy.medium.absolute || x = y let createVector array = Utils.createVectorFromArray format array (fIsEqual 0.0) - pairOfVectorsOfEqualSize normalFloatGenerator createVector + pairOfVectorsOfEqualSize Utils.normalFloatGenerator createVector + module MatrixGenerator = let private pairOfMatricesOfEqualSizeGenerator (valuesGenerator: Gen<'a>) createMatrix = gen { - let! nrows, ncols = Generators.dimension2DGenerator - let! matrixA = valuesGenerator |> Gen.array2DOfDim (nrows, ncols) - let! matrixB = valuesGenerator |> Gen.array2DOfDim (nrows, ncols) + let! rowsCount, columnsCount = Generators.dimension2DGenerator + let! matrixA = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) + let! matrixB = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) return (createMatrix matrixA, createMatrix matrixB) } @@ -293,12 +208,47 @@ module MatrixGenerator = |> pairOfMatricesOfEqualSizeGenerator Arb.generate let floatPairOfEqualSizes format = - let normalFloatGenerator = - (Arb.Default.NormalFloat() - |> Arb.toGen - |> Gen.map float) + fun array -> Utils.createMatrixFromArray2D format array (Utils.fIsEqual 0.0) + |> pairOfMatricesOfEqualSizeGenerator Utils.normalFloatGenerator - let fIsEqual x y = abs (x - y) < Accuracy.medium.absolute || x = y + let private pairOfMatricesWithMaskOfEqualSizeGenerator (valuesGenerator: Gen<'a>) format createMatrix = + gen { + let! rowsCount, columnsCount = Generators.dimension2DGenerator + let! matrixA = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) + let! matrixB = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) + let! mask = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) + + return (createMatrix format matrixA, + createMatrix format matrixB, + createMatrix COO mask) + } + + let intPairWithMaskOfEqualSizes format = + fun format array -> Utils.createMatrixFromArray2D format array ((=) 0) + |> pairOfMatricesWithMaskOfEqualSizeGenerator Arb.generate format + + let floatPairWithMaskOfEqualSizes format = + fun format array -> Utils.createMatrixFromArray2D format array (Utils.fIsEqual 0.0) + |> pairOfMatricesWithMaskOfEqualSizeGenerator Utils.normalFloatGenerator format + +module MatrixVectorGenerator = + let private pairOfMatricesAndVectorGenerator (valuesGenerator: Gen<'a>) createVector createMatrix = + gen { + let! rowsCount, columnsCount = Generators.dimension2DGenerator + let! matrixA = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) + let! vector = valuesGenerator |> Gen.arrayOfLength columnsCount + + return (createMatrix matrixA, createVector vector) + } + + let intPairOfCompatibleSizes matrixFormat vectorFormat = + let createVector array = Utils.createVectorFromArray vectorFormat array ((=) 0) + let createMatrix array = Utils.createMatrixFromArray2D matrixFormat array ((=) 0) + + pairOfMatricesAndVectorGenerator Arb.generate createVector createMatrix + + let floatPairOfCompatibleSizes matrixFormat vectorFormat = + let createVector array = Utils.createVectorFromArray vectorFormat array (Utils.floatIsEqual 0.0) + let createMatrix array = Utils.createMatrixFromArray2D matrixFormat array (Utils.floatIsEqual 0.0) - fun array -> Utils.createMatrixFromArray2D format array (fIsEqual 0.0) - |> pairOfMatricesOfEqualSizeGenerator normalFloatGenerator + pairOfMatricesAndVectorGenerator Utils.normalFloatGenerator createVector createMatrix diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs index da62a739..9a7bd385 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs @@ -1,4 +1,4 @@ -namespace GraphBLAS.FSharp.Benchmarks +namespace GraphBLAS.FSharp.Benchmarks.Matrix.Map2 open System.IO open GraphBLAS.FSharp.Backend.Quotes @@ -16,7 +16,7 @@ open GraphBLAS.FSharp.Benchmarks [] [] [)>] -type Map2Benchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( +type Map2<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( buildFunToBenchmark, converter: string -> 'elem, converterBool, @@ -108,7 +108,7 @@ type Map2BenchmarksWithoutDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceM converterBool, buildMatrix) = - inherit Map2Benchmarks<'matrixT, 'elem>( + inherit Map2<'matrixT, 'elem>( buildFunToBenchmark, converter, converterBool, @@ -140,7 +140,7 @@ type Map2BenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemO buildMatrix, resultToHost) = - inherit Map2Benchmarks<'matrixT, 'elem>( + inherit Map2<'matrixT, 'elem>( buildFunToBenchmark, converter, converterBool, @@ -176,7 +176,7 @@ type MatrixCOOMap2Float32WithoutTransferBenchmark() = ) static member InputMatricesProvider = - Map2Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + Map2<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" type MatrixCOOMap2Float32WithTransferBenchmark() = @@ -189,7 +189,7 @@ type MatrixCOOMap2Float32WithTransferBenchmark() = ) static member InputMatricesProvider = - Map2Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + Map2<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" type MatrixCOOMap2BoolWithoutTransferBenchmark() = @@ -202,7 +202,7 @@ type MatrixCOOMap2BoolWithoutTransferBenchmark() = ) static member InputMatricesProvider = - Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCOO.txt" + Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCOO.txt" type MatrixCSRMap2Float32WithoutTransferBenchmark() = @@ -215,7 +215,7 @@ type MatrixCSRMap2Float32WithoutTransferBenchmark() = ) static member InputMatricesProvider = - Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32CSR.txt" + Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32CSR.txt" type MatrixCSRMap2BoolWithoutTransferBenchmark() = @@ -228,7 +228,7 @@ type MatrixCSRMap2BoolWithoutTransferBenchmark() = ) static member InputMatricesProvider = - Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" // AtLeastOne @@ -242,7 +242,7 @@ type MatrixCOOMap2AtLeastOne4BoolWithoutTransferBenchmark() = ) static member InputMatricesProvider = - Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" type MatrixCSRMap2AtLeastOne4BoolWithoutTransferBenchmark() = @@ -254,7 +254,7 @@ type MatrixCSRMap2AtLeastOne4BoolWithoutTransferBenchmark() = ) static member InputMatricesProvider = - Map2Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" type MatrixCOOMap2AtLeastOne4Float32WithoutTransferBenchmark() = @@ -266,7 +266,7 @@ type MatrixCOOMap2AtLeastOne4Float32WithoutTransferBenchmark() = ) static member InputMatricesProvider = - Map2Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + Map2<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" type MatrixCSRMap2AtLeastOne4Float32CSRWithoutTransferBenchmark() = @@ -278,4 +278,4 @@ type MatrixCSRMap2AtLeastOne4Float32CSRWithoutTransferBenchmark() = ) static member InputMatricesProvider = - Map2Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + Map2<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs index 133d1d6c..68c763b0 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs @@ -1,4 +1,4 @@ -namespace GraphBLAS.FSharp.Benchmarks +namespace GraphBLAS.FSharp.Benchmarks.Matrix.SpGeMM open System.IO open GraphBLAS.FSharp.IO @@ -14,8 +14,8 @@ open GraphBLAS.FSharp.Backend [] [] [] -[)>] -type MxmBenchmarks<'elem when 'elem : struct>( +[)>] +type Masked<'elem when 'elem : struct>( buildFunToBenchmark, converter: string -> 'elem, converterBool, @@ -142,7 +142,7 @@ type MxmBenchmarksMultiplicationOnly<'elem when 'elem : struct>( converterBool, buildMatrix) = - inherit MxmBenchmarks<'elem>( + inherit Masked<'elem>( buildFunToBenchmark, converter, converterBool, @@ -173,7 +173,7 @@ type MxmBenchmarksWithTransposing<'elem when 'elem : struct>( converterBool, buildMatrix) = - inherit MxmBenchmarks<'elem>( + inherit Masked<'elem>( buildFunToBenchmark, converter, converterBool, @@ -210,7 +210,7 @@ type Mxm4Float32MultiplicationOnlyBenchmark() = ) static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" + Masked<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" type Mxm4Float32WithTransposingBenchmark() = @@ -222,7 +222,7 @@ type Mxm4Float32WithTransposingBenchmark() = ) static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" + Masked<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" type Mxm4BoolMultiplicationOnlyBenchmark() = @@ -234,7 +234,7 @@ type Mxm4BoolMultiplicationOnlyBenchmark() = ) static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" + Masked<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" type Mxm4BoolWithTransposingBenchmark() = @@ -246,7 +246,7 @@ type Mxm4BoolWithTransposingBenchmark() = ) static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" + Masked<_>.InputMatrixProviderBuilder "MxmBenchmarks4Bool.txt" type Mxm4Float32MultiplicationOnlyWithZerosFilterBenchmark() = @@ -258,7 +258,7 @@ type Mxm4Float32MultiplicationOnlyWithZerosFilterBenchmark() = ) static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" + Masked<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" type Mxm4Float32WithTransposingWithZerosFilterBenchmark() = @@ -270,4 +270,4 @@ type Mxm4Float32WithTransposingWithZerosFilterBenchmark() = ) static member InputMatrixProvider = - MxmBenchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" + Masked<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs index 20749b67..1da659bc 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs @@ -4,7 +4,7 @@ open BenchmarkDotNet.Running [] let main argv = let benchmarks = - BenchmarkSwitcher [| typeof |] + BenchmarkSwitcher [| typeof |] benchmarks.Run argv |> ignore 0 diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs index 0ca9069a..4241d8da 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs @@ -1,4 +1,4 @@ -namespace GraphBLAS.FSharp.Benchmarks +namespace GraphBLAS.FSharp.Benchmarks.Vector namespace GraphBLAS.FSharp.Benchmarks.Synthetic @@ -18,8 +18,8 @@ open GraphBLAS.FSharp.Backend.Objects.ClContext [] [] [] -[)>] -type VectorEWiseBenchmarks<'elem when 'elem : struct>( +[)>] +type Map2<'elem when 'elem : struct>( buildFunToBenchmark, generator: Gen * Vector<'elem>>) = @@ -33,7 +33,7 @@ type VectorEWiseBenchmarks<'elem when 'elem : struct>( member val ResultVector = Unchecked.defaultof> with get,set - [] + [] member val OclContextInfo = Unchecked.defaultof with get, set [] @@ -44,10 +44,10 @@ type VectorEWiseBenchmarks<'elem when 'elem : struct>( member this.Processor = let p = (fst this.OclContextInfo).Queue - p.Error.Add(fun e -> failwithf "%A" e) + p.Error.Add(fun e -> failwithf $"%A{e}") p - static member AvaliableContexts = Utils.avaliableContexts + static member AvailableContexts = Utils.avaliableContexts member this.FunToBenchmark = match funToBenchmark with @@ -95,7 +95,7 @@ type VectorEWiseBenchmarksWithoutDataTransfer<'elem when 'elem : struct>( buildFunToBenchmark, generator) = - inherit VectorEWiseBenchmarks<'elem>( + inherit Map2<'elem>( buildFunToBenchmark, generator) @@ -125,7 +125,7 @@ type VectorEWiseBenchmarksWithDataTransfer<'elem when 'elem : struct>( buildFunToBenchmark, generator) = - inherit VectorEWiseBenchmarks<'elem>( + inherit Map2<'elem>( buildFunToBenchmark, generator) diff --git a/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs b/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs index 5e0ba6c4..737f196e 100644 --- a/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs +++ b/src/GraphBLAS-sharp.Backend/Quotes/Arithmetic.fs @@ -56,7 +56,7 @@ module ArithmeticOperations = if res = zero then None else Some res @> - let boolSum = + let boolSumOption = <@ fun (x: bool option) (y: bool option) -> let mutable res = false diff --git a/src/GraphBLAS-sharp/IO/MtxReader.fs b/src/GraphBLAS-sharp/IO/MtxReader.fs index 6059b8bc..db4d4d5a 100644 --- a/src/GraphBLAS-sharp/IO/MtxReader.fs +++ b/src/GraphBLAS-sharp/IO/MtxReader.fs @@ -42,7 +42,7 @@ type MtxReader(pathToFile: string) = ColumnCount = ncols Nnz = nnz |} - member this.ReadMatrix(converter: string -> 'a) : Matrix<'a> = + member this.ReadMatrix(converter: string -> 'a) : Matrix.COO<'a> = if object <> MtxMatrix then failwith "Object is not matrix" @@ -119,12 +119,11 @@ type MtxReader(pathToFile: string) = values.[i] <- value) sortedData - Matrix.COO - { Rows = rows - Columns = cols - Values = values - RowCount = n - ColumnCount = m } + { Matrix.COO.Rows = rows + Matrix.COO.Columns = cols + Matrix.COO.Values = values + Matrix.COO.RowCount = n + Matrix.COO.ColumnCount = m } match format with | Coordinate -> matrixFromCoordinateFormat () diff --git a/src/GraphBLAS-sharp/Objects/Matrix.fs b/src/GraphBLAS-sharp/Objects/Matrix.fs index e0724e8e..c1ed4c33 100644 --- a/src/GraphBLAS-sharp/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp/Objects/Matrix.fs @@ -73,7 +73,7 @@ module Matrix = Values = values } static member FromArray2D(array: 'a [,], isZero: 'a -> bool) = - let rows, cols, vals = + let rows, cols, values = array |> Seq.cast<'a> |> Seq.mapi (fun idx v -> (idx / Array2D.length2 array, idx % Array2D.length2 array, v)) @@ -81,7 +81,7 @@ module Matrix = |> Array.ofSeq |> Array.unzip3 - COO.FromTuples(Array2D.length1 array, Array2D.length2 array, rows, cols, vals) + COO.FromTuples(Array2D.length1 array, Array2D.length2 array, rows, cols, values) member this.ToDevice(context: ClContext) = { Context = context @@ -91,7 +91,7 @@ module Matrix = Columns = context.CreateClArray this.Columns Values = context.CreateClArray this.Values } - member this.toCSR = + member this.ToCSR = let rowPointers = let nnzPerRow = Array.zeroCreate this.RowCount let rowPointers = Array.zeroCreate this.RowCount diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index 738224d5..0e8eda2f 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -6,31 +6,6 @@ open Expecto.Logging open Expecto.Logging.Message open FSharp.Quotations.Evaluator -[] -module Extensions = - type ClosedBinaryOp<'a> with - member this.Invoke = - let (ClosedBinaryOp f) = this - QuotationEvaluator.Evaluate f - -module CustomDatatypes = - // мб заменить рекорд на структуру (не помогает) - [] - type WrappedInt = - { InnerValue: int } - static member (+)(x: WrappedInt, y: WrappedInt) = - { InnerValue = x.InnerValue + y.InnerValue } - - static member (*)(x: WrappedInt, y: WrappedInt) = - { InnerValue = x.InnerValue * y.InnerValue } - - let addMultSemiringOnWrappedInt: Semiring = - { PlusMonoid = - { AssociativeOp = ClosedBinaryOp <@ (+) @> - Identity = { InnerValue = 0 } } - - TimesSemigroup = { AssociativeOp = ClosedBinaryOp <@ (*) @> } } - module Generators = let logger = Log.create "Generators" @@ -311,13 +286,6 @@ module Generators = |> genericSparseGenerator false Arb.generate |> Arb.fromGen - static member WrappedInt() = - pairOfMatrixAndVectorOfCompatibleSizeGenerator - |> genericSparseGenerator - CustomDatatypes.addMultSemiringOnWrappedInt.PlusMonoid.Identity - Arb.generate - |> Arb.fromGen - type PairOfSparseVectorAndMatrixAndMaskOfCompatibleSize() = static let pairOfVectorAndMatrixOfCompatibleSizeGenerator (valuesGenerator: Gen<'a>) = gen { diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs index 9c1fdf6e..3d179e21 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs @@ -114,7 +114,7 @@ let testFixturesMap2Add case = let q = case.TestContext.Queue q.Error.Add(fun e -> failwithf "%A" e) - creatTestMap2Add case false (||) (=) ArithmeticOperations.boolSum Matrix.map2 + creatTestMap2Add case false (||) (=) ArithmeticOperations.boolSumOption Matrix.map2 creatTestMap2Add case 0 (+) (=) ArithmeticOperations.intSumOption Matrix.map2 if Utils.isFloat64Available context.ClDevice then diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Map2.fs b/tests/GraphBLAS-sharp.Tests/Vector/Map2.fs index 0ff08e3f..cfb16b53 100644 --- a/tests/GraphBLAS-sharp.Tests/Vector/Map2.fs +++ b/tests/GraphBLAS-sharp.Tests/Vector/Map2.fs @@ -107,7 +107,7 @@ let addTestFixtures case = createTest case Utils.floatIsEqual 0.0 (+) ArithmeticOperations.floatSumOption Vector.map2 createTest case Utils.float32IsEqual 0.0f (+) ArithmeticOperations.float32SumOption Vector.map2 - createTest case (=) false (||) ArithmeticOperations.boolSum Vector.map2 + createTest case (=) false (||) ArithmeticOperations.boolSumOption Vector.map2 createTest case (=) 0uy (+) ArithmeticOperations.byteSumOption Vector.map2 ] let addTests = diff --git a/tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs b/tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs index db42fd9d..252c45ba 100644 --- a/tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs +++ b/tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs @@ -104,7 +104,7 @@ let testFixturesSpMV (testContext: TestContext) = let q = testContext.Queue q.Error.Add(fun e -> failwithf "%A" e) - createTest testContext false (=) (||) (&&) ArithmeticOperations.boolSum ArithmeticOperations.boolMulOption + createTest testContext false (=) (||) (&&) ArithmeticOperations.boolSumOption ArithmeticOperations.boolMulOption createTest testContext 0 (=) (+) (*) ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption if Utils.isFloat64Available context.ClDevice then From 1d45950da21e198c3f3e48929c335146c6f27dae Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sun, 23 Apr 2023 10:22:35 +0300 Subject: [PATCH 27/44] refactor: README --- README.md | 23 +- .../Algorithms/{BFS.fs => Benchmark.fs} | 152 ++++---- .../GraphBLAS-sharp.Benchmarks.fsproj | 3 +- .../GraphBLAS-sharp.Benchmarks/Helpers.fs | 42 +- .../Matrix/Map2/Map2.fs | 360 +++++++++--------- .../Matrix/SpGeMM/Expand.fs | 148 +++++++ .../Matrix/SpGeMM/Masked.fs | 2 +- .../GraphBLAS-sharp.Benchmarks/Program.fs | 2 +- .../GraphBLAS-sharp.Benchmarks/Vector/Map2.fs | 173 +++++---- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 89 ++--- .../Common/Sort/Radix.fs | 18 +- .../Matrix/CSR/Matrix.fs | 4 +- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 4 +- .../Matrix/SpGeMM/Expand.fs | 14 +- .../Vector/Dense/Vector.fs | 2 +- .../Common/ClArray/ChunkBySize.fs | 36 +- tests/GraphBLAS-sharp.Tests/Generators.fs | 66 +++- 17 files changed, 648 insertions(+), 490 deletions(-) rename benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/{BFS.fs => Benchmark.fs} (54%) create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs diff --git a/README.md b/README.md index 87c72287..c58f7839 100644 --- a/README.md +++ b/README.md @@ -25,27 +25,32 @@ GraphBLAS# is a GPGPU-based [GraphBLAS](https://graphblas.org/)-like API impleme ### Operations - **Matrix-Matrix** - - [x] COO-COO `map2` - [x] CSR-CSR `map2` + - [x] CSR-CSR `map2AtLeastOne` + - [x] COO-COO `map2` + - [x] COO-COO `map2AtLeastOne` - [x] CSR-CSR multiplication - **Vector-Matrix** - [x] Dense-CSR multiplication - - [ ] COO-CSR multiplication + - [ ] Sparse-CSR multiplication - **Vector-Vector** - - [x] Dense-Dense element-wise - - [x] Sparse-Sparse element-wise + - [x] Dense-Dense `map2` + - [x] Dense-Dense `map2AtLeastOne` + - [x] Sparse-Sparse `map2` + - [x] Sparse-Sparse `map2AtLeastOne` - [ ] ... - **Matrix** + - [x] `copy` - [x] `map` - [x] COO transpose - [x] CSR transpose - - [ ] `iter` + - [x] CSC transpose - [ ] ... - **Vector** - - [x] `map` - - [ ] `iter` - - [ ] `filter` - - [ ] `contains` + - [x] `zeroCreate` + - [x] `ofList` + - [x] `copy` + - [x] `reduce` - [ ] ... ### Graph Analysis Algorithms diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/Benchmark.fs similarity index 54% rename from benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs rename to benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/Benchmark.fs index 365db3df..4711b9cc 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/Benchmark.fs @@ -1,4 +1,4 @@ -namespace GraphBLAS.FSharp.Benchmarks.Algorithms +namespace GraphBLAS.FSharp.Benchmarks.Algorithms.BFS open System.IO open BenchmarkDotNet.Attributes @@ -16,7 +16,7 @@ open GraphBLAS.FSharp.Backend.Objects [] [] [)>] -type BFS<'elem when 'elem : struct>( +type Benchmarks<'elem when 'elem : struct>( buildFunToBenchmark, converter: string -> 'elem, binaryConverter, @@ -43,7 +43,7 @@ type BFS<'elem when 'elem : struct>( p.Error.Add(fun e -> failwithf "%A" e) p - static member AvailableContexts = Utils.avaliableContexts + static member AvailableContexts = Utils.availableContexts static member InputMatrixProviderBuilder pathToConfig = let datasetFolder = "BFS" @@ -92,87 +92,89 @@ type BFS<'elem when 'elem : struct>( abstract member Benchmark : unit -> unit -type BFSBenchmarksWithoutDataTransfer<'elem when 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - boolConverter, - vertex) = - - inherit BFS<'elem>( - buildFunToBenchmark, - converter, - boolConverter, - vertex) - - [] - override this.GlobalSetup() = - this.ReadMatrix() - this.LoadMatrixToGPU() - - [] - override this.IterationCleanup() = - this.ClearResult() - - [] - override this.GlobalCleanup() = - this.ClearInputMatrix() - - [] - override this.Benchmark() = - this.BFS() - this.Processor.PostAndReply Msg.MsgNotifyMe - -type BFSBenchmarksWithTransfer<'elem when 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - boolConverter, - vertex) = - - inherit BFS<'elem>( +module WithoutTransfer = + type Benchmark<'elem when 'elem : struct>( buildFunToBenchmark, - converter, + converter: string -> 'elem, boolConverter, - vertex) - - [] - override this.GlobalSetup() = - this.ReadMatrix() + vertex) = - [] - override this.GlobalCleanup() = - this.ClearResult() + inherit Benchmarks<'elem>( + buildFunToBenchmark, + converter, + boolConverter, + vertex) - [] - override this.IterationCleanup() = - this.ClearInputMatrix() - this.ClearResult() + [] + override this.GlobalSetup() = + this.ReadMatrix() + this.LoadMatrixToGPU() - [] - override this.Benchmark() = - this.LoadMatrixToGPU() - this.BFS() - this.ResultLevels.ToHost this.Processor |> ignore - this.Processor.PostAndReply Msg.MsgNotifyMe + [] + override this.IterationCleanup() = + this.ClearResult() -type BFSIntWithoutTransferBenchmark() = + [] + override this.GlobalCleanup() = + this.ClearInputMatrix() - inherit BFSBenchmarksWithoutDataTransfer( - (fun context -> singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), - int32, - (fun _ -> Utils.nextInt (System.Random())), - 0) + [] + override this.Benchmark() = + this.BFS() + this.Processor.PostAndReply Msg.MsgNotifyMe - static member InputMatrixProvider = - BFS<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" + type Int() = -type BFSIntWithTransferBenchmark() = + inherit Benchmark( + (fun context -> singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), + int32, + (fun _ -> Utils.nextInt (System.Random())), + 0) - inherit BFSBenchmarksWithTransfer( - (fun context -> singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), - int32, - (fun _ -> Utils.nextInt (System.Random())), - 0) + static member InputMatrixProvider = + Benchmark<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" - static member InputMatrixProvider = - BFS<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" +module WithTransfer = + type Benchmark<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + boolConverter, + vertex) = + + inherit Benchmarks<'elem>( + buildFunToBenchmark, + converter, + boolConverter, + vertex) + + [] + override this.GlobalSetup() = + this.ReadMatrix() + + [] + override this.GlobalCleanup() = + this.ClearResult() + + [] + override this.IterationCleanup() = + this.ClearInputMatrix() + this.ClearResult() + + [] + override this.Benchmark() = + this.LoadMatrixToGPU() + this.BFS() + this.ResultLevels.ToHost this.Processor |> ignore + this.Processor.PostAndReply Msg.MsgNotifyMe + + type Int() = + + inherit Benchmark( + (fun context -> singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), + int32, + (fun _ -> Utils.nextInt (System.Random())), + 0) + + static member InputMatrixProvider = + Benchmark<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj b/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj index e3a8d920..1a5d1710 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj @@ -21,10 +21,11 @@ + - + diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs index 4183e1d1..0d292f3c 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs @@ -38,7 +38,7 @@ module Utils = datasetsFolder matrixFilename |] - let avaliableContexts = + let availableContexts = let pathToConfig = Path.Combine [| __SOURCE_DIRECTORY__ "Configs" @@ -97,18 +97,6 @@ module Utils = .ToString() |> Platform.Custom - let deviceType = - Cl - .GetDeviceInfo(device, DeviceInfo.Type, &e) - .CastTo() - - let _ = - match deviceType with - | DeviceType.Cpu -> ClDeviceType.Cpu - | DeviceType.Gpu -> ClDeviceType.Gpu - | DeviceType.Default -> ClDeviceType.Default - | _ -> failwith "Unsupported" - let device = ClDevice.GetFirstAppropriateDevice(clPlatform) @@ -142,34 +130,6 @@ module Utils = let nextInt (random: System.Random) = random.Next() -module Operations = - let inline add () = <@ fun x y -> Some(x + y) @> - - let addWithFilter = <@ fun x y -> - let res = x + y - if abs res < 1e-8f then None else Some res - @> - - let inline mult () = <@ fun x y -> Some <|x * y @> - - let logicalOr = <@ fun x y -> - let mutable res = None - - match x, y with - | false, false -> res <- None - | _ -> res <- Some true - - res @> - - let logicalAnd = <@ fun x y -> - let mutable res = None - - match x, y with - | true, true -> res <- Some true - | _ -> res <- None - - res @> - module VectorGenerator = let private pairOfVectorsOfEqualSize (valuesGenerator: Gen<'a>) createVector = gen { diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs index 9a7bd385..b2fb0bc6 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs @@ -16,7 +16,7 @@ open GraphBLAS.FSharp.Benchmarks [] [] [)>] -type Map2<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( +type Benchmarks<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( buildFunToBenchmark, converter: string -> 'elem, converterBool, @@ -44,7 +44,7 @@ type Map2<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( p.Error.Add(fun e -> failwithf "%A" e) p - static member AvailableContexts = Utils.avaliableContexts + static member AvailableContexts = Utils.availableContexts static member InputMatricesProviderBuilder pathToConfig = let datasetFolder = "EWiseAdd" @@ -102,180 +102,184 @@ type Map2<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( abstract member GlobalCleanup: unit -> unit -type Map2BenchmarksWithoutDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - inherit Map2<'matrixT, 'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup() = - this.ReadMatrices () - this.LoadMatricesToGPU () - this.Processor.PostAndReply(Msg.MsgNotifyMe) - - [] - override this.Benchmark () = - this.EWiseAddition() - this.Processor.PostAndReply(Msg.MsgNotifyMe) - - [] - override this.IterationCleanup () = - this.ClearResult() - - [] - override this.GlobalCleanup () = - this.ClearInputMatrices() - -type Map2BenchmarksWithDataTransfer<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix, - resultToHost) = - - inherit Map2<'matrixT, 'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup() = - this.ReadMatrices() - - [] - override this.GlobalCleanup() = () - - [] - override this.IterationCleanup() = - this.ClearInputMatrices() - this.ClearResult() - - [] - override this.Benchmark() = - this.LoadMatricesToGPU() - this.EWiseAddition() - this.Processor.PostAndReply Msg.MsgNotifyMe - resultToHost this.ResultMatrix this.Processor |> ignore - this.Processor.PostAndReply Msg.MsgNotifyMe - -type MatrixCOOMap2Float32WithoutTransferBenchmark() = - - inherit Map2BenchmarksWithoutDataTransfer,float32>( - (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.COO - ) - - static member InputMatricesProvider = - Map2<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - -type MatrixCOOMap2Float32WithTransferBenchmark() = - - inherit Map2BenchmarksWithDataTransfer,float32>( - (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.COO, - (fun matrix -> matrix.ToHost) - ) - - static member InputMatricesProvider = - Map2<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - - -type MatrixCOOMap2BoolWithoutTransferBenchmark() = - - inherit Map2BenchmarksWithoutDataTransfer,bool>( - (fun context -> Matrix.map2 context ArithmeticOperations.boolSumOption), - (fun _ -> true), - (fun _ -> true), - Matrix.COO - ) - - static member InputMatricesProvider = - Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCOO.txt" - - -type MatrixCSRMap2Float32WithoutTransferBenchmark() = - - inherit Map2BenchmarksWithoutDataTransfer,float32>( - (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - (fun matrix -> Matrix.CSR matrix.ToCSR) - ) - - static member InputMatricesProvider = - Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32CSR.txt" - - -type MatrixCSRMap2BoolWithoutTransferBenchmark() = - - inherit Map2BenchmarksWithoutDataTransfer,bool>( - (fun context -> Matrix.map2 context ArithmeticOperations.boolSumOption), - (fun _ -> true), - (fun _ -> true), - (fun matrix -> Matrix.CSR matrix.ToCSR) - ) - - static member InputMatricesProvider = - Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" - -// AtLeastOne - -type MatrixCOOMap2AtLeastOne4BoolWithoutTransferBenchmark() = - - inherit Map2BenchmarksWithoutDataTransfer,bool>( - (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne), - (fun _ -> true), - (fun _ -> true), - Matrix.COO - ) - - static member InputMatricesProvider = - Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" - -type MatrixCSRMap2AtLeastOne4BoolWithoutTransferBenchmark() = - - inherit Map2BenchmarksWithoutDataTransfer,bool>( - (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne), - (fun _ -> true), - (fun _ -> true), - (fun matrix -> Matrix.CSR matrix.ToCSR) - ) - - static member InputMatricesProvider = - Map2<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" - -type MatrixCOOMap2AtLeastOne4Float32WithoutTransferBenchmark() = - - inherit Map2BenchmarksWithoutDataTransfer,float32>( - (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - Matrix.COO - ) - - static member InputMatricesProvider = - Map2<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - -type MatrixCSRMap2AtLeastOne4Float32CSRWithoutTransferBenchmark() = - - inherit Map2BenchmarksWithoutDataTransfer,float32>( - (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne), - float32, - (fun _ -> Utils.nextSingle (System.Random())), - (fun matrix -> Matrix.CSR matrix.ToCSR) - ) +module WithoutTransfer = + type Benchmark<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + inherit Benchmarks<'matrixT, 'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup() = + this.ReadMatrices () + this.LoadMatricesToGPU () + this.Processor.PostAndReply(Msg.MsgNotifyMe) + + [] + override this.Benchmark () = + this.EWiseAddition() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + + [] + override this.IterationCleanup () = + this.ClearResult() + + [] + override this.GlobalCleanup () = + this.ClearInputMatrices() + + module COO = + type Float32() = + + inherit Benchmark,float32>( + (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.COO + ) + + static member InputMatricesProvider = + Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + + type Bool() = + + inherit Benchmark,bool>( + (fun context -> Matrix.map2 context ArithmeticOperations.boolSumOption), + (fun _ -> true), + (fun _ -> true), + Matrix.COO + ) + + static member InputMatricesProvider = + Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCOO.txt" + + module CSR = + type Float32() = + + inherit Benchmark,float32>( + (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + (fun matrix -> Matrix.CSR matrix.ToCSR) + ) + + static member InputMatricesProvider = + Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32CSR.txt" + + type Bool() = + + inherit Benchmark,bool>( + (fun context -> Matrix.map2 context ArithmeticOperations.boolSumOption), + (fun _ -> true), + (fun _ -> true), + (fun matrix -> Matrix.CSR matrix.ToCSR) + ) + + static member InputMatricesProvider = + Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + + module AtLeastOne = + module COO = + type Bool() = + + inherit Benchmark,bool>( + (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne), + (fun _ -> true), + (fun _ -> true), + Matrix.COO + ) + + static member InputMatricesProvider = + Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCOO.txt" + + type Float32() = + + inherit Benchmark,float32>( + (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.COO + ) + + static member InputMatricesProvider = + Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + + module CSR = + type Bool() = + + inherit Benchmark,bool>( + (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne), + (fun _ -> true), + (fun _ -> true), + (fun matrix -> Matrix.CSR matrix.ToCSR) + ) + + static member InputMatricesProvider = + Benchmarks<_, _>.InputMatricesProviderBuilder "EWiseAddBenchmarks4BoolCSR.txt" + + type Float32() = + + inherit Benchmark,float32>( + (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + (fun matrix -> Matrix.CSR matrix.ToCSR) + ) + + static member InputMatricesProvider = + Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" + +module WithTransfer = + type Benchmark<'matrixT, 'elem when 'matrixT :> IDeviceMemObject and 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix, + resultToHost) = + + inherit Benchmarks<'matrixT, 'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup() = + this.ReadMatrices() + + [] + override this.GlobalCleanup() = () + + [] + override this.IterationCleanup() = + this.ClearInputMatrices() + this.ClearResult() + + [] + override this.Benchmark() = + this.LoadMatricesToGPU() + this.EWiseAddition() + this.Processor.PostAndReply Msg.MsgNotifyMe + resultToHost this.ResultMatrix this.Processor |> ignore + this.Processor.PostAndReply Msg.MsgNotifyMe + + module COO = + type Float32() = + + inherit Benchmark,float32>( + (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + Matrix.COO, + (fun matrix -> matrix.ToHost) + ) + + static member InputMatricesProvider = + Benchmarks<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" - static member InputMatricesProvider = - Map2<_,_>.InputMatricesProviderBuilder "EWiseAddBenchmarks4Float32COO.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs new file mode 100644 index 00000000..a99730b9 --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs @@ -0,0 +1,148 @@ +module GraphBLAS.FSharp.Benchmarks.Matrix.SpGeMM.Expand + +open System.IO +open GraphBLAS.FSharp.Backend.Quotes +open GraphBLAS.FSharp.IO +open BenchmarkDotNet.Attributes +open Brahma.FSharp +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Matrix +open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Benchmarks +open GraphBLAS.FSharp.Backend + +[] +[] +[] +[)>] +type Benchmarks<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + let mutable funToBenchmark = None + + let mutable firstMatrix = Unchecked.defaultof> + let mutable secondMatrix = Unchecked.defaultof> + + let mutable firstMatrixHost = Unchecked.defaultof<_> + let mutable secondMatrixHost = Unchecked.defaultof<_> + + member val ResultMatrix = Unchecked.defaultof> with get, set + + [] + member val OclContextInfo = Unchecked.defaultof with get, set + + [] + member val InputMatrixReader = Unchecked.defaultof with get, set + + member this.OclContext:ClContext = (fst this.OclContextInfo).ClContext + member this.WorkGroupSize = snd this.OclContextInfo + + member this.Processor = + let p = (fst this.OclContextInfo).Queue + p.Error.Add(fun e -> failwithf "%A" e) + p + + static member AvailableContexts = Utils.availableContexts + + static member InputMatrixProviderBuilder pathToConfig = + let datasetFolder = "Mxm" + pathToConfig + |> Utils.getMatricesFilenames + |> Seq.map + (fun matrixFilename -> + printfn "%A" matrixFilename + + match Path.GetExtension matrixFilename with + | ".mtx" -> + MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) + , MtxReader(Utils.getFullPathToMatrix datasetFolder (matrixFilename)) + | _ -> failwith "Unsupported matrix format") + + member this.FunToBenchmark = + match funToBenchmark with + | None -> + let x = buildFunToBenchmark this.OclContext this.WorkGroupSize + funToBenchmark <- Some x + x + | Some x -> x + + member this.ReadMatrix (reader: MtxReader) = + let converter = + match reader.Field with + | Pattern -> converterBool + | _ -> converter + + reader.ReadMatrix converter + + member this.Mxm() = + this.ResultMatrix <- this.FunToBenchmark this.Processor DeviceOnly firstMatrix secondMatrix + + member this.ClearInputMatrices() = + firstMatrix.Dispose this.Processor + secondMatrix.Dispose this.Processor + + member this.ClearResult() = + this.ResultMatrix.Dispose this.Processor + + member this.ReadMatrices() = + firstMatrixHost <- this.ReadMatrix this.InputMatrixReader + secondMatrixHost <- this.ReadMatrix this.InputMatrixReader + + member this.LoadMatricesToGPU () = + firstMatrix <- buildMatrix this.OclContext firstMatrixHost + secondMatrix <- buildMatrix this.OclContext secondMatrixHost + + abstract member GlobalSetup : unit -> unit + + abstract member Benchmark : unit -> unit + + abstract member IterationCleanup : unit -> unit + + abstract member GlobalCleanup : unit -> unit + +type MxmBenchmarksMultiplicationOnly<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + inherit Benchmarks<'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup() = + this.ReadMatrices() + this.LoadMatricesToGPU() + + [] + override this.Benchmark() = + this.Mxm() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + + [] + override this.IterationCleanup () = + this.ClearResult() + + [] + override this.GlobalCleanup () = + this.ClearInputMatrices() + + +// type Mxm4Float32WithTransposingWithZerosFilterBenchmark() = +// +// inherit MxmBenchmarksWithTransposing( +// (fun context wgSize -> Matrix.SpGeMM.expand context wgSize (fst ArithmeticOperations.float32Add) (fst ArithmeticOperations.float32Mul)), +// float32, +// (fun _ -> Utils.nextSingle (System.Random())), +// (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) +// ) +// +// static member InputMatrixProvider = +// Benchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs index 68c763b0..8e909388 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs @@ -49,7 +49,7 @@ type Masked<'elem when 'elem : struct>( p.Error.Add(fun e -> failwithf "%A" e) p - static member AvaliableContexts = Utils.avaliableContexts + static member AvaliableContexts = Utils.availableContexts static member InputMatrixProviderBuilder pathToConfig = let datasetFolder = "Mxm" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs index 1da659bc..ea487610 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs @@ -4,7 +4,7 @@ open BenchmarkDotNet.Running [] let main argv = let benchmarks = - BenchmarkSwitcher [| typeof |] + BenchmarkSwitcher [| typeof |] benchmarks.Run argv |> ignore 0 diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs index 4241d8da..c39c207f 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs @@ -1,6 +1,4 @@ -namespace GraphBLAS.FSharp.Benchmarks.Vector - -namespace GraphBLAS.FSharp.Benchmarks.Synthetic +module GraphBLAS.FSharp.Benchmarks.Vector.Map2 open FsCheck open BenchmarkDotNet.Attributes @@ -19,7 +17,7 @@ open GraphBLAS.FSharp.Backend.Objects.ClContext [] [] [)>] -type Map2<'elem when 'elem : struct>( +type Benchmarks<'elem when 'elem : struct>( buildFunToBenchmark, generator: Gen * Vector<'elem>>) = @@ -47,7 +45,7 @@ type Map2<'elem when 'elem : struct>( p.Error.Add(fun e -> failwithf $"%A{e}") p - static member AvailableContexts = Utils.avaliableContexts + static member AvailableContexts = Utils.availableContexts member this.FunToBenchmark = match funToBenchmark with @@ -90,115 +88,114 @@ type Map2<'elem when 'elem : struct>( abstract member GlobalCleanup: unit -> unit +module WithoutTransfer = + type Benchmark<'elem when 'elem : struct>( + buildFunToBenchmark, + generator) = -type VectorEWiseBenchmarksWithoutDataTransfer<'elem when 'elem : struct>( - buildFunToBenchmark, - generator) = - - inherit Map2<'elem>( - buildFunToBenchmark, - generator) + inherit Benchmarks<'elem>( + buildFunToBenchmark, + generator) - [] - override this.GlobalSetup() = () + [] + override this.GlobalSetup() = () - [] - override this.IterationSetup() = - this.CreateVectors() - this.LoadVectorsToGPU() - this.Processor.PostAndReply Msg.MsgNotifyMe + [] + override this.IterationSetup() = + this.CreateVectors() + this.LoadVectorsToGPU() + this.Processor.PostAndReply Msg.MsgNotifyMe - [] - override this.Benchmark() = - this.Map2() - this.Processor.PostAndReply Msg.MsgNotifyMe + [] + override this.Benchmark() = + this.Map2() + this.Processor.PostAndReply Msg.MsgNotifyMe - [] - override this.IterationCleanup() = - this.ClearResult() - this.ClearInputVectors() + [] + override this.IterationCleanup() = + this.ClearResult() + this.ClearInputVectors() - [] - override this.GlobalCleanup() = () + [] + override this.GlobalCleanup() = () -type VectorEWiseBenchmarksWithDataTransfer<'elem when 'elem : struct>( - buildFunToBenchmark, - generator) = + type Float() = - inherit Map2<'elem>( - buildFunToBenchmark, - generator) + inherit Benchmark( + (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), + VectorGenerator.floatPair Sparse) - [] - override this.GlobalSetup() = () + type Int32() = - [] - override this.IterationSetup() = - this.CreateVectors() + inherit Benchmark( + (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), + VectorGenerator.intPair Sparse) - [] - override this.Benchmark () = - this.LoadVectorsToGPU() - this.Map2() - this.ResultVector.ToHost this.Processor |> ignore - this.Processor.PostAndReply Msg.MsgNotifyMe + module AtLeastOne = + type Float() = - [] - override this.IterationCleanup () = - this.ClearInputVectors() - this.ClearResult() + inherit Benchmark( + (fun context -> Vector.map2AtLeastOne context ArithmeticOperations.floatSumAtLeastOne), + VectorGenerator.floatPair Sparse) - [] - override this.GlobalCleanup() = () + type Int32() = -/// Without data transfer -type VectorSparseMap2FloatWithoutTransferBenchmark() = + inherit Benchmark( + (fun context -> Vector.map2AtLeastOne context ArithmeticOperations.intSumAtLeastOne), + VectorGenerator.intPair Sparse) - inherit VectorEWiseBenchmarksWithoutDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), - VectorGenerator.floatPair Sparse) +module WithTransfer = + type Benchmark<'elem when 'elem : struct>( + buildFunToBenchmark, + generator) = -type VectorSparseMap2Int32WithoutTransferBenchmark() = + inherit Benchmarks<'elem>( + buildFunToBenchmark, + generator) - inherit VectorEWiseBenchmarksWithoutDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), - VectorGenerator.intPair Sparse) + [] + override this.GlobalSetup() = () -/// General -type VectorSparseMap2GeneralFloatWithoutTransferBenchmark() = + [] + override this.IterationSetup() = + this.CreateVectors() - inherit VectorEWiseBenchmarksWithoutDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), - VectorGenerator.floatPair Sparse) + [] + override this.Benchmark () = + this.LoadVectorsToGPU() + this.Map2() + this.ResultVector.ToHost this.Processor |> ignore + this.Processor.PostAndReply Msg.MsgNotifyMe -type VectorSparseMap2GeneralInt32WithoutTransferBenchmark() = + [] + override this.IterationCleanup () = + this.ClearInputVectors() + this.ClearResult() - inherit VectorEWiseBenchmarksWithoutDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), - VectorGenerator.intPair Sparse) + [] + override this.GlobalCleanup() = () -/// With data transfer -type VectorSparseMap2FloatWithTransferBenchmark() = + type Float() = - inherit VectorEWiseBenchmarksWithDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), - VectorGenerator.floatPair Sparse) + inherit Benchmark( + (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), + VectorGenerator.floatPair Sparse) -type VectorSparseMap2Int32WithTransferBenchmark() = + type Int32() = - inherit VectorEWiseBenchmarksWithDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), - VectorGenerator.intPair Sparse) + inherit Benchmark( + (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), + VectorGenerator.intPair Sparse) -/// Map2 with data transfer -type VectorMap2GeneralFloatSparseWithTransferBenchmark() = + module AtLeastOne = + type Float() = - inherit VectorEWiseBenchmarksWithDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), - VectorGenerator.floatPair Sparse) + inherit Benchmark( + (fun context -> Vector.map2AtLeastOne context ArithmeticOperations.floatSumAtLeastOne), + VectorGenerator.floatPair Sparse) -type VectorMap2GeneralInt32SparseWithTransferBenchmark() = + type Int32() = - inherit VectorEWiseBenchmarksWithDataTransfer( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), - VectorGenerator.intPair Sparse) + inherit Benchmark( + (fun context -> Vector.map2AtLeastOne context ArithmeticOperations.intSumAtLeastOne), + VectorGenerator.intPair Sparse) diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 54b59062..9d743653 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -267,7 +267,7 @@ module ClArray = result - let map2Inplace<'a, 'b, 'c> (clContext: ClContext) workGroupSize (map: Expr<'a -> 'b -> 'c>) = + let map2InPlace<'a, 'b, 'c> (clContext: ClContext) workGroupSize (map: Expr<'a -> 'b -> 'c>) = let kernel = <@ fun (ndRange: Range1D) length (leftArray: ClArray<'a>) (rightArray: ClArray<'b>) (resultArray: ClArray<'c>) -> @@ -296,7 +296,7 @@ module ClArray = let map2<'a, 'b, 'c> (clContext: ClContext) workGroupSize map = let map2 = - map2Inplace<'a, 'b, 'c> clContext workGroupSize map + map2InPlace<'a, 'b, 'c> clContext workGroupSize map fun (processor: MailboxProcessor<_>) allocationMode (leftArray: ClArray<'a>) (rightArray: ClArray<'b>) -> @@ -472,43 +472,39 @@ module ClArray = result - let getChunk (clContext: ClContext) workGroupSize = + let sub (clContext: ClContext) workGroupSize = let kernel = - <@ fun (ndRange: Range1D) startIndex endIndex (sourceArray: ClArray<'a>) (targetChunk: ClArray<'a>) -> + <@ fun (ndRange: Range1D) startIndex count (sourceArray: ClArray<'a>) (targetChunk: ClArray<'a>) -> let gid = ndRange.GlobalID0 - let sourcePosition = gid + startIndex - if sourcePosition < endIndex then + if gid < count then + let sourcePosition = gid + startIndex targetChunk.[gid] <- sourceArray.[sourcePosition] @> let kernel = clContext.Compile kernel - fun (processor: MailboxProcessor<_>) allocationMode (sourceArray: ClArray<'a>) startIndex endIndex -> - if startIndex < 0 then - failwith "startIndex is less than zero" - - if startIndex >= endIndex then - failwith "startIndex is greater than or equal to the endIndex" + fun (processor: MailboxProcessor<_>) allocationMode (sourceArray: ClArray<'a>) startIndex count -> + if count <= 0 then + failwith "Count must be greater than zero" - if endIndex > sourceArray.Length then - failwith "endIndex is larger than the size of the array" + if startIndex < 0 then + failwith "startIndex must be greater then zero" - let resultLength = endIndex - startIndex + if startIndex + count > sourceArray.Length then + failwith "startIndex and count sum is larger than the size of the array" let result = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, count) let ndRange = - Range1D.CreateValid(resultLength, workGroupSize) + Range1D.CreateValid(count, workGroupSize) let kernel = kernel.GetKernel() - processor.Post( - Msg.MsgSetArguments(fun () -> kernel.KernelFunc ndRange startIndex endIndex sourceArray result) - ) + processor.Post(Msg.MsgSetArguments(fun () -> kernel.KernelFunc ndRange startIndex count sourceArray result)) processor.Post(Msg.CreateRunMsg<_, _>(kernel)) @@ -524,25 +520,24 @@ module ClArray = /// let lazyChunkBySize (clContext: ClContext) workGroupSize = - let getChunk = getChunk clContext workGroupSize + let sub = sub clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode chunkSize (sourceArray: ClArray<'a>) -> if chunkSize <= 0 then - failwith "The size of the piece cannot be less than 1" + failwith "The size of the chunk cannot be less than 1" - let chunkCount = (sourceArray.Length - 1) / chunkSize + let chunkCount = (sourceArray.Length - 1) / chunkSize + 1 - let getChunk = - getChunk processor allocationMode sourceArray + let sub = sub processor allocationMode sourceArray seq { - for i in 0 .. chunkCount do + for i in 0 .. chunkCount - 1 do let startIndex = i * chunkSize - let endIndex = - min (startIndex + chunkSize) sourceArray.Length + let count = + min chunkSize (sourceArray.Length - startIndex) - yield lazy (getChunk startIndex endIndex) + yield lazy (sub startIndex count) } /// @@ -575,24 +570,21 @@ module ClArray = let kernel = clContext.Compile assign fun (processor: MailboxProcessor<_>) (sourceArray: ClArray<'a>) sourceIndex (targetArray: ClArray<'a>) targetIndex count -> - // check count - if count < 0 then - failwith "Count must be greater than zero" - - // check sourceIndex - if sourceIndex < 0 - && sourceIndex + count >= sourceArray.Length then - failwith "The source index does not match" - - // check targetPosition - if targetIndex < 0 - && targetIndex + count >= targetArray.Length then - failwith "The target index does not match" - if count = 0 then + // nothing to do () - // nothing to do else + if count < 0 then + failwith "Count must be greater than zero" + + if sourceIndex < 0 + && sourceIndex + count >= sourceArray.Length then + failwith "The source index does not match" + + if targetIndex < 0 + && targetIndex + count >= targetArray.Length then + failwith "The target index does not match" + let ndRange = Range1D.CreateValid(targetArray.Length, workGroupSize) @@ -646,15 +638,12 @@ module ClArray = if count = 0 then () else + if count < 0 then + failwith "Count must be greater than zero" + if firstPosition + count > targetArray.Length then failwith "The array should fit completely" - if firstPosition < 0 then - failwith "The starting position cannot be less than zero" - - if count < 0 then - failwith "The count cannot be less than zero" - let ndRange = Range1D.CreateValid(count, workGroupSize) diff --git a/src/GraphBLAS-sharp.Backend/Common/Sort/Radix.fs b/src/GraphBLAS-sharp.Backend/Common/Sort/Radix.fs index 6bc24183..5e4a88b4 100644 --- a/src/GraphBLAS-sharp.Backend/Common/Sort/Radix.fs +++ b/src/GraphBLAS-sharp.Backend/Common/Sort/Radix.fs @@ -7,8 +7,6 @@ open GraphBLAS.FSharp.Backend.Objects.ClContext open GraphBLAS.FSharp.Backend.Objects.ClCell open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions -type Indices = ClArray - module Radix = // the number of bits considered per iteration let defaultBitCount = 4 @@ -36,7 +34,7 @@ module Radix = let bitCount = mask + 1 let kernel = - <@ fun (ndRange: Range1D) length (indices: Indices) (workGroupCount: ClCell) (shift: ClCell) (globalOffsets: Indices) (localOffsets: Indices) -> + <@ fun (ndRange: Range1D) length (indices: ClArray) (workGroupCount: ClCell) (shift: ClCell) (globalOffsets: ClArray) (localOffsets: ClArray) -> let gid = ndRange.GlobalID0 let lid = ndRange.LocalID0 @@ -77,7 +75,7 @@ module Radix = let kernel = clContext.Compile kernel - fun (processor: MailboxProcessor<_>) (indices: Indices) (clWorkGroupCount: ClCell) (shift: ClCell) -> + fun (processor: MailboxProcessor<_>) (indices: ClArray) (clWorkGroupCount: ClCell) (shift: ClCell) -> let ndRange = Range1D.CreateValid(indices.Length, workGroupSize) @@ -113,7 +111,7 @@ module Radix = let scatter (clContext: ClContext) workGroupSize mask = let kernel = - <@ fun (ndRange: Range1D) length (keys: Indices) (shift: ClCell) (workGroupCount: ClCell) (globalOffsets: Indices) (localOffsets: Indices) (result: ClArray) -> + <@ fun (ndRange: Range1D) length (keys: ClArray) (shift: ClCell) (workGroupCount: ClCell) (globalOffsets: ClArray) (localOffsets: ClArray) (result: ClArray) -> let gid = ndRange.GlobalID0 let wgId = gid / workGroupSize @@ -134,7 +132,7 @@ module Radix = let kernel = clContext.Compile kernel - fun (processor: MailboxProcessor<_>) (keys: Indices) (shift: ClCell) (workGroupCount: ClCell) (globalOffset: Indices) (localOffsets: Indices) (result: ClArray) -> + fun (processor: MailboxProcessor<_>) (keys: ClArray) (shift: ClCell) (workGroupCount: ClCell) (globalOffset: ClArray) (localOffsets: ClArray) (result: ClArray) -> let ndRange = Range1D.CreateValid(keys.Length, workGroupSize) @@ -161,7 +159,7 @@ module Radix = let scatter = scatter clContext workGroupSize mask - fun (processor: MailboxProcessor<_>) (keys: Indices) -> + fun (processor: MailboxProcessor<_>) (keys: ClArray) -> if keys.Length <= 1 then copy processor DeviceOnly keys // TODO(allocation mode) else @@ -203,7 +201,7 @@ module Radix = let scatterByKey (clContext: ClContext) workGroupSize mask = let kernel = - <@ fun (ndRange: Range1D) length (keys: Indices) (values: ClArray<'a>) (shift: ClCell) (workGroupCount: ClCell) (globalOffsets: Indices) (localOffsets: Indices) (resultKeys: ClArray) (resultValues: ClArray<'a>) -> + <@ fun (ndRange: Range1D) length (keys: ClArray) (values: ClArray<'a>) (shift: ClCell) (workGroupCount: ClCell) (globalOffsets: ClArray) (localOffsets: ClArray) (resultKeys: ClArray) (resultValues: ClArray<'a>) -> let gid = ndRange.GlobalID0 let wgId = gid / workGroupSize @@ -225,7 +223,7 @@ module Radix = let kernel = clContext.Compile kernel - fun (processor: MailboxProcessor<_>) (keys: Indices) (values: ClArray<'a>) (shift: ClCell) (workGroupCount: ClCell) (globalOffset: Indices) (localOffsets: Indices) (resultKeys: ClArray) (resultValues: ClArray<'a>) -> + fun (processor: MailboxProcessor<_>) (keys: ClArray) (values: ClArray<'a>) (shift: ClCell) (workGroupCount: ClCell) (globalOffset: ClArray) (localOffsets: ClArray) (resultKeys: ClArray) (resultValues: ClArray<'a>) -> let ndRange = Range1D.CreateValid(keys.Length, workGroupSize) @@ -265,7 +263,7 @@ module Radix = let scatterByKey = scatterByKey clContext workGroupSize mask - fun (processor: MailboxProcessor<_>) allocationMode (keys: Indices) (values: ClArray<'a>) -> + fun (processor: MailboxProcessor<_>) allocationMode (keys: ClArray) (values: ClArray<'a>) -> if values.Length <> keys.Length then failwith "Mismatch of key lengths and value. Lengths must be the same" diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 1e95a3c0..e6857a20 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -109,9 +109,9 @@ module Matrix = let byRowsLazy (clContext: ClContext) workGroupSize = - let getChunkValues = ClArray.getChunk clContext workGroupSize + let getChunkValues = ClArray.sub clContext workGroupSize - let getChunkIndices = ClArray.getChunk clContext workGroupSize + let getChunkIndices = ClArray.sub clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index 69fa630b..eb60f655 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -6,7 +6,7 @@ open GraphBLAS.FSharp.Backend.Common open GraphBLAS.FSharp.Backend.Matrix open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClMatrix -open GraphBLAS.FSharp.Backend +open GraphBLAS.FSharp.Backend.Vector module Matrix = let copy (clContext: ClContext) workGroupSize = @@ -16,7 +16,7 @@ module Matrix = let copyData = ClArray.copy clContext workGroupSize let vectorCopy = - Vector.Sparse.Vector.copy clContext workGroupSize + Sparse.Vector.copy clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix<'a>) -> match matrix with diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index 214e8a49..0256ffd1 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -14,10 +14,6 @@ open GraphBLAS.FSharp.Backend.Vector.Sparse open GraphBLAS.FSharp.Backend.Objects.ClVector open GraphBLAS.FSharp.Backend.Objects.ClMatrix -type Indices = ClArray - -type Values<'a> = ClArray<'a> - module Expand = let getSegmentPointers (clContext: ClContext) workGroupSize = @@ -69,7 +65,7 @@ module Expand = let rightMatrixGather = Gather.run clContext workGroupSize - fun (processor: MailboxProcessor<_>) length (segmentsPointers: Indices) (leftMatrixRow: ClVector.Sparse<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> + fun (processor: MailboxProcessor<_>) length (segmentsPointers: ClArray) (leftMatrixRow: ClVector.Sparse<'a>) (rightMatrix: ClMatrix.CSR<'b>) -> if length = 0 then None else @@ -140,7 +136,7 @@ module Expand = let scatter = Scatter.lastOccurrence clContext workGroupSize - fun (processor: MailboxProcessor<_>) (firstValues: ClArray<'a>) (secondValues: ClArray<'b>) (columns: Indices) -> + fun (processor: MailboxProcessor<_>) (firstValues: ClArray<'a>) (secondValues: ClArray<'b>) (columns: ClArray) -> let positions = getBitmap processor DeviceOnly firstValues secondValues @@ -172,7 +168,7 @@ module Expand = let sortKeys = Radix.standardRunKeysOnly clContext workGroupSize - fun (processor: MailboxProcessor<_>) (values: ClArray<'a>) (columns: Indices) -> + fun (processor: MailboxProcessor<_>) (values: ClArray<'a>) (columns: ClArray) -> // sort by columns let sortedValues = sortByKeyValues processor DeviceOnly columns values @@ -195,7 +191,7 @@ module Expand = let idScatter = Scatter.initFirsOccurrence Map.id clContext workGroupSize - fun (processor: MailboxProcessor<_>) allocationMode (values: ClArray<'a>) (columns: Indices) -> + fun (processor: MailboxProcessor<_>) allocationMode (values: ClArray<'a>) (columns: ClArray) -> let bitmap = getUniqueBitmap processor DeviceOnly columns @@ -231,7 +227,7 @@ module Expand = let reduce = reduce clContext workGroupSize opAdd // left matrix last --- for curring - fun (processor: MailboxProcessor<_>) allocationMode (rightMatrix: ClMatrix.CSR<'b>) (leftMatrixRowsLengths: Indices) (leftMatrixRow: ClVector.Sparse<'a>) -> + fun (processor: MailboxProcessor<_>) allocationMode (rightMatrix: ClMatrix.CSR<'b>) (leftMatrixRowsLengths: ClArray) (leftMatrixRow: ClVector.Sparse<'a>) -> // TODO(sort in range) // required right matrix lengths let length, segmentPointers = diff --git a/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs index 813f52f6..c99c7e3b 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs @@ -16,7 +16,7 @@ module Vector = = let map2InPlace = - ClArray.map2Inplace clContext workGroupSize opAdd + ClArray.map2InPlace clContext workGroupSize opAdd fun (processor: MailboxProcessor<_>) (leftVector: ClArray<'a option>) (rightVector: ClArray<'b option>) (resultVector: ClArray<'c option>) -> diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs index 4501fa23..ae282f9a 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs @@ -14,42 +14,40 @@ let processor = Context.defaultContext.Queue let config = { Utils.defaultConfig with - arbitrary = [ typeof ] } + arbitrary = [ typeof ] } -let makeTestGetChunk<'a when 'a: equality> testFun (array: 'a [], startPosition: int, endPosition: int) = +let makeTestGetChunk<'a when 'a: equality> testFun (array: 'a [], startPosition, count) = if array.Length > 0 then let clArray = context.CreateClArray array let (clActual: ClArray<'a>) = - testFun processor HostInterop clArray startPosition endPosition + testFun processor HostInterop clArray startPosition count clArray.Free processor let actual = clActual.ToHostAndFree processor "Results must be the same" - |> Expect.sequenceEqual actual array.[startPosition..endPosition - 1] + |> Expect.sequenceEqual actual (Array.sub array startPosition count) -let creatTestGetChunk<'a when 'a: equality> = - ClArray.getChunk context Utils.defaultWorkGroupSize +let creatTestSub<'a when 'a: equality> = + ClArray.sub context Utils.defaultWorkGroupSize |> makeTestGetChunk<'a> |> testPropertyWithConfig config $"test on %A{typeof<'a>}" -let getChunkTests = - [ creatTestGetChunk +let subTests = + [ creatTestSub if Utils.isFloat64Available context.ClDevice then - creatTestGetChunk + creatTestSub - creatTestGetChunk - creatTestGetChunk - creatTestGetChunk ] + creatTestSub + creatTestSub + creatTestSub ] |> testList "getChunk" -let makeTestChunkBySize<'a when 'a: equality> isEqual testFun (array: 'a [], chunkSize: uint) = - - let chunkSize = int chunkSize +let makeTestChunkBySize<'a when 'a: equality> isEqual testFun (array: 'a [], chunkSize: int) = if chunkSize > 0 && array.Length > 0 then @@ -69,10 +67,14 @@ let makeTestChunkBySize<'a when 'a: equality> isEqual testFun (array: 'a [], chu "Results must be the same" |> Utils.compareChunksArrays isEqual actual expected +let chunkBySizeConfig = + { config with + arbitrary = [ typeof ] } + let creatTestChunkBySize<'a when 'a: equality> isEqual = ClArray.chunkBySize context Utils.defaultWorkGroupSize |> makeTestChunkBySize<'a> isEqual - |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + |> testPropertyWithConfig chunkBySizeConfig $"test on %A{typeof<'a>}" let chunkBySizeTests = [ creatTestChunkBySize (=) @@ -107,6 +109,6 @@ let lazyChunkBySizeTests = let allTests = testList "chunk" - [ getChunkTests + [ subTests chunkBySizeTests lazyChunkBySizeTests ] diff --git a/tests/GraphBLAS-sharp.Tests/Generators.fs b/tests/GraphBLAS-sharp.Tests/Generators.fs index 0e8eda2f..089602f4 100644 --- a/tests/GraphBLAS-sharp.Tests/Generators.fs +++ b/tests/GraphBLAS-sharp.Tests/Generators.fs @@ -923,17 +923,73 @@ module Generators = pairOfVectorsOfEqualSize <| Arb.generate |> Arb.fromGen - type ArrayAndChunkPositions() = + type Sub() = static let arrayAndChunkPosition (valuesGenerator: Gen<'a>) = gen { - let! length = Gen.sized <| fun size -> Gen.choose (1, size) + let! length = Gen.sized <| fun size -> Gen.choose (2, size + 2) + + let! array = Gen.arrayOfLength length valuesGenerator + + let! startPosition = Gen.choose (0, length - 2) + let! count = Gen.choose (1, length - startPosition - 1) + + return (array, startPosition, count) + } + + static member IntType() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member FloatType() = + arrayAndChunkPosition + <| (Arb.Default.NormalFloat() + |> Arb.toGen + |> Gen.map float) + |> Arb.fromGen + + static member Float32Type() = + arrayAndChunkPosition + <| (normalFloat32Generator <| System.Random()) + |> Arb.fromGen + + static member SByteType() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member ByteType() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member Int16Type() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member UInt16Type() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member Int32Type() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member UInt32Type() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + static member BoolType() = + arrayAndChunkPosition <| Arb.generate + |> Arb.fromGen + + type ChunkBySize() = + static let arrayAndChunkPosition (valuesGenerator: Gen<'a>) = + gen { + let! length = Gen.sized <| fun size -> Gen.choose (2, size + 2) let! array = Gen.arrayOfLength length valuesGenerator - let! endPosition = Gen.choose (1, length - 1) - let! startPosition = Gen.choose (0, endPosition - 1) + let! chunkSize = Gen.choose (1, length) - return (array, startPosition, endPosition) + return (array, chunkSize) } static member IntType() = From 2a5617bced21a116ab76fc37bb9056136231652a Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sun, 23 Apr 2023 11:36:22 +0300 Subject: [PATCH 28/44] refactor: operations early binding --- .../Algorithms/{Benchmark.fs => BFS.fs} | 4 +- .../GraphBLAS-sharp.Benchmarks.fsproj | 13 ++- .../Matrix/Map2/Map2.fs | 18 ++-- .../Matrix/SpGeMM/Expand.fs | 84 +++++++++---------- .../Matrix/SpGeMM/Masked.fs | 13 +-- .../GraphBLAS-sharp.Benchmarks/Vector/Map2.fs | 16 ++-- src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs | 10 +-- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 40 +++++---- src/GraphBLAS-sharp.Backend/Common/Gather.fs | 1 - .../Common/PrefixSum.fs | 28 +++---- .../Common/Sort/Radix.fs | 4 +- src/GraphBLAS-sharp.Backend/Common/Sum.fs | 38 ++++----- src/GraphBLAS-sharp.Backend/Matrix/COO/Map.fs | 6 +- .../Matrix/COO/Map2.fs | 6 +- .../Matrix/COO/Map2AtLeastOne.fs | 6 +- .../Matrix/COO/Matrix.fs | 4 +- src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs | 14 ++-- .../Matrix/CSR/Map2.fs | 14 ++-- .../Matrix/CSR/Map2AtLeastOne.fs | 10 +-- .../Matrix/CSR/Matrix.fs | 4 +- src/GraphBLAS-sharp.Backend/Matrix/Common.fs | 4 +- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 22 ++--- .../Matrix/SpGeMM/Expand.fs | 17 ++-- .../Matrix/SpGeMM/Masked.fs | 28 +++---- .../Vector/Dense/Vector.fs | 36 ++++---- src/GraphBLAS-sharp.Backend/Vector/SpMV.fs | 6 +- .../Vector/Sparse/Common.fs | 2 +- .../Vector/Sparse/Map2.fs | 12 +-- .../Vector/Sparse/Map2AtLeastOne.fs | 6 +- .../Vector/Sparse/Vector.fs | 6 +- src/GraphBLAS-sharp.Backend/Vector/Vector.fs | 32 +++---- tests/GraphBLAS-sharp.Tests/Algorithms/BFS.fs | 2 +- .../Common/ClArray/Choose.fs | 4 +- .../Common/ClArray/Exists.fs | 15 +--- .../Common/ClArray/Map.fs | 3 +- .../Common/ClArray/Map2.fs | 2 +- .../Common/Reduce/Reduce.fs | 2 +- .../Common/Reduce/ReduceByKey.fs | 14 ++-- .../Common/Reduce/Sum.fs | 2 +- .../Common/Scan/ByKey.fs | 2 +- .../Common/Scan/PrefixSum.fs | 2 +- tests/GraphBLAS-sharp.Tests/Matrix/Map.fs | 2 +- tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs | 2 +- .../Matrix/SpGeMM/Expand.fs | 2 +- .../Vector/AssignByMask.fs | 2 +- tests/GraphBLAS-sharp.Tests/Vector/Map2.fs | 2 +- tests/GraphBLAS-sharp.Tests/Vector/Reduce.fs | 27 ++---- tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs | 2 +- 48 files changed, 279 insertions(+), 312 deletions(-) rename benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/{Benchmark.fs => BFS.fs} (95%) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/Benchmark.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs similarity index 95% rename from benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/Benchmark.fs rename to benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs index 4711b9cc..035b9b2f 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/Benchmark.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs @@ -126,7 +126,7 @@ module WithoutTransfer = type Int() = inherit Benchmark( - (fun context -> singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), + (singleSource ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), int32, (fun _ -> Utils.nextInt (System.Random())), 0) @@ -170,7 +170,7 @@ module WithTransfer = type Int() = inherit Benchmark( - (fun context -> singleSource context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), + (singleSource ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), int32, (fun _ -> Utils.nextInt (System.Random())), 0) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj b/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj index 1a5d1710..8c455f09 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj @@ -19,13 +19,12 @@ - - - - - - - + + + + + + diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs index b2fb0bc6..2e2582f1 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/Map2/Map2.fs @@ -138,7 +138,7 @@ module WithoutTransfer = type Float32() = inherit Benchmark,float32>( - (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), + (Matrix.map2 ArithmeticOperations.float32SumOption), float32, (fun _ -> Utils.nextSingle (System.Random())), Matrix.COO @@ -150,7 +150,7 @@ module WithoutTransfer = type Bool() = inherit Benchmark,bool>( - (fun context -> Matrix.map2 context ArithmeticOperations.boolSumOption), + (Matrix.map2 ArithmeticOperations.boolSumOption), (fun _ -> true), (fun _ -> true), Matrix.COO @@ -163,7 +163,7 @@ module WithoutTransfer = type Float32() = inherit Benchmark,float32>( - (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), + (Matrix.map2 ArithmeticOperations.float32SumOption), float32, (fun _ -> Utils.nextSingle (System.Random())), (fun matrix -> Matrix.CSR matrix.ToCSR) @@ -175,7 +175,7 @@ module WithoutTransfer = type Bool() = inherit Benchmark,bool>( - (fun context -> Matrix.map2 context ArithmeticOperations.boolSumOption), + (Matrix.map2 ArithmeticOperations.boolSumOption), (fun _ -> true), (fun _ -> true), (fun matrix -> Matrix.CSR matrix.ToCSR) @@ -189,7 +189,7 @@ module WithoutTransfer = type Bool() = inherit Benchmark,bool>( - (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne), + (Matrix.map2AtLeastOne ArithmeticOperations.boolSumAtLeastOne), (fun _ -> true), (fun _ -> true), Matrix.COO @@ -201,7 +201,7 @@ module WithoutTransfer = type Float32() = inherit Benchmark,float32>( - (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne), + (Matrix.map2AtLeastOne ArithmeticOperations.float32SumAtLeastOne), float32, (fun _ -> Utils.nextSingle (System.Random())), Matrix.COO @@ -214,7 +214,7 @@ module WithoutTransfer = type Bool() = inherit Benchmark,bool>( - (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.boolSumAtLeastOne), + (Matrix.map2AtLeastOne ArithmeticOperations.boolSumAtLeastOne), (fun _ -> true), (fun _ -> true), (fun matrix -> Matrix.CSR matrix.ToCSR) @@ -226,7 +226,7 @@ module WithoutTransfer = type Float32() = inherit Benchmark,float32>( - (fun context -> Matrix.map2AtLeastOne context ArithmeticOperations.float32SumAtLeastOne), + (Matrix.map2AtLeastOne ArithmeticOperations.float32SumAtLeastOne), float32, (fun _ -> Utils.nextSingle (System.Random())), (fun matrix -> Matrix.CSR matrix.ToCSR) @@ -273,7 +273,7 @@ module WithTransfer = type Float32() = inherit Benchmark,float32>( - (fun context -> Matrix.map2 context ArithmeticOperations.float32SumOption), + (Matrix.map2 ArithmeticOperations.float32SumOption), float32, (fun _ -> Utils.nextSingle (System.Random())), Matrix.COO, diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs index a99730b9..3daf2ec4 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs @@ -104,45 +104,45 @@ type Benchmarks<'elem when 'elem : struct>( abstract member GlobalCleanup : unit -> unit -type MxmBenchmarksMultiplicationOnly<'elem when 'elem : struct>( - buildFunToBenchmark, - converter: string -> 'elem, - converterBool, - buildMatrix) = - - inherit Benchmarks<'elem>( - buildFunToBenchmark, - converter, - converterBool, - buildMatrix) - - [] - override this.GlobalSetup() = - this.ReadMatrices() - this.LoadMatricesToGPU() - - [] - override this.Benchmark() = - this.Mxm() - this.Processor.PostAndReply(Msg.MsgNotifyMe) - - [] - override this.IterationCleanup () = - this.ClearResult() - - [] - override this.GlobalCleanup () = - this.ClearInputMatrices() - - -// type Mxm4Float32WithTransposingWithZerosFilterBenchmark() = -// -// inherit MxmBenchmarksWithTransposing( -// (fun context wgSize -> Matrix.SpGeMM.expand context wgSize (fst ArithmeticOperations.float32Add) (fst ArithmeticOperations.float32Mul)), -// float32, -// (fun _ -> Utils.nextSingle (System.Random())), -// (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) -// ) -// -// static member InputMatrixProvider = -// Benchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" +module WithoutTransfer = + type Benchmark<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + converterBool, + buildMatrix) = + + inherit Benchmarks<'elem>( + buildFunToBenchmark, + converter, + converterBool, + buildMatrix) + + [] + override this.GlobalSetup() = + this.ReadMatrices() + this.LoadMatricesToGPU() + + [] + override this.Benchmark() = + this.Mxm() + this.Processor.PostAndReply(Msg.MsgNotifyMe) + + [] + override this.IterationCleanup () = + this.ClearResult() + + [] + override this.GlobalCleanup () = + this.ClearInputMatrices() + + type Float32() = + + inherit Benchmark( + Matrix.SpGeMM.expand (fst ArithmeticOperations.float32Add) (fst ArithmeticOperations.float32Mul), + float32, + (fun _ -> Utils.nextSingle (System.Random())), + (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) + ) + + static member InputMatrixProvider = + Benchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs index 8e909388..2a164021 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Masked.fs @@ -1,6 +1,7 @@ namespace GraphBLAS.FSharp.Benchmarks.Matrix.SpGeMM open System.IO +open GraphBLAS.FSharp.Backend.Quotes open GraphBLAS.FSharp.IO open BenchmarkDotNet.Attributes open Brahma.FSharp @@ -203,7 +204,7 @@ type MxmBenchmarksWithTransposing<'elem when 'elem : struct>( type Mxm4Float32MultiplicationOnlyBenchmark() = inherit MxmBenchmarksMultiplicationOnly( - Matrix.SpGeMM.masked (Operations.add ()) (Operations.mult ()), + Matrix.SpGeMM.masked (fst ArithmeticOperations.float32Add) (fst ArithmeticOperations.float32Mul), float32, (fun _ -> Utils.nextSingle (System.Random())), (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) @@ -215,7 +216,7 @@ type Mxm4Float32MultiplicationOnlyBenchmark() = type Mxm4Float32WithTransposingBenchmark() = inherit MxmBenchmarksWithTransposing( - Matrix.SpGeMM.masked (Operations.add ()) (Operations.mult ()), + Matrix.SpGeMM.masked (fst ArithmeticOperations.float32Add) (fst ArithmeticOperations.float32Mul), float32, (fun _ -> Utils.nextSingle (System.Random())), (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) @@ -227,7 +228,7 @@ type Mxm4Float32WithTransposingBenchmark() = type Mxm4BoolMultiplicationOnlyBenchmark() = inherit MxmBenchmarksMultiplicationOnly( - (Matrix.SpGeMM.masked Operations.logicalOr Operations.logicalAnd), + (Matrix.SpGeMM.masked (fst ArithmeticOperations.boolAdd) (fst ArithmeticOperations.boolMul)), (fun _ -> true), (fun _ -> true), (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) @@ -239,7 +240,7 @@ type Mxm4BoolMultiplicationOnlyBenchmark() = type Mxm4BoolWithTransposingBenchmark() = inherit MxmBenchmarksWithTransposing( - (Matrix.SpGeMM.masked Operations.logicalOr Operations.logicalAnd), + (Matrix.SpGeMM.masked (fst ArithmeticOperations.boolAdd) (fst ArithmeticOperations.boolMul)), (fun _ -> true), (fun _ -> true), (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) @@ -251,7 +252,7 @@ type Mxm4BoolWithTransposingBenchmark() = type Mxm4Float32MultiplicationOnlyWithZerosFilterBenchmark() = inherit MxmBenchmarksMultiplicationOnly( - (Matrix.SpGeMM.masked Operations.addWithFilter (Operations.mult ())), + (Matrix.SpGeMM.masked (fst ArithmeticOperations.float32Add) (fst ArithmeticOperations.float32Mul)), float32, (fun _ -> Utils.nextSingle (System.Random())), (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) @@ -263,7 +264,7 @@ type Mxm4Float32MultiplicationOnlyWithZerosFilterBenchmark() = type Mxm4Float32WithTransposingWithZerosFilterBenchmark() = inherit MxmBenchmarksWithTransposing( - Matrix.SpGeMM.masked Operations.addWithFilter (Operations.mult ()), + Matrix.SpGeMM.masked (fst ArithmeticOperations.float32Add) (fst ArithmeticOperations.float32Mul), float32, (fun _ -> Utils.nextSingle (System.Random())), (fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs index c39c207f..523f5185 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Vector/Map2.fs @@ -122,26 +122,26 @@ module WithoutTransfer = type Float() = inherit Benchmark( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), + (Vector.map2 ArithmeticOperations.floatSumOption), VectorGenerator.floatPair Sparse) type Int32() = inherit Benchmark( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), + (Vector.map2 ArithmeticOperations.intSumOption), VectorGenerator.intPair Sparse) module AtLeastOne = type Float() = inherit Benchmark( - (fun context -> Vector.map2AtLeastOne context ArithmeticOperations.floatSumAtLeastOne), + (Vector.map2AtLeastOne ArithmeticOperations.floatSumAtLeastOne), VectorGenerator.floatPair Sparse) type Int32() = inherit Benchmark( - (fun context -> Vector.map2AtLeastOne context ArithmeticOperations.intSumAtLeastOne), + (Vector.map2AtLeastOne ArithmeticOperations.intSumAtLeastOne), VectorGenerator.intPair Sparse) module WithTransfer = @@ -178,24 +178,24 @@ module WithTransfer = type Float() = inherit Benchmark( - (fun context -> Vector.map2 context ArithmeticOperations.floatSumOption), + (Vector.map2 ArithmeticOperations.floatSumOption), VectorGenerator.floatPair Sparse) type Int32() = inherit Benchmark( - (fun context -> Vector.map2 context ArithmeticOperations.intSumOption), + (Vector.map2 ArithmeticOperations.intSumOption), VectorGenerator.intPair Sparse) module AtLeastOne = type Float() = inherit Benchmark( - (fun context -> Vector.map2AtLeastOne context ArithmeticOperations.floatSumAtLeastOne), + (Vector.map2AtLeastOne ArithmeticOperations.floatSumAtLeastOne), VectorGenerator.floatPair Sparse) type Int32() = inherit Benchmark( - (fun context -> Vector.map2AtLeastOne context ArithmeticOperations.intSumAtLeastOne), + (Vector.map2AtLeastOne ArithmeticOperations.intSumAtLeastOne), VectorGenerator.intPair Sparse) diff --git a/src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs b/src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs index 2a38c25c..9896a557 100644 --- a/src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs +++ b/src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs @@ -14,14 +14,14 @@ open GraphBLAS.FSharp.Backend.Objects.ClCell module BFS = let singleSource - (clContext: ClContext) (add: Expr int option -> int option>) (mul: Expr<'a option -> int option -> int option>) + (clContext: ClContext) workGroupSize = let spMVTo = - SpMV.runTo clContext add mul workGroupSize + SpMV.runTo add mul clContext workGroupSize let zeroCreate = ClArray.zeroCreate clContext workGroupSize @@ -29,13 +29,13 @@ module BFS = let ofList = Vector.ofList clContext workGroupSize let maskComplementedTo = - Vector.map2InPlace clContext Mask.complementedOp workGroupSize + Vector.map2InPlace Mask.complementedOp clContext workGroupSize let fillSubVectorTo = - Vector.assignByMaskInPlace clContext (Convert.assignToOption Mask.assign) workGroupSize + Vector.assignByMaskInPlace (Convert.assignToOption Mask.assign) clContext workGroupSize let containsNonZero = - ClArray.exists clContext workGroupSize Predicates.isSome + ClArray.exists Predicates.isSome clContext workGroupSize fun (queue: MailboxProcessor) (matrix: ClMatrix.CSR<'a>) (source: int) -> let vertexCount = matrix.RowCount diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 9d743653..9763db01 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -10,7 +10,7 @@ open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions open GraphBLAS.FSharp.Backend.Quotes module ClArray = - let init (clContext: ClContext) workGroupSize (initializer: Expr 'a>) = + let init (initializer: Expr 'a>) (clContext: ClContext) workGroupSize = let init = <@ fun (range: Range1D) (outputBuffer: ClArray<'a>) (length: int) -> @@ -190,7 +190,7 @@ module ClArray = getUniqueBitmapLastOccurrence clContext workGroupSize let prefixSumExclude = - PrefixSum.runExcludeInplace <@ (+) @> clContext workGroupSize + PrefixSum.runExcludeInPlace <@ (+) @> clContext workGroupSize fun (processor: MailboxProcessor<_>) (inputArray: ClArray<'a>) -> @@ -210,7 +210,7 @@ module ClArray = outputArray - let exists (clContext: ClContext) workGroupSize (predicate: Expr<'a -> bool>) = + let exists (predicate: Expr<'a -> bool>) (clContext: ClContext) workGroupSize = let exists = <@ fun (ndRange: Range1D) length (vector: ClArray<'a>) (result: ClCell) -> @@ -239,7 +239,7 @@ module ClArray = result - let map<'a, 'b> (clContext: ClContext) workGroupSize (op: Expr<'a -> 'b>) = + let map<'a, 'b> (op: Expr<'a -> 'b>) (clContext: ClContext) workGroupSize = let map = <@ fun (ndRange: Range1D) lenght (inputArray: ClArray<'a>) (result: ClArray<'b>) -> @@ -267,7 +267,7 @@ module ClArray = result - let map2InPlace<'a, 'b, 'c> (clContext: ClContext) workGroupSize (map: Expr<'a -> 'b -> 'c>) = + let map2InPlace<'a, 'b, 'c> (map: Expr<'a -> 'b -> 'c>) (clContext: ClContext) workGroupSize = let kernel = <@ fun (ndRange: Range1D) length (leftArray: ClArray<'a>) (rightArray: ClArray<'b>) (resultArray: ClArray<'c>) -> @@ -294,9 +294,9 @@ module ClArray = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - let map2<'a, 'b, 'c> (clContext: ClContext) workGroupSize map = + let map2<'a, 'b, 'c> map (clContext: ClContext) workGroupSize = let map2 = - map2InPlace<'a, 'b, 'c> clContext workGroupSize map + map2InPlace<'a, 'b, 'c> map clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (leftArray: ClArray<'a>) (rightArray: ClArray<'b>) -> @@ -310,7 +310,7 @@ module ClArray = let getUniqueBitmap2General<'a when 'a: equality> getUniqueBitmap (clContext: ClContext) workGroupSize = let map = - map2 clContext workGroupSize <@ fun x y -> x ||| y @> + map2 <@ fun x y -> x ||| y @> clContext workGroupSize let firstGetBitmap = getUniqueBitmap clContext workGroupSize @@ -335,7 +335,7 @@ module ClArray = let getUniqueBitmap2LastOccurrence clContext = getUniqueBitmap2General getUniqueBitmapLastOccurrence clContext - let assignOption (clContext: ClContext) workGroupSize (op: Expr<'a -> 'b option>) = + let assignOption (op: Expr<'a -> 'b option>) (clContext: ClContext) workGroupSize = let assign = <@ fun (ndRange: Range1D) length (values: ClArray<'a>) (positions: ClArray) (result: ClArray<'b>) resultLength -> @@ -371,16 +371,15 @@ module ClArray = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - let choose<'a, 'b> (clContext: ClContext) workGroupSize (predicate: Expr<'a -> 'b option>) = + let choose<'a, 'b> (predicate: Expr<'a -> 'b option>) (clContext: ClContext) workGroupSize = let getBitmap = - map<'a, int> clContext workGroupSize - <| Map.chooseBitmap predicate + map<'a, int> (Map.chooseBitmap predicate) clContext workGroupSize let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize let assignValues = - assignOption clContext workGroupSize predicate + assignOption predicate clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (sourceValues: ClArray<'a>) -> @@ -398,7 +397,7 @@ module ClArray = result - let assignOption2 (clContext: ClContext) workGroupSize (op: Expr<'a -> 'b -> 'c option>) = + let assignOption2 (op: Expr<'a -> 'b -> 'c option>) (clContext: ClContext) workGroupSize = let assign = <@ fun (ndRange: Range1D) length (firstValues: ClArray<'a>) (secondValues: ClArray<'b>) (positions: ClArray) (result: ClArray<'c>) resultLength -> @@ -445,16 +444,15 @@ module ClArray = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - let choose2 (clContext: ClContext) workGroupSize (predicate: Expr<'a -> 'b -> 'c option>) = + let choose2 (predicate: Expr<'a -> 'b -> 'c option>) (clContext: ClContext) workGroupSize = let getBitmap = - map2<'a, 'b, int> clContext workGroupSize - <| Map.choose2Bitmap predicate + map2<'a, 'b, int> (Map.choose2Bitmap predicate) clContext workGroupSize let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize let assignValues = - assignOption2 clContext workGroupSize predicate + assignOption2 predicate clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (firstValues: ClArray<'a>) (secondValues: ClArray<'b>) -> @@ -664,7 +662,7 @@ module ClArray = Gather.runInit Map.inc clContext workGroupSize let map = - map2 clContext workGroupSize <@ fun first second -> (first, second) @> + map2 <@ fun first second -> (first, second) @> clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (values: ClArray<'a>) -> if values.Length > 1 then diff --git a/src/GraphBLAS-sharp.Backend/Common/Gather.fs b/src/GraphBLAS-sharp.Backend/Common/Gather.fs index c4f1fa19..791c88de 100644 --- a/src/GraphBLAS-sharp.Backend/Common/Gather.fs +++ b/src/GraphBLAS-sharp.Backend/Common/Gather.fs @@ -29,7 +29,6 @@ module internal Gather = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - /// /// Creates a new array obtained from positions replaced with values from the given array at these positions (indices). /// diff --git a/src/GraphBLAS-sharp.Backend/Common/PrefixSum.fs b/src/GraphBLAS-sharp.Backend/Common/PrefixSum.fs index 3e030589..09cdfb5d 100644 --- a/src/GraphBLAS-sharp.Backend/Common/PrefixSum.fs +++ b/src/GraphBLAS-sharp.Backend/Common/PrefixSum.fs @@ -144,7 +144,7 @@ module PrefixSum = && localID < workGroupSize - 1 then resultBuffer.[i] <- resultLocalBuffer.[localID + 1] @> - let private runInplace (mirror: bool) scan (opAdd: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = + let private runInPlace (opAdd: Expr<'a -> 'a -> 'a>) (mirror: bool) scan (clContext: ClContext) workGroupSize = let scan = scan opAdd clContext workGroupSize @@ -200,13 +200,13 @@ module PrefixSum = totalSum - let runExcludeInplace plus = runInplace false scanExclusive plus + let runExcludeInPlace plus = runInPlace plus false scanExclusive - let runIncludeInplace plus = runInplace false scanInclusive plus + let runIncludeInPlace plus = runInPlace plus false scanInclusive - let runBackwardsExcludeInplace plus = runInplace true scanExclusive plus + let runBackwardsExcludeInPlace plus = runInPlace plus true scanExclusive - let runBackwardsIncludeInplace plus = runInplace true scanInclusive plus + let runBackwardsIncludeInPlace plus = runInPlace plus true scanInclusive /// /// Exclude inplace prefix sum. @@ -222,13 +222,14 @@ module PrefixSum = /// > val sum = [| 4 |] /// /// + ///ClContext. ///Should be a power of 2 and greater than 1. ///Associative binary operation. ///Zero element for binary operation. - let standardExcludeInplace (clContext: ClContext) workGroupSize = + let standardExcludeInPlace (clContext: ClContext) workGroupSize = let scan = - runExcludeInplace <@ (+) @> clContext workGroupSize + runExcludeInPlace <@ (+) @> clContext workGroupSize fun (processor: MailboxProcessor<_>) (inputArray: ClArray) -> @@ -248,20 +249,21 @@ module PrefixSum = /// > val sum = [| 4 |] /// /// + ///ClContext. ///Should be a power of 2 and greater than 1. ///Associative binary operation. ///Zero element for binary operation. - let standardIncludeInplace (clContext: ClContext) workGroupSize = + let standardIncludeInPlace (clContext: ClContext) workGroupSize = let scan = - runIncludeInplace <@ (+) @> clContext workGroupSize + runIncludeInPlace <@ (+) @> clContext workGroupSize fun (processor: MailboxProcessor<_>) (inputArray: ClArray) -> scan processor inputArray 0 module ByKey = - let private sequentialSegments opWrite (clContext: ClContext) workGroupSize opAdd zero = + let private sequentialSegments opWrite opAdd zero (clContext: ClContext) workGroupSize = let kernel = <@ fun (ndRange: Range1D) lenght uniqueKeysCount (values: ClArray<'a>) (keys: ClArray) (offsets: ClArray) -> @@ -313,8 +315,7 @@ module PrefixSum = /// > val result = [| 0; 0; 1; 2; 0; 1 |] /// /// - let sequentialExclude clContext = - sequentialSegments (Map.fst ()) clContext + let sequentialExclude op = sequentialSegments (Map.fst ()) op /// /// Include scan by key. @@ -327,5 +328,4 @@ module PrefixSum = /// > val result = [| 1; 1; 2; 3; 1; 2 |] /// /// - let sequentialInclude clContext = - sequentialSegments (Map.snd ()) clContext + let sequentialInclude op = sequentialSegments (Map.snd ()) op diff --git a/src/GraphBLAS-sharp.Backend/Common/Sort/Radix.fs b/src/GraphBLAS-sharp.Backend/Common/Sort/Radix.fs index 5e4a88b4..29f9e26a 100644 --- a/src/GraphBLAS-sharp.Backend/Common/Sort/Radix.fs +++ b/src/GraphBLAS-sharp.Backend/Common/Sort/Radix.fs @@ -155,7 +155,7 @@ module Radix = let count = count clContext workGroupSize mask let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize let scatter = scatter clContext workGroupSize mask @@ -258,7 +258,7 @@ module Radix = let count = count clContext workGroupSize mask let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize let scatterByKey = scatterByKey clContext workGroupSize mask diff --git a/src/GraphBLAS-sharp.Backend/Common/Sum.fs b/src/GraphBLAS-sharp.Backend/Common/Sum.fs index d243d14e..fe7feeb2 100644 --- a/src/GraphBLAS-sharp.Backend/Common/Sum.fs +++ b/src/GraphBLAS-sharp.Backend/Common/Sum.fs @@ -55,7 +55,7 @@ module Reduce = result - let private scanSum (clContext: ClContext) (workGroupSize: int) (opAdd: Expr<'a -> 'a -> 'a>) zero = + let private scanSum (opAdd: Expr<'a -> 'a -> 'a>) (clContext: ClContext) (workGroupSize: int) zero = let subSum = SubSum.sequentialSum opAdd @@ -92,7 +92,7 @@ module Reduce = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) - let private scanToCellSum (clContext: ClContext) workGroupSize (opAdd: Expr<'a -> 'a -> 'a>) zero = + let private scanToCellSum (opAdd: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize zero = let subSum = SubSum.sequentialSum opAdd @@ -139,12 +139,12 @@ module Reduce = /// Work group size. /// Summation operation. /// Neutral element for summation. - let sum (clContext: ClContext) workGroupSize op zero = + let sum op zero (clContext: ClContext) workGroupSize = - let scan = scanSum clContext workGroupSize op zero + let scan = scanSum op clContext workGroupSize zero let scanToCell = - scanToCellSum clContext workGroupSize op zero + scanToCellSum op clContext workGroupSize zero let run = runGeneral clContext workGroupSize scan scanToCell @@ -152,9 +152,9 @@ module Reduce = fun (processor: MailboxProcessor<_>) (array: ClArray<'a>) -> run processor array let private scanReduce<'a when 'a: struct> + (opAdd: Expr<'a -> 'a -> 'a>) (clContext: ClContext) (workGroupSize: int) - (opAdd: Expr<'a -> 'a -> 'a>) = let scan = @@ -193,9 +193,9 @@ module Reduce = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) let private scanToCellReduce<'a when 'a: struct> + (opAdd: Expr<'a -> 'a -> 'a>) (clContext: ClContext) (workGroupSize: int) - (opAdd: Expr<'a -> 'a -> 'a>) = let scan = @@ -242,12 +242,12 @@ module Reduce = /// ClContext. /// Work group size. /// Reduction operation. - let reduce (clContext: ClContext) workGroupSize op = + let reduce op (clContext: ClContext) workGroupSize = - let scan = scanReduce clContext workGroupSize op + let scan = scanReduce op clContext workGroupSize let scanToCell = - scanToCellReduce clContext workGroupSize op + scanToCellReduce op clContext workGroupSize let run = runGeneral clContext workGroupSize scan scanToCell @@ -267,7 +267,7 @@ module Reduce = /// /// The length of the result must be calculated in advance. /// - let sequential (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a>) = + let sequential (reduceOp: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = let kernel = <@ fun (ndRange: Range1D) length (keys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (reducedKeys: ClArray) -> @@ -326,7 +326,7 @@ module Reduce = /// /// The length of the result must be calculated in advance. /// - let segmentSequential (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a>) = + let segmentSequential (reduceOp: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = let kernel = <@ fun (ndRange: Range1D) uniqueKeyCount keysLength (offsets: ClArray) (keys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (reducedKeys: ClArray) -> @@ -393,7 +393,7 @@ module Reduce = /// Reduces an array of values that does not exceed the size of the workgroup. /// The length of the result must be calculated in advance. /// - let oneWorkGroupSegments (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a>) = + let oneWorkGroupSegments (reduceOp: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = let kernel = <@ fun (ndRange: Range1D) length (keys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (reducedKeys: ClArray) -> @@ -482,7 +482,7 @@ module Reduce = /// /// The length of the result must be calculated in advance. /// - let segmentSequential<'a> (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a option>) = + let segmentSequential<'a> (reduceOp: Expr<'a -> 'a -> 'a option>) (clContext: ClContext) workGroupSize = let kernel = <@ fun (ndRange: Range1D) uniqueKeyCount keysLength (offsets: ClArray) (keys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (firstReducedKeys: ClArray) (resultPositions: ClArray) -> @@ -528,7 +528,7 @@ module Reduce = Scatter.lastOccurrence clContext workGroupSize let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (resultLength: int) (offsets: ClArray) (keys: ClArray) (values: ClArray<'a>) -> @@ -599,7 +599,7 @@ module Reduce = /// /// The length of the result must be calculated in advance. /// - let sequential (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a>) = + let sequential (reduceOp: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = let kernel = <@ fun (ndRange: Range1D) length (firstKeys: ClArray) (secondKeys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (firstReducedKeys: ClArray) (secondReducedKeys: ClArray) -> @@ -678,7 +678,7 @@ module Reduce = /// /// The length of the result must be calculated in advance. /// - let segmentSequential<'a> (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a>) = + let segmentSequential<'a> (reduceOp: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = let kernel = <@ fun (ndRange: Range1D) uniqueKeyCount keysLength (offsets: ClArray) (firstKeys: ClArray) (secondKeys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (firstReducedKeys: ClArray) (secondReducedKeys: ClArray) -> @@ -754,7 +754,7 @@ module Reduce = /// /// The length of the result must be calculated in advance. /// - let segmentSequential<'a> (clContext: ClContext) workGroupSize (reduceOp: Expr<'a -> 'a -> 'a option>) = + let segmentSequential<'a> (reduceOp: Expr<'a -> 'a -> 'a option>) (clContext: ClContext) workGroupSize = let kernel = <@ fun (ndRange: Range1D) uniqueKeyCount keysLength (offsets: ClArray) (firstKeys: ClArray) (secondKeys: ClArray) (values: ClArray<'a>) (reducedValues: ClArray<'a>) (firstReducedKeys: ClArray) (secondReducedKeys: ClArray) (resultPositions: ClArray) -> @@ -803,7 +803,7 @@ module Reduce = Scatter.lastOccurrence clContext workGroupSize let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (resultLength: int) (offsets: ClArray) (firstKeys: ClArray) (secondKeys: ClArray) (values: ClArray<'a>) -> diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COO/Map.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Map.fs index cc7c2f72..7700b476 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/COO/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/COO/Map.fs @@ -11,7 +11,7 @@ open GraphBLAS.FSharp.Backend.Objects.ClMatrix open GraphBLAS.FSharp.Backend.Objects.ClContext module internal Map = - let preparePositions<'a, 'b> (clContext: ClContext) workGroupSize opAdd = + let preparePositions<'a, 'b> opAdd (clContext: ClContext) workGroupSize = let preparePositions (op: Expr<'a option -> 'b option>) = <@ fun (ndRange: Range1D) rowCount columnCount valuesLength (values: ClArray<'a>) (rows: ClArray) (columns: ClArray) (resultBitmap: ClArray) (resultValues: ClArray<'b>) (resultRows: ClArray) (resultColumns: ClArray) -> @@ -84,13 +84,13 @@ module internal Map = resultBitmap, resultValues, resultRows, resultColumns let run<'a, 'b when 'a: struct and 'b: struct and 'b: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option>) + (clContext: ClContext) workGroupSize = let map = - preparePositions clContext workGroupSize opAdd + preparePositions opAdd clContext workGroupSize let setPositions = Common.setPositions<'b> clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2.fs index ee0f1b4f..9aeb400c 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2.fs @@ -12,7 +12,7 @@ open GraphBLAS.FSharp.Backend.Quotes module internal Map2 = - let preparePositions<'a, 'b, 'c> (clContext: ClContext) workGroupSize opAdd = + let preparePositions<'a, 'b, 'c> opAdd (clContext: ClContext) workGroupSize = let preparePositions (op: Expr<'a option -> 'b option -> 'c option>) = <@ fun (ndRange: Range1D) rowCount columnCount leftValuesLength rightValuesLength (leftValues: ClArray<'a>) (leftRows: ClArray) (leftColumns: ClArray) (rightValues: ClArray<'b>) (rightRows: ClArray) (rightColumn: ClArray) (resultBitmap: ClArray) (resultValues: ClArray<'c>) (resultRows: ClArray) (resultColumns: ClArray) -> @@ -95,13 +95,13 @@ module internal Map2 = ///. ///Should be a power of 2 and greater than 1. let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = let map2 = - preparePositions clContext workGroupSize opAdd + preparePositions opAdd clContext workGroupSize let setPositions = Common.setPositions<'c> clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2AtLeastOne.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2AtLeastOne.fs index 0c776f10..5768b8fd 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2AtLeastOne.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/COO/Map2AtLeastOne.fs @@ -11,8 +11,8 @@ open GraphBLAS.FSharp.Backend.Objects.ClContext module internal Map2AtLeastOne = let preparePositionsAtLeastOne<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = @@ -264,15 +264,15 @@ module internal Map2AtLeastOne = ///. ///Should be a power of 2 and greater than 1. let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = let merge = merge clContext workGroupSize let preparePositions = - preparePositionsAtLeastOne clContext opAdd workGroupSize + preparePositionsAtLeastOne opAdd clContext workGroupSize let setPositions = Common.setPositions<'c> clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs index 0ac34ba4..928a9d7a 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/COO/Matrix.fs @@ -23,7 +23,7 @@ module Matrix = workGroupSize = - Map2AtLeastOne.run clContext (Convert.atLeastOneToOption opAdd) workGroupSize + Map2AtLeastOne.run (Convert.atLeastOneToOption opAdd) clContext workGroupSize let getTuples (clContext: ClContext) workGroupSize = @@ -65,7 +65,7 @@ module Matrix = let create = ClArray.create clContext workGroupSize let scan = - PrefixSum.runBackwardsIncludeInplace <@ min @> clContext workGroupSize + PrefixSum.runBackwardsIncludeInPlace <@ min @> clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (rowIndices: ClArray) rowCount -> diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs index 018c027b..49336bf9 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs @@ -11,7 +11,7 @@ open GraphBLAS.FSharp.Backend.Objects.ClMatrix open GraphBLAS.FSharp.Backend.Objects.ClContext module internal Map = - let preparePositions<'a, 'b> (clContext: ClContext) workGroupSize op = + let preparePositions<'a, 'b> op (clContext: ClContext) workGroupSize = let preparePositions (op: Expr<'a option -> 'b option>) = <@ fun (ndRange: Range1D) rowCount columnCount (values: ClArray<'a>) (rowPointers: ClArray) (columns: ClArray) (resultBitmap: ClArray) (resultValues: ClArray<'b>) (resultRows: ClArray) (resultColumns: ClArray) -> @@ -82,13 +82,13 @@ module internal Map = resultBitmap, resultValues, resultRows, resultColumns let runToCOO<'a, 'b when 'a: struct and 'b: struct and 'b: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option>) + (clContext: ClContext) workGroupSize = let map = - preparePositions clContext workGroupSize opAdd + preparePositions opAdd clContext workGroupSize let setPositions = Common.setPositions<'b> clContext workGroupSize @@ -114,16 +114,16 @@ module internal Map = Values = resultValues } let run<'a, 'b when 'a: struct and 'b: struct and 'b: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option>) + (clContext: ClContext) workGroupSize = - let mapToCOO = runToCOO clContext opAdd workGroupSize + let mapToCOO = runToCOO opAdd clContext workGroupSize - let toCSRInplace = + let toCSRInPlace = Matrix.toCSRInPlace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> mapToCOO queue allocationMode matrix - |> toCSRInplace queue allocationMode + |> toCSRInPlace queue allocationMode diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs index 0d363dac..869d121b 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs @@ -11,7 +11,7 @@ open GraphBLAS.FSharp.Backend.Objects.ClContext open GraphBLAS.FSharp.Backend.Matrix.COO module internal Map2 = - let preparePositions<'a, 'b, 'c> (clContext: ClContext) workGroupSize opAdd = + let preparePositions<'a, 'b, 'c> opAdd (clContext: ClContext) workGroupSize = let preparePositions (op: Expr<'a option -> 'b option -> 'c option>) = <@ fun (ndRange: Range1D) rowCount columnCount (leftValues: ClArray<'a>) (leftRowPointers: ClArray) (leftColumns: ClArray) (rightValues: ClArray<'b>) (rightRowPointers: ClArray) (rightColumn: ClArray) (resultBitmap: ClArray) (resultValues: ClArray<'c>) (resultRows: ClArray) (resultColumns: ClArray) -> @@ -95,13 +95,13 @@ module internal Map2 = ///. ///Should be a power of 2 and greater than 1. let runToCOO<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = let map2 = - preparePositions clContext workGroupSize opAdd + preparePositions opAdd clContext workGroupSize let setPositions = Common.setPositions<'c> clContext workGroupSize @@ -136,16 +136,16 @@ module internal Map2 = Values = resultValues } let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = - let map2ToCOO = runToCOO clContext opAdd workGroupSize + let map2ToCOO = runToCOO opAdd clContext workGroupSize - let toCSRInplace = + let toCSRInPlace = Matrix.toCSRInPlace clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrixLeft: ClMatrix.CSR<'a>) (matrixRight: ClMatrix.CSR<'b>) -> map2ToCOO queue allocationMode matrixLeft matrixRight - |> toCSRInplace queue allocationMode + |> toCSRInPlace queue allocationMode diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs index 1f379b0b..dd24e1b5 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2AtLeastOne.fs @@ -13,8 +13,8 @@ open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions module internal Map2AtLeastOne = let preparePositions<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = @@ -283,15 +283,15 @@ module internal Map2AtLeastOne = allRows, allColumns, leftMergedValues, rightMergedValues, isEndOfRow, isLeft let runToCOO<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = let merge = merge clContext workGroupSize let preparePositions = - preparePositions clContext opAdd workGroupSize + preparePositions opAdd clContext workGroupSize let setPositions = Matrix.Common.setPositions<'c> clContext workGroupSize @@ -332,12 +332,12 @@ module internal Map2AtLeastOne = Values = resultValues } let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = - let elementwiseToCOO = runToCOO clContext opAdd workGroupSize + let elementwiseToCOO = runToCOO opAdd clContext workGroupSize let toCSRInPlace = Matrix.toCSRInPlace clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index e6857a20..7730eaa2 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -67,7 +67,7 @@ module Matrix = workGroupSize = - Map2AtLeastOne.runToCOO clContext (Convert.atLeastOneToOption opAdd) workGroupSize + Map2AtLeastOne.runToCOO (Convert.atLeastOneToOption opAdd) clContext workGroupSize let map2AtLeastOne<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> (clContext: ClContext) @@ -75,7 +75,7 @@ module Matrix = workGroupSize = - Map2AtLeastOne.run clContext (Convert.atLeastOneToOption opAdd) workGroupSize + Map2AtLeastOne.run (Convert.atLeastOneToOption opAdd) clContext workGroupSize let transposeInPlace (clContext: ClContext) workGroupSize = diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Common.fs b/src/GraphBLAS-sharp.Backend/Matrix/Common.fs index ea26fd7f..edf5efef 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Common.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Common.fs @@ -17,7 +17,7 @@ module Common = Scatter.lastOccurrence clContext workGroupSize let sum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (allRows: ClArray) (allColumns: ClArray) (allValues: ClArray<'a>) (positions: ClArray) -> @@ -60,7 +60,7 @@ module Common = ClArray.zeroCreate clContext workGroupSize let scan = - PrefixSum.runIncludeInplace <@ max @> clContext workGroupSize + PrefixSum.runIncludeInPlace <@ max @> clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (rowPointers: ClArray) nnz rowCount -> diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index eb60f655..f3b39641 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -257,12 +257,12 @@ module Matrix = |> ClMatrix.LIL | ClMatrix.LIL _ -> copy processor allocationMode matrix - let map (clContext: ClContext) (opAdd: Expr<'a option -> 'b option>) workGroupSize = + let map (opAdd: Expr<'a option -> 'b option>) (clContext: ClContext) workGroupSize = let mapCOO = - COO.Matrix.map clContext opAdd workGroupSize + COO.Matrix.map opAdd clContext workGroupSize let mapCSR = - CSR.Matrix.map clContext opAdd workGroupSize + CSR.Matrix.map opAdd clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode matrix -> match matrix with @@ -273,12 +273,12 @@ module Matrix = |> ClMatrix.CSC | _ -> failwith "Not yet implemented" - let map2 (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) workGroupSize = + let map2 (opAdd: Expr<'a option -> 'b option -> 'c option>) (clContext: ClContext) workGroupSize = let map2COO = - COO.Matrix.map2 clContext opAdd workGroupSize + COO.Matrix.map2 opAdd clContext workGroupSize let map2CSR = - CSR.Matrix.map2 clContext opAdd workGroupSize + CSR.Matrix.map2 opAdd clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode matrix1 matrix2 -> match matrix1, matrix2 with @@ -294,7 +294,7 @@ module Matrix = |> ClMatrix.CSC | _ -> failwith "Matrix formats are not matching" - let map2AtLeastOne (clContext: ClContext) (opAdd: Expr -> 'c option>) workGroupSize = + let map2AtLeastOne (opAdd: Expr -> 'c option>) (clContext: ClContext) workGroupSize = let COOElementwise = COO.Matrix.map2AtLeastOne clContext opAdd workGroupSize @@ -315,7 +315,7 @@ module Matrix = |> ClMatrix.CSC | _ -> failwith "Matrix formats are not matching" - let map2AtLeastOneToCOO (clContext: ClContext) (opAdd: Expr -> 'c option>) workGroupSize = + let map2AtLeastOneToCOO (opAdd: Expr -> 'c option>) (clContext: ClContext) workGroupSize = let COOElementwise = COO.Matrix.map2AtLeastOne clContext opAdd workGroupSize @@ -415,7 +415,7 @@ module Matrix = = let runCSRnCSC = - SpGeMM.Masked.run clContext workGroupSize opAdd opMul + SpGeMM.Masked.run opAdd opMul clContext workGroupSize fun (queue: MailboxProcessor<_>) (matrix1: ClMatrix<'a>) (matrix2: ClMatrix<'b>) (mask: ClMatrix<_>) -> match matrix1, matrix2, mask with @@ -423,10 +423,10 @@ module Matrix = | _ -> failwith "Matrix formats are not matching" let expand - (clContext: ClContext) - workGroupSize (opAdd: Expr<'c -> 'c -> 'c option>) (opMul: Expr<'a -> 'b -> 'c option>) + (clContext: ClContext) + workGroupSize = let run = diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index 0256ffd1..7041ac33 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -20,7 +20,7 @@ module Expand = let gather = Gather.run clContext workGroupSize let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize fun (processor: MailboxProcessor<_>) (leftMatrixRow: ClVector.Sparse<'a>) (rightMatrixRowsLengths: ClArray) -> @@ -49,14 +49,14 @@ module Expand = ClArray.zeroCreate clContext workGroupSize let maxPrefixSum = - PrefixSum.runIncludeInplace <@ max @> clContext workGroupSize + PrefixSum.runIncludeInPlace <@ max @> clContext workGroupSize let create = ClArray.create clContext workGroupSize let gather = Gather.run clContext workGroupSize let segmentPrefixSum = - PrefixSum.ByKey.sequentialInclude clContext workGroupSize <@ (+) @> 0 + PrefixSum.ByKey.sequentialInclude <@ (+) @> 0 clContext workGroupSize let removeDuplicates = ClArray.removeDuplications clContext workGroupSize @@ -124,14 +124,13 @@ module Expand = let multiply (clContext: ClContext) workGroupSize (predicate: Expr<'a -> 'b -> 'c option>) = let getBitmap = - ClArray.map2<'a, 'b, int> clContext workGroupSize - <| Map.choose2Bitmap predicate + ClArray.map2<'a, 'b, int> (Map.choose2Bitmap predicate) clContext workGroupSize let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize let assignValues = - ClArray.assignOption2 clContext workGroupSize predicate + ClArray.assignOption2 predicate clContext workGroupSize let scatter = Scatter.lastOccurrence clContext workGroupSize @@ -180,13 +179,13 @@ module Expand = let reduce (clContext: ClContext) workGroupSize opAdd = let reduce = - Reduce.ByKey.Option.segmentSequential clContext workGroupSize opAdd + Reduce.ByKey.Option.segmentSequential opAdd clContext workGroupSize let getUniqueBitmap = ClArray.getUniqueBitmapLastOccurrence clContext workGroupSize let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize let idScatter = Scatter.initFirsOccurrence Map.id clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Masked.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Masked.fs index c1b0d2a9..700018c3 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Masked.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Masked.fs @@ -10,10 +10,10 @@ open GraphBLAS.FSharp.Backend.Objects.ClCell module internal Masked = let private calculate - (context: ClContext) - workGroupSize (opAdd: Expr<'c -> 'c -> 'c option>) (opMul: Expr<'a -> 'b -> 'c option>) + (context: ClContext) + workGroupSize = let run = @@ -142,14 +142,14 @@ module internal Masked = values, bitmap let run - (context: ClContext) - workGroupSize (opAdd: Expr<'c -> 'c -> 'c option>) (opMul: Expr<'a -> 'b -> 'c option>) + (context: ClContext) + workGroupSize = let calculate = - calculate context workGroupSize opAdd opMul + calculate opAdd opMul context workGroupSize let scatter = Scatter.lastOccurrence context workGroupSize @@ -157,8 +157,8 @@ module internal Masked = let scatterData = Scatter.lastOccurrence context workGroupSize - let scanInplace = - PrefixSum.standardExcludeInplace context workGroupSize + let scanInPlace = + PrefixSum.standardExcludeInPlace context workGroupSize fun (queue: MailboxProcessor<_>) (matrixLeft: ClMatrix.CSR<'a>) (matrixRight: ClMatrix.CSC<'b>) (mask: ClMatrix.COO<_>) -> @@ -166,15 +166,15 @@ module internal Masked = calculate queue matrixLeft matrixRight mask let resultNNZ = - (scanInplace queue positions).ToHostAndFree(queue) + (scanInPlace queue positions).ToHostAndFree(queue) let resultRows = context.CreateClArray resultNNZ - let resultCols = context.CreateClArray resultNNZ - let resultVals = context.CreateClArray<'c> resultNNZ + let resultColumns = context.CreateClArray resultNNZ + let resultValues = context.CreateClArray<'c> resultNNZ scatter queue positions mask.Rows resultRows - scatter queue positions mask.Columns resultCols - scatterData queue positions values resultVals + scatter queue positions mask.Columns resultColumns + scatterData queue positions values resultValues queue.Post(Msg.CreateFreeMsg<_>(values)) queue.Post(Msg.CreateFreeMsg<_>(positions)) @@ -183,5 +183,5 @@ module internal Masked = RowCount = matrixLeft.RowCount ColumnCount = matrixRight.ColumnCount Rows = resultRows - Columns = resultCols - Values = resultVals } + Columns = resultColumns + Values = resultValues } diff --git a/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs index c99c7e3b..756de4bb 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs @@ -10,13 +10,13 @@ open GraphBLAS.FSharp.Backend.Objects.ClCell module Vector = let map2InPlace<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = let map2InPlace = - ClArray.map2InPlace clContext workGroupSize opAdd + ClArray.map2InPlace opAdd clContext workGroupSize fun (processor: MailboxProcessor<_>) (leftVector: ClArray<'a option>) (rightVector: ClArray<'b option>) (resultVector: ClArray<'c option>) -> @@ -24,25 +24,25 @@ module Vector = let map2<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> - (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = let map2 = - ClArray.map2 clContext workGroupSize opAdd + ClArray.map2 opAdd clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (leftVector: ClArray<'a option>) (rightVector: ClArray<'b option>) -> map2 processor allocationMode leftVector rightVector - let map2AtLeastOne clContext op workGroupSize = - map2 clContext (Convert.atLeastOneToOption op) workGroupSize + let map2AtLeastOne op clContext workGroupSize = + map2 (Convert.atLeastOneToOption op) clContext workGroupSize let assignByMaskInPlace<'a, 'b when 'a: struct and 'b: struct> - (clContext: ClContext) (maskOp: Expr<'a option -> 'b option -> 'a -> 'a option>) + (clContext: ClContext) workGroupSize = @@ -71,13 +71,13 @@ module Vector = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) let assignByMask<'a, 'b when 'a: struct and 'b: struct> - (clContext: ClContext) (maskOp: Expr<'a option -> 'b option -> 'a -> 'a option>) + (clContext: ClContext) workGroupSize = let assignByMask = - assignByMaskInPlace clContext maskOp workGroupSize + assignByMaskInPlace maskOp clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (leftVector: ClArray<'a option>) (maskVector: ClArray<'b option>) (value: ClCell<'a>) -> let resultVector = @@ -96,18 +96,16 @@ module Vector = Scatter.lastOccurrence clContext workGroupSize let getBitmap = - ClArray.map clContext workGroupSize - <| Map.option 1 0 + ClArray.map (Map.option 1 0) clContext workGroupSize let prefixSum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize let allIndices = - ClArray.init clContext workGroupSize Map.id + ClArray.init Map.id clContext workGroupSize let allValues = - ClArray.map clContext workGroupSize - <| Map.optionToValueOrZero Unchecked.defaultof<'a> + ClArray.map (Map.optionToValueOrZero Unchecked.defaultof<'a>) clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (vector: ClArray<'a option>) -> @@ -145,16 +143,16 @@ module Vector = Values = resultValues Size = vector.Length } - let reduce<'a when 'a: struct> (clContext: ClContext) workGroupSize (opAdd: Expr<'a -> 'a -> 'a>) = + let reduce<'a when 'a: struct> (opAdd: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = let choose = - ClArray.choose clContext workGroupSize Map.id + ClArray.choose Map.id clContext workGroupSize let reduce = - Reduce.reduce clContext workGroupSize opAdd + Reduce.reduce opAdd clContext workGroupSize let containsNonZero = - ClArray.exists clContext workGroupSize Predicates.isSome + ClArray.exists Predicates.isSome clContext workGroupSize fun (processor: MailboxProcessor<_>) (vector: ClArray<'a option>) -> diff --git a/src/GraphBLAS-sharp.Backend/Vector/SpMV.fs b/src/GraphBLAS-sharp.Backend/Vector/SpMV.fs index 4de83189..46895b0c 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/SpMV.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/SpMV.fs @@ -8,9 +8,9 @@ open GraphBLAS.FSharp.Backend.Objects.ClContext module SpMV = let runTo - (clContext: ClContext) (add: Expr<'c option -> 'c option -> 'c option>) (mul: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = @@ -144,12 +144,12 @@ module SpMV = queue.Post(Msg.CreateFreeMsg intermediateArray) let run - (clContext: ClContext) (add: Expr<'c option -> 'c option -> 'c option>) (mul: Expr<'a option -> 'b option -> 'c option>) + (clContext: ClContext) workGroupSize = - let runTo = runTo clContext add mul workGroupSize + let runTo = runTo add mul clContext workGroupSize fun (queue: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) (vector: ClArray<'b option>) -> diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Common.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Common.fs index d44c5a4b..93b809c1 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Common.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Common.fs @@ -10,7 +10,7 @@ module internal Common = let setPositions<'a when 'a: struct> (clContext: ClContext) workGroupSize = let sum = - PrefixSum.standardExcludeInplace clContext workGroupSize + PrefixSum.standardExcludeInPlace clContext workGroupSize let valuesScatter = Scatter.lastOccurrence clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2.fs index 851b28c1..adf88833 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2.fs @@ -9,7 +9,7 @@ open GraphBLAS.FSharp.Backend.Objects.ClContext open GraphBLAS.FSharp.Backend.Quotes module internal Map2 = - let private preparePositions<'a, 'b, 'c> (clContext: ClContext) workGroupSize opAdd = + let private preparePositions<'a, 'b, 'c> opAdd (clContext: ClContext) workGroupSize = let preparePositions (op: Expr<'a option -> 'b option -> 'c option>) = <@ fun (ndRange: Range1D) length leftValuesLength rightValuesLength (leftValues: ClArray<'a>) (leftIndices: ClArray) (rightValues: ClArray<'b>) (rightIndices: ClArray) (resultBitmap: ClArray) (resultValues: ClArray<'c>) (resultIndices: ClArray) -> @@ -72,10 +72,10 @@ module internal Map2 = resultBitmap, resultValues, resultIndices - let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> (clContext: ClContext) op workGroupSize = + let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> op (clContext: ClContext) workGroupSize = let prepare = - preparePositions<'a, 'b, 'c> clContext workGroupSize op + preparePositions<'a, 'b, 'c> op clContext workGroupSize let setPositions = Common.setPositions clContext workGroupSize @@ -104,8 +104,8 @@ module internal Map2 = Size = max leftVector.Size rightVector.Size } let private preparePositionsAssignByMask<'a, 'b when 'a: struct and 'b: struct> - (clContext: ClContext) op + (clContext: ClContext) workGroupSize = @@ -175,10 +175,10 @@ module internal Map2 = ///. ///. ///Should be a power of 2 and greater than 1. - let assignByMask<'a, 'b when 'a: struct and 'b: struct> (clContext: ClContext) op workGroupSize = + let assignByMask<'a, 'b when 'a: struct and 'b: struct> op (clContext: ClContext) workGroupSize = let prepare = - preparePositionsAssignByMask clContext op workGroupSize + preparePositionsAssignByMask op clContext workGroupSize let setPositions = Common.setPositions clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2AtLeastOne.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2AtLeastOne.fs index 8c346b87..171ab203 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2AtLeastOne.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Map2AtLeastOne.fs @@ -170,8 +170,8 @@ module internal Map2AtLeastOne = allIndices, firstResultValues, secondResultValues, isLeftBitmap let private preparePositions<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> - (clContext: ClContext) op + (clContext: ClContext) workGroupSize = @@ -225,12 +225,12 @@ module internal Map2AtLeastOne = ///. ///. ///Should be a power of 2 and greater than 1. - let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> (clContext: ClContext) op workGroupSize = + let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> op (clContext: ClContext) workGroupSize = let merge = merge clContext workGroupSize let prepare = - preparePositions<'a, 'b, 'c> clContext op workGroupSize + preparePositions<'a, 'b, 'c> op clContext workGroupSize let setPositions = Common.setPositions clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs index 75cb4d7e..8d0be005 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs @@ -22,8 +22,8 @@ module Vector = let map2 = Map2.run - let map2AtLeastOne (clContext: ClContext) opAdd workGroupSize allocationMode = - Map2AtLeastOne.run clContext (Convert.atLeastOneToOption opAdd) workGroupSize allocationMode + let map2AtLeastOne opAdd (clContext: ClContext) workGroupSize = + Map2AtLeastOne.run (Convert.atLeastOneToOption opAdd) clContext workGroupSize let assignByMask = Map2.assignByMask @@ -62,7 +62,7 @@ module Vector = resultVector - let reduce<'a when 'a: struct> (clContext: ClContext) workGroupSize (opAdd: Expr<'a -> 'a -> 'a>) = + let reduce<'a when 'a: struct> (opAdd: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = let reduce = Reduce.reduce clContext workGroupSize opAdd diff --git a/src/GraphBLAS-sharp.Backend/Vector/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Vector.fs index 97a1ca08..9dd9fc6b 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Vector.fs @@ -119,12 +119,12 @@ module Vector = ClVector.Dense <| toDense processor allocationMode vector - let map2 (clContext: ClContext) (opAdd: Expr<'a option -> 'b option -> 'c option>) workGroupSize = + let map2 (opAdd: Expr<'a option -> 'b option -> 'c option>) (clContext: ClContext) workGroupSize = let map2Dense = - Dense.Vector.map2 clContext opAdd workGroupSize + Dense.Vector.map2 opAdd clContext workGroupSize let map2Sparse = - Sparse.Vector.map2 clContext opAdd workGroupSize + Sparse.Vector.map2 opAdd clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) -> match leftVector, rightVector with @@ -136,12 +136,12 @@ module Vector = <| map2Sparse processor allocationMode left right | _ -> failwith "Vector formats are not matching." - let map2AtLeastOne (clContext: ClContext) (opAdd: Expr -> 'c option>) workGroupSize = + let map2AtLeastOne (opAdd: Expr -> 'c option>) (clContext: ClContext) workGroupSize = let map2Sparse = - Sparse.Vector.map2AtLeastOne clContext opAdd workGroupSize + Sparse.Vector.map2AtLeastOne opAdd clContext workGroupSize let map2Dense = - Dense.Vector.map2AtLeastOne clContext opAdd workGroupSize + Dense.Vector.map2AtLeastOne opAdd clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (leftVector: ClVector<'a>) (rightVector: ClVector<'b>) -> match leftVector, rightVector with @@ -153,13 +153,13 @@ module Vector = <| map2Dense processor allocationMode left right | _ -> failwith "Vector formats are not matching." - let private assignByMaskGeneral<'a, 'b when 'a: struct and 'b: struct> (clContext: ClContext) op workGroupSize = + let private assignByMaskGeneral<'a, 'b when 'a: struct and 'b: struct> op (clContext: ClContext) workGroupSize = let sparseFillVector = - Sparse.Vector.assignByMask clContext op workGroupSize + Sparse.Vector.assignByMask op clContext workGroupSize let denseFillVector = - Dense.Vector.assignByMask clContext op workGroupSize + Dense.Vector.assignByMask op clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (vector: ClVector<'a>) (mask: ClVector<'b>) (value: ClCell<'a>) -> match vector, mask with @@ -171,18 +171,18 @@ module Vector = <| denseFillVector processor allocationMode vector mask value | _ -> failwith "Vector formats are not matching." - let assignByMask<'a, 'b when 'a: struct and 'b: struct> clContext op workGroupSize = - assignByMaskGeneral<'a, 'b> clContext (Convert.assignToOption op) workGroupSize + let assignByMask<'a, 'b when 'a: struct and 'b: struct> op clContext workGroupSize = + assignByMaskGeneral<'a, 'b> (Convert.assignToOption op) clContext workGroupSize - let assignByMaskComplemented<'a, 'b when 'a: struct and 'b: struct> clContext op workGroupSize = - assignByMaskGeneral<'a, 'b> clContext (Convert.assignComplementedToOption op) workGroupSize + let assignByMaskComplemented<'a, 'b when 'a: struct and 'b: struct> op clContext workGroupSize = + assignByMaskGeneral<'a, 'b> (Convert.assignComplementedToOption op) clContext workGroupSize - let reduce (clContext: ClContext) workGroupSize (opAdd: Expr<'a -> 'a -> 'a>) = + let reduce (opAdd: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = let sparseReduce = - Sparse.Vector.reduce clContext workGroupSize opAdd + Sparse.Vector.reduce opAdd clContext workGroupSize let denseReduce = - Dense.Vector.reduce clContext workGroupSize opAdd + Dense.Vector.reduce opAdd clContext workGroupSize fun (processor: MailboxProcessor<_>) (vector: ClVector<'a>) -> match vector with diff --git a/tests/GraphBLAS-sharp.Tests/Algorithms/BFS.fs b/tests/GraphBLAS-sharp.Tests/Algorithms/BFS.fs index 4c7f76d6..a85d8424 100644 --- a/tests/GraphBLAS-sharp.Tests/Algorithms/BFS.fs +++ b/tests/GraphBLAS-sharp.Tests/Algorithms/BFS.fs @@ -23,9 +23,9 @@ let testFixtures (testContext: TestContext) = let bfs = Algorithms.BFS.singleSource - context ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption + context workGroupSize testPropertyWithConfig config testName diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Choose.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Choose.fs index 7c1cfdea..7fa142dd 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Choose.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Choose.fs @@ -41,7 +41,7 @@ let createTest<'a, 'b> testContext mapFun mapFunQ isEqual = let context = testContext.ClContext let choose = - ClArray.choose context workGroupSize mapFunQ + ClArray.choose mapFunQ context workGroupSize makeTest<'a, 'b> testContext choose mapFun isEqual |> testPropertyWithConfig config $"test on %A{typeof<'a>} -> %A{typeof<'b>}" @@ -83,7 +83,7 @@ let makeTest2 isEqual opMap testFun (firstArray: 'a [], secondArray: 'a []) = let createTest2 (isEqual: 'a -> 'a -> bool) (opMapQ, opMap) testFun = let testFun = - testFun context Utils.defaultWorkGroupSize opMapQ + testFun opMapQ context Utils.defaultWorkGroupSize makeTest2 isEqual opMap testFun |> testPropertyWithConfig config $"test on %A{typeof<'a>}" diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Exists.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Exists.fs index dbbb3415..ff061074 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Exists.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Exists.fs @@ -8,6 +8,7 @@ open Context open Brahma.FSharp open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Quotes +open GraphBLAS.FSharp.Backend.Objects.ClCell let logger = Log.create "ClArray.containsNonZero.Tests" @@ -28,17 +29,7 @@ let correctnessGenericTest<'a when 'a: struct and 'a: equality> isZero exists (a let result = match vector.ToDevice context with - | ClVector.Dense clArray -> - let resultCell = exists q clArray - let result = Array.zeroCreate 1 - - let res = - q.PostAndReply(fun ch -> Msg.CreateToHostMsg<_>(resultCell, result, ch)) - - q.Post(Msg.CreateFreeMsg<_>(resultCell)) - - res.[0] - + | ClVector.Dense clArray -> (exists q clArray: ClCell<_>).ToHostAndFree q | _ -> failwith "Unsupported vector format" $"The results should be the same, vector : {vector}" @@ -46,7 +37,7 @@ let correctnessGenericTest<'a when 'a: struct and 'a: equality> isZero exists (a let createTest<'a when 'a: struct and 'a: equality> isEqual zero = let exists = - ClArray.exists context wgSize Predicates.isSome + ClArray.exists Predicates.isSome context wgSize [ correctnessGenericTest<'a> (isEqual zero) exists |> testPropertyWithConfig config "FSCheck data" diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map.fs index be501e41..a49ea492 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map.fs @@ -44,8 +44,7 @@ let createTest<'a when 'a: equality> (testContext: TestContext) (zero: 'a) isEqu let context = testContext.ClContext let map = - ClArray.map context wgSize - <| Map.optionToValueOrZero zero + ClArray.map (Map.optionToValueOrZero zero) context wgSize makeTest testContext map zero isEqual |> testPropertyWithConfig config $"Correctness on {typeof<'a>}" diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map2.fs b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map2.fs index c1ab2af8..ae4342b8 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map2.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map2.fs @@ -42,7 +42,7 @@ let createTest<'a when 'a: equality> (testContext: TestContext) isEqual hostMapF let context = testContext.ClContext - let map = ClArray.map2 context wgSize mapFunQ + let map = ClArray.map2 mapFunQ context wgSize makeTest<'a> testContext map hostMapFun isEqual |> testPropertyWithConfig config $"Correctness on {typeof<'a>}" diff --git a/tests/GraphBLAS-sharp.Tests/Common/Reduce/Reduce.fs b/tests/GraphBLAS-sharp.Tests/Common/Reduce/Reduce.fs index d6d47640..3500e639 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/Reduce/Reduce.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/Reduce/Reduce.fs @@ -52,7 +52,7 @@ let makeTest (reduce: MailboxProcessor<_> -> ClArray<'a> -> ClCell<'a>) plus zer |> Expect.equal actualSum expectedSum let testFixtures plus plusQ zero name = - let reduce = Reduce.reduce context wgSize plusQ + let reduce = Reduce.reduce plusQ context wgSize makeTest reduce plus zero |> testPropertyWithConfig config $"Correctness on %s{name}" diff --git a/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs b/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs index 75e0b9dd..772eafb5 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs @@ -63,7 +63,7 @@ let makeTest isEqual reduce reduceOp (arrayAndKeys: (int * 'a) []) = let createTestSequential<'a> (isEqual: 'a -> 'a -> bool) reduceOp reduceOpQ = let reduce = - Reduce.ByKey.sequential context Utils.defaultWorkGroupSize reduceOpQ + Reduce.ByKey.sequential reduceOpQ context Utils.defaultWorkGroupSize makeTest isEqual reduce reduceOp |> testPropertyWithConfig config $"test on {typeof<'a>}" @@ -97,7 +97,7 @@ let sequentialTest = let createTestOneWorkGroup<'a> (isEqual: 'a -> 'a -> bool) reduceOp reduceOpQ = let reduce = - Reduce.ByKey.oneWorkGroupSegments context Utils.defaultWorkGroupSize reduceOpQ + Reduce.ByKey.oneWorkGroupSegments reduceOpQ context Utils.defaultWorkGroupSize makeTest isEqual reduce reduceOp |> testPropertyWithConfig @@ -166,7 +166,7 @@ let makeTestSequentialSegments isEqual reduce reduceOp (valuesAndKeys: (int * 'a let createTestSequentialSegments<'a> (isEqual: 'a -> 'a -> bool) reduceOp reduceOpQ = let reduce = - Reduce.ByKey.segmentSequential context Utils.defaultWorkGroupSize reduceOpQ + Reduce.ByKey.segmentSequential reduceOpQ context Utils.defaultWorkGroupSize makeTestSequentialSegments isEqual reduce reduceOp |> testPropertyWithConfig { config with startSize = 1000 } $"test on {typeof<'a>}" @@ -252,7 +252,7 @@ let makeTest2D isEqual reduce reduceOp (array: (int * int * 'a) []) = let createTestSequential2D<'a> (isEqual: 'a -> 'a -> bool) reduceOp reduceOpQ = let reduce = - Reduce.ByKey2D.sequential context Utils.defaultWorkGroupSize reduceOpQ + Reduce.ByKey2D.sequential reduceOpQ context Utils.defaultWorkGroupSize makeTest2D isEqual reduce reduceOp |> testPropertyWithConfig @@ -331,7 +331,7 @@ let makeTestSequentialSegments2D isEqual reduce reduceOp (array: (int * int * 'a let createTestSequentialSegments2D<'a> (isEqual: 'a -> 'a -> bool) reduceOp reduceOpQ = let reduce = - Reduce.ByKey2D.segmentSequential context Utils.defaultWorkGroupSize reduceOpQ + Reduce.ByKey2D.segmentSequential reduceOpQ context Utils.defaultWorkGroupSize makeTestSequentialSegments2D isEqual reduce reduceOp |> testPropertyWithConfig @@ -430,7 +430,7 @@ let testOption<'a> isEqual reduceOp testFun (array: (int * 'a) []) = |> checkResultOption isEqual keys values reduceOp let createTestOption (isEqual: 'a -> 'a -> bool) (reduceOpQ, reduceOp) = - Reduce.ByKey.Option.segmentSequential context Utils.defaultWorkGroupSize reduceOpQ + Reduce.ByKey.Option.segmentSequential reduceOpQ context Utils.defaultWorkGroupSize |> testOption<'a> isEqual reduceOp |> testPropertyWithConfig { config with @@ -518,7 +518,7 @@ let test2DOption<'a> isEqual reduceOp reduce (array: (int * int * 'a) []) = |> checkResult2DOption isEqual firstKeys secondKeys values reduceOp let createTest2DOption (isEqual: 'a -> 'a -> bool) (reduceOpQ, reduceOp) = - Reduce.ByKey2D.Option.segmentSequential context Utils.defaultWorkGroupSize reduceOpQ + Reduce.ByKey2D.Option.segmentSequential reduceOpQ context Utils.defaultWorkGroupSize |> test2DOption<'a> isEqual reduceOp |> testPropertyWithConfig { config with diff --git a/tests/GraphBLAS-sharp.Tests/Common/Reduce/Sum.fs b/tests/GraphBLAS-sharp.Tests/Common/Reduce/Sum.fs index e094d572..977b085e 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/Reduce/Sum.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/Reduce/Sum.fs @@ -51,7 +51,7 @@ let makeTest plus zero sum (array: 'a []) = |> Expect.equal actualSum expectedSum let testFixtures plus (plusQ: Expr<'a -> 'a -> 'a>) zero name = - Reduce.sum context wgSize plusQ zero + Reduce.sum plusQ zero context wgSize |> makeTest plus zero |> testPropertyWithConfig config (sprintf "Correctness on %s" name) diff --git a/tests/GraphBLAS-sharp.Tests/Common/Scan/ByKey.fs b/tests/GraphBLAS-sharp.Tests/Common/Scan/ByKey.fs index 1cb81709..a89b5f36 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/Scan/ByKey.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/Scan/ByKey.fs @@ -53,7 +53,7 @@ let createTest (zero: 'a) opAddQ opAdd isEqual deviceScan hostScan = let hostScan = hostScan zero opAdd let deviceScan = - deviceScan context Utils.defaultWorkGroupSize opAddQ zero + deviceScan opAddQ zero context Utils.defaultWorkGroupSize makeTestSequentialSegments isEqual hostScan deviceScan |> testPropertyWithConfig Utils.defaultConfig $"test on {typeof<'a>}" diff --git a/tests/GraphBLAS-sharp.Tests/Common/Scan/PrefixSum.fs b/tests/GraphBLAS-sharp.Tests/Common/Scan/PrefixSum.fs index 734b96f9..fbf12398 100644 --- a/tests/GraphBLAS-sharp.Tests/Common/Scan/PrefixSum.fs +++ b/tests/GraphBLAS-sharp.Tests/Common/Scan/PrefixSum.fs @@ -61,7 +61,7 @@ let makeTest plus zero isEqual scan (array: 'a []) = |> Tests.Utils.compareArrays isEqual actual expected let testFixtures plus plusQ zero isEqual name = - PrefixSum.runIncludeInplace plusQ context wgSize + PrefixSum.runIncludeInPlace plusQ context wgSize |> makeTest plus zero isEqual |> testPropertyWithConfig config $"Correctness on %s{name}" diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Map.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Map.fs index cb5b7e51..508f7d75 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Map.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Map.fs @@ -98,7 +98,7 @@ let createTestMap case (zero: 'a) (constant: 'a) binOp isEqual opQ = let unaryOp = binOp constant let unaryOpQ = opQ zero constant - let map = Matrix.map context unaryOpQ wgSize + let map = Matrix.map unaryOpQ context wgSize let toCOO = Matrix.toCOO context wgSize diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs index 3d179e21..da0fd3c3 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs @@ -101,7 +101,7 @@ let creatTestMap2Add case (zero: 'a) add isEqual addQ map2 = let context = case.TestContext.ClContext let q = case.TestContext.Queue - let map2 = map2 context addQ wgSize + let map2 = map2 addQ context wgSize let toCOO = Matrix.toCOO context wgSize diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs index 69cda013..e187d118 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs @@ -218,7 +218,7 @@ let makeGeneralTest<'a when 'a: struct> zero isEqual opMul opAdd testFun (leftAr | _ -> failwith "Matrix format are not matching" let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = - testFun context Utils.defaultWorkGroupSize opAddQ opMulQ + testFun opAddQ opMulQ context Utils.defaultWorkGroupSize |> makeGeneralTest<'a> zero isEqual opMul opAdd |> testPropertyWithConfig { config with diff --git a/tests/GraphBLAS-sharp.Tests/Vector/AssignByMask.fs b/tests/GraphBLAS-sharp.Tests/Vector/AssignByMask.fs index c4193eb3..50dab7c2 100644 --- a/tests/GraphBLAS-sharp.Tests/Vector/AssignByMask.fs +++ b/tests/GraphBLAS-sharp.Tests/Vector/AssignByMask.fs @@ -96,7 +96,7 @@ let createTest case (isZero: 'a -> bool) isComplemented fill = let context = case.TestContext.ClContext let getCorrectnessTestName = getCorrectnessTestName case - let fill = fill context Mask.assign wgSize + let fill = fill Mask.assign context wgSize let toCoo = Vector.toDense context wgSize diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Map2.fs b/tests/GraphBLAS-sharp.Tests/Vector/Map2.fs index cfb16b53..fee9103a 100644 --- a/tests/GraphBLAS-sharp.Tests/Vector/Map2.fs +++ b/tests/GraphBLAS-sharp.Tests/Vector/Map2.fs @@ -90,7 +90,7 @@ let correctnessGenericTest let createTest case isEqual (zero: 'a) plus plusQ map2 = let context = case.TestContext.ClContext - let map2 = map2 context plusQ wgSize + let map2 = map2 plusQ context wgSize let intToDense = Vector.toDense context wgSize diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Reduce.fs b/tests/GraphBLAS-sharp.Tests/Vector/Reduce.fs index cfbca46b..42f29688 100644 --- a/tests/GraphBLAS-sharp.Tests/Vector/Reduce.fs +++ b/tests/GraphBLAS-sharp.Tests/Vector/Reduce.fs @@ -7,7 +7,7 @@ open GraphBLAS.FSharp.Tests open Brahma.FSharp open FSharp.Quotations open TestCases -open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Objects.ClCell open GraphBLAS.FSharp.Backend.Vector let logger = Log.create "Vector.reduce.Tests" @@ -22,15 +22,7 @@ let checkResult zero op (actual: 'a) (vector: 'a []) = "Results should be the same" |> Expect.equal actual expected -let correctnessGenericTest - isEqual - zero - op - opQ - (reduce: Expr<'a -> 'a -> 'a> -> MailboxProcessor<_> -> ClVector<'a> -> ClCell<'a>) - case - (array: 'a []) - = +let correctnessGenericTest isEqual zero op reduce case (array: 'a []) = let vector = Utils.createVectorFromArray case.Format array (isEqual zero) @@ -41,27 +33,18 @@ let correctnessGenericTest let clVector = vector.ToDevice context - let resultCell = reduce opQ q clVector - - let result = Array.zeroCreate 1 - let result = - let res = - q.PostAndReply(fun ch -> Msg.CreateToHostMsg<_>(resultCell, result, ch)) - - q.Post(Msg.CreateFreeMsg<_>(resultCell)) - - res.[0] + (reduce q clVector: ClCell<_>).ToHostAndFree q checkResult zero op result array let createTest<'a when 'a: equality and 'a: struct> case isEqual (zero: 'a) plus plusQ name = let context = case.TestContext.ClContext - let reduce = Vector.reduce context wgSize + let reduce = Vector.reduce plusQ context wgSize case - |> correctnessGenericTest isEqual zero plus plusQ reduce + |> correctnessGenericTest isEqual zero plus reduce |> testPropertyWithConfig config $"Correctness on %A{typeof<'a>}, %s{name} %A{case.Format}" diff --git a/tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs b/tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs index 252c45ba..e19ade53 100644 --- a/tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs +++ b/tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs @@ -92,7 +92,7 @@ let createTest testContext (zero: 'a) isEqual add mul addQ mulQ = let getCorrectnessTestName datatype = $"Correctness on %s{datatype}, %A{testContext.ClContext}" - let spMV = SpMV.run context addQ mulQ wgSize + let spMV = SpMV.run addQ mulQ context wgSize testContext |> correctnessGenericTest zero add mul spMV isEqual q From d9dd757d09e21e1be423f6371ade428e609ed174 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sun, 23 Apr 2023 16:04:33 +0300 Subject: [PATCH 29/44] wip: SpGeMM benchmark --- .../Algorithms/BFS.fs | 142 +++++++++--------- .../Configs/Context.txt | 4 + .../Configs/SpGeMM.txt | 1 + .../GraphBLAS-sharp.Benchmarks.fsproj | 1 + .../GraphBLAS-sharp.Benchmarks/Helpers.fs | 13 +- .../Matrix/SpGeMM/Expand.fs | 5 +- .../GraphBLAS-sharp.Benchmarks/Program.fs | 3 +- .../Matrix/CSR/Matrix.fs | 2 +- .../Vector/Sparse/Vector.fs | 2 +- src/GraphBLAS-sharp.Backend/Vector/Vector.fs | 2 +- 10 files changed, 91 insertions(+), 84 deletions(-) create mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/Configs/SpGeMM.txt diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs index 035b9b2f..7115a90c 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Algorithms/BFS.fs @@ -92,89 +92,87 @@ type Benchmarks<'elem when 'elem : struct>( abstract member Benchmark : unit -> unit -module WithoutTransfer = - type Benchmark<'elem when 'elem : struct>( +type WithoutTransferBenchmark<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + boolConverter, + vertex) = + + inherit Benchmarks<'elem>( buildFunToBenchmark, - converter: string -> 'elem, + converter, boolConverter, - vertex) = + vertex) - inherit Benchmarks<'elem>( - buildFunToBenchmark, - converter, - boolConverter, - vertex) + [] + override this.GlobalSetup() = + this.ReadMatrix() + this.LoadMatrixToGPU() - [] - override this.GlobalSetup() = - this.ReadMatrix() - this.LoadMatrixToGPU() + [] + override this.IterationCleanup() = + this.ClearResult() - [] - override this.IterationCleanup() = - this.ClearResult() + [] + override this.GlobalCleanup() = + this.ClearInputMatrix() - [] - override this.GlobalCleanup() = - this.ClearInputMatrix() + [] + override this.Benchmark() = + this.BFS() + this.Processor.PostAndReply Msg.MsgNotifyMe - [] - override this.Benchmark() = - this.BFS() - this.Processor.PostAndReply Msg.MsgNotifyMe +type BFSWithoutTransferBenchmarkInt32() = - type Int() = + inherit WithoutTransferBenchmark( + (singleSource ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), + int32, + (fun _ -> Utils.nextInt (System.Random())), + 0) - inherit Benchmark( - (singleSource ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), - int32, - (fun _ -> Utils.nextInt (System.Random())), - 0) + static member InputMatrixProvider = + Benchmarks<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" - static member InputMatrixProvider = - Benchmark<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" +type WithTransferBenchmark<'elem when 'elem : struct>( + buildFunToBenchmark, + converter: string -> 'elem, + boolConverter, + vertex) = -module WithTransfer = - type Benchmark<'elem when 'elem : struct>( + inherit Benchmarks<'elem>( buildFunToBenchmark, - converter: string -> 'elem, + converter, boolConverter, - vertex) = - - inherit Benchmarks<'elem>( - buildFunToBenchmark, - converter, - boolConverter, - vertex) - - [] - override this.GlobalSetup() = - this.ReadMatrix() - - [] - override this.GlobalCleanup() = - this.ClearResult() - - [] - override this.IterationCleanup() = - this.ClearInputMatrix() - this.ClearResult() - - [] - override this.Benchmark() = - this.LoadMatrixToGPU() - this.BFS() - this.ResultLevels.ToHost this.Processor |> ignore - this.Processor.PostAndReply Msg.MsgNotifyMe - - type Int() = - - inherit Benchmark( - (singleSource ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), - int32, - (fun _ -> Utils.nextInt (System.Random())), - 0) - - static member InputMatrixProvider = - Benchmark<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" + vertex) + + [] + override this.GlobalSetup() = + this.ReadMatrix() + + [] + override this.GlobalCleanup() = + this.ClearResult() + + [] + override this.IterationCleanup() = + this.ClearInputMatrix() + this.ClearResult() + + [] + override this.Benchmark() = + this.LoadMatrixToGPU() + this.BFS() + this.ResultLevels.ToHost this.Processor |> ignore + this.Processor.PostAndReply Msg.MsgNotifyMe + +type BFSWithTransferBenchmarkInt32() = + + inherit WithTransferBenchmark( + (singleSource ArithmeticOperations.intSumOption ArithmeticOperations.intMulOption), + int32, + (fun _ -> Utils.nextInt (System.Random())), + 0) + + static member InputMatrixProvider = + Benchmarks<_>.InputMatrixProviderBuilder "BFSBenchmarks.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/Context.txt b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/Context.txt index 04f1c08e..af722237 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/Context.txt +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/Context.txt @@ -1,3 +1,7 @@ + +Gpu +32 + NVIDIA* Gpu 32 diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/SpGeMM.txt b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/SpGeMM.txt new file mode 100644 index 00000000..9a294a4a --- /dev/null +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/SpGeMM.txt @@ -0,0 +1 @@ +hollywood-2009.mtx diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj b/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj index 8c455f09..6e8486b0 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/GraphBLAS-sharp.Benchmarks.fsproj @@ -26,6 +26,7 @@ + \ No newline at end of file diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs index 0d292f3c..8702d511 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs @@ -108,13 +108,16 @@ module Utils = let queue = context.QueueProvider.CreateQueue() { ClContext = context; Queue = queue }) + let result = + seq { + for wgSize in workGroupSizes do + for context in contexts do + yield (context, wgSize) + } - seq { - for wgSize in workGroupSizes do - for context in contexts do - yield (context, wgSize) - } + printfn "result length: %A" <| Seq.length result + result let nextSingle (random: System.Random) = let buffer = Array.zeroCreate 4 random.NextBytes buffer diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs index 3daf2ec4..3f1751af 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Matrix/SpGeMM/Expand.fs @@ -49,7 +49,7 @@ type Benchmarks<'elem when 'elem : struct>( static member AvailableContexts = Utils.availableContexts static member InputMatrixProviderBuilder pathToConfig = - let datasetFolder = "Mxm" + let datasetFolder = "" pathToConfig |> Utils.getMatricesFilenames |> Seq.map @@ -59,7 +59,6 @@ type Benchmarks<'elem when 'elem : struct>( match Path.GetExtension matrixFilename with | ".mtx" -> MtxReader(Utils.getFullPathToMatrix datasetFolder matrixFilename) - , MtxReader(Utils.getFullPathToMatrix datasetFolder (matrixFilename)) | _ -> failwith "Unsupported matrix format") member this.FunToBenchmark = @@ -145,4 +144,4 @@ module WithoutTransfer = ) static member InputMatrixProvider = - Benchmarks<_>.InputMatrixProviderBuilder "MxmBenchmarks4Float32.txt" + Benchmarks<_>.InputMatrixProviderBuilder "SpGeMM.txt" diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs index ea487610..d22c1e5a 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs @@ -4,7 +4,8 @@ open BenchmarkDotNet.Running [] let main argv = let benchmarks = - BenchmarkSwitcher [| typeof |] + BenchmarkSwitcher [| typeof + typeof |] benchmarks.Run argv |> ignore 0 diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 7730eaa2..64a18e49 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -167,7 +167,7 @@ module Matrix = let pairwise = ClArray.pairwise clContext workGroupSize let subtract = - ClArray.map clContext workGroupSize <@ fun (fst, snd) -> snd - fst @> + ClArray.map <@ fun (fst, snd) -> snd - fst @> clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'b>) -> let pointerPairs = diff --git a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs index 8d0be005..add0e2a7 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Sparse/Vector.fs @@ -65,6 +65,6 @@ module Vector = let reduce<'a when 'a: struct> (opAdd: Expr<'a -> 'a -> 'a>) (clContext: ClContext) workGroupSize = let reduce = - Reduce.reduce clContext workGroupSize opAdd + Reduce.reduce opAdd clContext workGroupSize fun (processor: MailboxProcessor<_>) (vector: ClVector.Sparse<'a>) -> reduce processor vector.Values diff --git a/src/GraphBLAS-sharp.Backend/Vector/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Vector.fs index 9dd9fc6b..9c94992b 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Vector.fs @@ -39,7 +39,7 @@ module Vector = ClArray.zeroCreate clContext workGroupSize let map = - ClArray.map clContext workGroupSize <@ Some @> + ClArray.map <@ Some @> clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode format size (elements: (int * 'a) list) -> match format with From f5c6fe611feedc429efe9a97a98c80bcd2830700 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sun, 23 Apr 2023 17:36:37 +0300 Subject: [PATCH 30/44] fix: count in CSR.byRows --- .../GraphBLAS-sharp.Benchmarks/Configs/Context.txt | 4 ---- benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs | 3 +-- src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs | 10 ++++++---- src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs | 10 ++++++++-- src/GraphBLAS-sharp.Backend/Objects/Matrix.fs | 4 ++-- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/Context.txt b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/Context.txt index af722237..04f1c08e 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/Context.txt +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs/Context.txt @@ -1,7 +1,3 @@ - -Gpu -32 - NVIDIA* Gpu 32 diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs index d22c1e5a..5a3ccf37 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Program.fs @@ -4,8 +4,7 @@ open BenchmarkDotNet.Running [] let main argv = let benchmarks = - BenchmarkSwitcher [| typeof - typeof |] + BenchmarkSwitcher [| typeof |] benchmarks.Run argv |> ignore 0 diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 64a18e49..835596f1 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -132,12 +132,14 @@ module Matrix = |> Seq.map (fun (first, second) -> lazy - (if second - first > 0 then - let values = getChunkValues first second - let columns = getChunkIndices first second + (let count = second - first + + if count > 0 then + let values = getChunkValues first count + let columns = getChunkIndices first count Some <| creatSparseVector values columns - else + else None)) let byRows (clContext: ClContext) workGroupSize = diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index 7041ac33..5f33fb90 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -301,7 +301,13 @@ module Expand = runRow processor allocationMode rightMatrix rightMatrixRowsLengths split processor allocationMode leftMatrix - |> Seq.map (fun lazyRow -> Option.bind runRow lazyRow.Value) + |> Seq.map (fun lazyRow -> + Option.bind (fun row -> + let result = runRow row + row.Dispose processor + + result + ) lazyRow.Value) |> Seq.toArray |> fun rows -> rightMatrixRowsLengths.Free processor @@ -309,7 +315,7 @@ module Expand = // compute nnz let nnz = rows - |> Array.fold + |> Seq.fold (fun count -> function | Some row -> count + row.Size diff --git a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs index e2a1d76a..3ddb7cea 100644 --- a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs @@ -92,8 +92,8 @@ module ClMatrix = interface IDeviceMemObject with member this.Dispose q = this.Rows - |> Array.choose id - |> Array.iter (fun vector -> vector.Dispose q) + |> Seq.choose id + |> Seq.iter (fun vector -> vector.Dispose q) type Tuple<'elem when 'elem: struct> = { Context: ClContext From ad9b5283a71b9503ab1fbb0d160f81a66b57e528 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Mon, 24 Apr 2023 19:28:05 +0300 Subject: [PATCH 31/44] add: CSR.byRows tests --- src/GraphBLAS-sharp/Objects/Matrix.fs | 2 +- .../GraphBLAS-sharp.Tests.fsproj | 1 + tests/GraphBLAS-sharp.Tests/Matrix/ByRows.fs | 55 +++++++++++++++++++ tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs | 8 ++- tests/GraphBLAS-sharp.Tests/Program.fs | 3 +- 5 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 tests/GraphBLAS-sharp.Tests/Matrix/ByRows.fs diff --git a/src/GraphBLAS-sharp/Objects/Matrix.fs b/src/GraphBLAS-sharp/Objects/Matrix.fs index c1ed4c33..c99e5b6a 100644 --- a/src/GraphBLAS-sharp/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp/Objects/Matrix.fs @@ -24,7 +24,7 @@ module Matrix = |> List.mapi (fun i x -> (x, i)) |> List.filter (fun pair -> not <| isZero (fst pair))) |> List.fold - (fun (rowPtrs, valueInx) row -> ((rowPtrs.Head + row.Length) :: rowPtrs), valueInx @ row) + (fun (rowPointers, valueInx) row -> ((rowPointers.Head + row.Length) :: rowPointers), valueInx @ row) ([ 0 ], []) { Values = diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index 9ea04ea9..b507283f 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -53,6 +53,7 @@ + diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/ByRows.fs b/tests/GraphBLAS-sharp.Tests/Matrix/ByRows.fs new file mode 100644 index 00000000..2b5cf78b --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Matrix/ByRows.fs @@ -0,0 +1,55 @@ +module GraphBLAS.FSharp.Tests.Matrix.ByRows + +open Expecto +open GraphBLAS.FSharp.Tests +open GraphBLAS.FSharp.Backend +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Backend.Matrix +open GraphBLAS.FSharp.Backend.Objects +open GraphBLAS.FSharp.Backend.Objects.ClContext +open GraphBLAS.FSharp.Objects.ClVectorExtensions + +let context = Context.defaultContext.ClContext + +let processor = Context.defaultContext.Queue + +let config = Utils.defaultConfig + +let makeTest<'a when 'a : struct> isEqual zero testFun (array: 'a [,]) = + + let matrix = Matrix.CSR.FromArray2D(array, isEqual zero) + + if matrix.NNZ > 0 then + + let clMatrix = matrix.ToDevice context + + let rows = testFun processor HostInterop clMatrix + + "Rows count must be the same" + |> Expect.equal (Seq.length rows) (Array2D.length1 array) + + rows + |> Seq.iteri (fun index -> function + | Some (actualRow: ClVector.Sparse<_>) -> + let expectedRow = Vector.Sparse.FromArray(array.[index, *], (isEqual zero)) + let actualHost = actualRow.ToHost processor + + Utils.compareSparseVectors isEqual actualHost expectedRow + | None -> + "Expected row must be None" + |> Expect.isFalse (Array.exists ((<<) not <| isEqual zero) array.[index, *])) + +let createTest isEqual (zero: 'a) = + CSR.Matrix.byRows context Utils.defaultWorkGroupSize + |> makeTest<'a> isEqual zero + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + +let tests = + [ createTest (=) 0 + + if Utils.isFloat64Available context.ClDevice then + createTest Utils.floatIsEqual 0.0 + + createTest Utils.float32IsEqual 0.0f + createTest (=) false ] + |> testList "CSR byRows" diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs b/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs index c9c171db..c27bf511 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs +++ b/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs @@ -45,6 +45,12 @@ let makeTest context q formatFrom formatTo convertFun isZero (array: 'a [,]) = let expected = Utils.createMatrixFromArray2D formatTo array isZero + "Row count should be the same" + |> Expect.equal actual.RowCount (Array2D.length1 array) + + "Column count should be the same" + |> Expect.equal actual.ColumnCount (Array2D.length2 array) + "Matrices should be equal" |> Expect.equal actual expected @@ -56,7 +62,7 @@ let createTest<'a when 'a: struct and 'a: equality> convertFun formatTo (isZero: |> List.map (fun formatFrom -> makeTest context q formatFrom formatTo convertFun isZero - |> testPropertyWithConfig { config with endSize = 10 } $"test on %A{typeof<'a>} from %A{formatFrom}") + |> testPropertyWithConfig config $"test on %A{typeof<'a>} from %A{formatFrom}") let testFixtures formatTo = match formatTo with diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index b47ee325..0421f533 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -16,7 +16,8 @@ let matrixTests = Matrix.SpGeMM.Expand.generalTests Matrix.SpGeMM.Masked.tests Matrix.Transpose.tests - Matrix.RowsLengths.tests ] + Matrix.RowsLengths.tests + Matrix.ByRows.tests ] |> testSequenced let commonTests = From acaa0c1c68a07fe217d9367d80ea21b2b6b703ae Mon Sep 17 00:00:00 2001 From: IgorErin Date: Mon, 24 Apr 2023 20:18:09 +0300 Subject: [PATCH 32/44] fix: host COO -> CSR --- src/GraphBLAS-sharp/Objects/Matrix.fs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/GraphBLAS-sharp/Objects/Matrix.fs b/src/GraphBLAS-sharp/Objects/Matrix.fs index c99e5b6a..468c1a5e 100644 --- a/src/GraphBLAS-sharp/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp/Objects/Matrix.fs @@ -93,15 +93,12 @@ module Matrix = member this.ToCSR = let rowPointers = - let nnzPerRow = Array.zeroCreate this.RowCount - let rowPointers = Array.zeroCreate this.RowCount + let pointers = Array.zeroCreate this.RowCount - Array.iter (fun rowIndex -> nnzPerRow.[rowIndex] <- nnzPerRow.[rowIndex] + 1) this.Rows + Array.countBy id this.Rows + |> Array.iter (fun (index, count) -> pointers.[index] <- count) - for i in 1 .. this.RowCount - 1 do - rowPointers.[i] <- rowPointers.[i - 1] + nnzPerRow.[i - 1] - - rowPointers + Array.scan (+) 0 pointers { RowCount = this.RowCount ColumnCount = this.ColumnCount @@ -128,7 +125,7 @@ module Matrix = |> List.mapi (fun i x -> (x, i)) |> List.filter (fun pair -> not <| isZero (fst pair))) |> List.fold - (fun (colPtrs, valueInx) col -> ((colPtrs.Head + col.Length) :: colPtrs), valueInx @ col) + (fun (colPointers, valueInx) col -> ((colPointers.Head + col.Length) :: colPointers), valueInx @ col) ([ 0 ], []) { Values = From a4497543c2bc474f9d2920568b37c0f801910fa0 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Tue, 25 Apr 2023 11:44:50 +0300 Subject: [PATCH 33/44] add: host tests --- .../GraphBLAS-sharp.Benchmarks/Configs.fs | 6 +- .../Matrix/CSR/Matrix.fs | 2 +- .../Matrix/SpGeMM/Expand.fs | 16 +- src/GraphBLAS-sharp/IO/MtxReader.fs | 10 +- src/GraphBLAS-sharp/Objects/Matrix.fs | 6 +- .../{ => Backend}/Algorithms/BFS.fs | 0 .../{ => Backend}/Common/ClArray/Blit.fs | 0 .../{ => Backend}/Common/ClArray/Choose.fs | 0 .../Common/ClArray/ChunkBySize.fs | 0 .../{ => Backend}/Common/ClArray/Concat.fs | 0 .../{ => Backend}/Common/ClArray/Copy.fs | 0 .../{ => Backend}/Common/ClArray/Exists.fs | 0 .../{ => Backend}/Common/ClArray/Fill.fs | 0 .../{ => Backend}/Common/ClArray/Map.fs | 0 .../{ => Backend}/Common/ClArray/Map2.fs | 0 .../{ => Backend}/Common/ClArray/Pairwise.fs | 0 .../Common/ClArray/RemoveDuplicates.fs | 0 .../{ => Backend}/Common/ClArray/Replicate.fs | 0 .../{ => Backend}/Common/Gather.fs | 0 .../{ => Backend}/Common/Reduce/Reduce.fs | 0 .../Common/Reduce/ReduceByKey.fs | 0 .../{ => Backend}/Common/Reduce/Sum.fs | 0 .../{ => Backend}/Common/Scan/ByKey.fs | 0 .../{ => Backend}/Common/Scan/PrefixSum.fs | 0 .../{ => Backend}/Common/Scatter.fs | 0 .../{ => Backend}/Common/Sort/Bitonic.fs | 0 .../{ => Backend}/Common/Sort/Radix.fs | 0 .../{ => Backend}/Matrix/ByRows.fs | 27 +-- .../{ => Backend}/Matrix/Convert.fs | 0 .../{ => Backend}/Matrix/Map.fs | 0 .../{ => Backend}/Matrix/Map2.fs | 0 .../{ => Backend}/Matrix/RowsLengths.fs | 0 .../{ => Backend}/Matrix/SpGeMM/Expand.fs | 0 .../{ => Backend}/Matrix/SpGeMM/Masked.fs | 0 .../{ => Backend}/Matrix/Transpose.fs | 0 .../QuickGraph/Algorithms/BFS.fs | 0 .../Algorithms/ConnectedComponents.fs | 0 .../{ => Backend}/QuickGraph/CreateGraph.fs | 0 .../{ => Backend}/Vector/AssignByMask.fs | 0 .../{ => Backend}/Vector/Convert.fs | 0 .../{ => Backend}/Vector/Copy.fs | 0 .../{ => Backend}/Vector/Map2.fs | 0 .../{ => Backend}/Vector/OfList.fs | 0 .../{ => Backend}/Vector/Reduce.fs | 0 .../{ => Backend}/Vector/SpMV.fs | 0 .../{ => Backend}/Vector/ZeroCreate.fs | 0 .../GraphBLAS-sharp.Tests.fsproj | 86 ++++----- tests/GraphBLAS-sharp.Tests/Helpers.fs | 16 ++ .../Host/IO/Dataset/testMatrix.mtx | 5 + .../Host/IO/MtxReader.fs | 45 +++++ .../Host/Matrix/Convert.fs | 25 +++ .../Host/Matrix/FromaArray2D.fs | 169 ++++++++++++++++++ tests/GraphBLAS-sharp.Tests/Program.fs | 22 ++- 53 files changed, 361 insertions(+), 74 deletions(-) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Algorithms/BFS.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Blit.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Choose.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/ChunkBySize.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Concat.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Copy.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Exists.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Fill.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Map.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Map2.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Pairwise.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/RemoveDuplicates.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/ClArray/Replicate.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/Gather.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/Reduce/Reduce.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/Reduce/ReduceByKey.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/Reduce/Sum.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/Scan/ByKey.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/Scan/PrefixSum.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/Scatter.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/Sort/Bitonic.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Common/Sort/Radix.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Matrix/ByRows.fs (59%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Matrix/Convert.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Matrix/Map.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Matrix/Map2.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Matrix/RowsLengths.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Matrix/SpGeMM/Expand.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Matrix/SpGeMM/Masked.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Matrix/Transpose.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/QuickGraph/Algorithms/BFS.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/QuickGraph/Algorithms/ConnectedComponents.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/QuickGraph/CreateGraph.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Vector/AssignByMask.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Vector/Convert.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Vector/Copy.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Vector/Map2.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Vector/OfList.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Vector/Reduce.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Vector/SpMV.fs (100%) rename tests/GraphBLAS-sharp.Tests/{ => Backend}/Vector/ZeroCreate.fs (100%) create mode 100644 tests/GraphBLAS-sharp.Tests/Host/IO/Dataset/testMatrix.mtx create mode 100644 tests/GraphBLAS-sharp.Tests/Host/IO/MtxReader.fs create mode 100644 tests/GraphBLAS-sharp.Tests/Host/Matrix/Convert.fs create mode 100644 tests/GraphBLAS-sharp.Tests/Host/Matrix/FromaArray2D.fs diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Configs.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs.fs index 0d1c51d0..8f22f19f 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Configs.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Configs.fs @@ -18,7 +18,7 @@ type Matrix2() = "NNZ", fun (matrix,_) -> match matrix.Format with - | Coordinate -> matrix.ReadMatrixShape().Nnz + | Coordinate -> matrix.ReadMatrixShape().NNZ | Array -> 0 ) :> IColumn, @@ -26,7 +26,7 @@ type Matrix2() = "SqrNNZ", fun (_,matrix) -> match matrix.Format with - | Coordinate -> matrix.ReadMatrixShape().Nnz + | Coordinate -> matrix.ReadMatrixShape().NNZ | Array -> 0 ) :> IColumn, @@ -46,7 +46,7 @@ type Matrix() = "NNZ", fun matrix -> match matrix.Format with - | Coordinate -> matrix.ReadMatrixShape().Nnz + | Coordinate -> matrix.ReadMatrixShape().NNZ | Array -> 0 ) :> IColumn, diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 835596f1..40095927 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -139,7 +139,7 @@ module Matrix = let columns = getChunkIndices first count Some <| creatSparseVector values columns - else + else None)) let byRows (clContext: ClContext) workGroupSize = diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index 5f33fb90..704c0a98 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -301,13 +301,15 @@ module Expand = runRow processor allocationMode rightMatrix rightMatrixRowsLengths split processor allocationMode leftMatrix - |> Seq.map (fun lazyRow -> - Option.bind (fun row -> - let result = runRow row - row.Dispose processor - - result - ) lazyRow.Value) + |> Seq.map + (fun lazyRow -> + Option.bind + (fun row -> + let result = runRow row + row.Dispose processor + + result) + lazyRow.Value) |> Seq.toArray |> fun rows -> rightMatrixRowsLengths.Free processor diff --git a/src/GraphBLAS-sharp/IO/MtxReader.fs b/src/GraphBLAS-sharp/IO/MtxReader.fs index db4d4d5a..f25ce8c0 100644 --- a/src/GraphBLAS-sharp/IO/MtxReader.fs +++ b/src/GraphBLAS-sharp/IO/MtxReader.fs @@ -34,13 +34,13 @@ type MtxReader(pathToFile: string) = streamReader.ReadLine().Split(' ') |> Array.map int - let nrows = size.[0] - let ncols = size.[1] + let rowsCount = size.[0] + let columnsCount = size.[1] let nnz = size.[2] - {| RowCount = nrows - ColumnCount = ncols - Nnz = nnz |} + {| RowCount = rowsCount + ColumnCount = columnsCount + NNZ = nnz |} member this.ReadMatrix(converter: string -> 'a) : Matrix.COO<'a> = if object <> MtxMatrix then diff --git a/src/GraphBLAS-sharp/Objects/Matrix.fs b/src/GraphBLAS-sharp/Objects/Matrix.fs index 468c1a5e..558f965b 100644 --- a/src/GraphBLAS-sharp/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp/Objects/Matrix.fs @@ -24,7 +24,8 @@ module Matrix = |> List.mapi (fun i x -> (x, i)) |> List.filter (fun pair -> not <| isZero (fst pair))) |> List.fold - (fun (rowPointers, valueInx) row -> ((rowPointers.Head + row.Length) :: rowPointers), valueInx @ row) + (fun (rowPointers, valueInx) row -> + ((rowPointers.Head + row.Length) :: rowPointers), valueInx @ row) ([ 0 ], []) { Values = @@ -125,7 +126,8 @@ module Matrix = |> List.mapi (fun i x -> (x, i)) |> List.filter (fun pair -> not <| isZero (fst pair))) |> List.fold - (fun (colPointers, valueInx) col -> ((colPointers.Head + col.Length) :: colPointers), valueInx @ col) + (fun (colPointers, valueInx) col -> + ((colPointers.Head + col.Length) :: colPointers), valueInx @ col) ([ 0 ], []) { Values = diff --git a/tests/GraphBLAS-sharp.Tests/Algorithms/BFS.fs b/tests/GraphBLAS-sharp.Tests/Backend/Algorithms/BFS.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Algorithms/BFS.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Algorithms/BFS.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Blit.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Blit.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Blit.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Blit.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Choose.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Choose.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Choose.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Choose.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/ChunkBySize.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/ChunkBySize.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/ChunkBySize.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Concat.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Concat.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Concat.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Copy.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Copy.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Copy.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Copy.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Exists.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Exists.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Exists.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Exists.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Fill.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Fill.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Fill.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Map.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Map.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Map.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Map2.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Map2.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Map2.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Map2.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Pairwise.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Pairwise.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Pairwise.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/RemoveDuplicates.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/RemoveDuplicates.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/RemoveDuplicates.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/RemoveDuplicates.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/ClArray/Replicate.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Replicate.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/ClArray/Replicate.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Replicate.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/Gather.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/Gather.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/Gather.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/Gather.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/Reduce/Reduce.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/Reduce/Reduce.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/Reduce/Reduce.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/Reduce/Reduce.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/Reduce/ReduceByKey.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/Reduce/ReduceByKey.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/Reduce/ReduceByKey.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/Reduce/Sum.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/Reduce/Sum.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/Reduce/Sum.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/Reduce/Sum.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/Scan/ByKey.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/Scan/ByKey.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/Scan/ByKey.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/Scan/ByKey.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/Scan/PrefixSum.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/Scan/PrefixSum.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/Scan/PrefixSum.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/Scan/PrefixSum.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/Scatter.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/Scatter.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/Scatter.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/Scatter.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/Sort/Bitonic.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/Sort/Bitonic.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/Sort/Bitonic.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/Sort/Bitonic.fs diff --git a/tests/GraphBLAS-sharp.Tests/Common/Sort/Radix.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/Sort/Radix.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Common/Sort/Radix.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Common/Sort/Radix.fs diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/ByRows.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/ByRows.fs similarity index 59% rename from tests/GraphBLAS-sharp.Tests/Matrix/ByRows.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Matrix/ByRows.fs index 2b5cf78b..98270784 100644 --- a/tests/GraphBLAS-sharp.Tests/Matrix/ByRows.fs +++ b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/ByRows.fs @@ -15,9 +15,10 @@ let processor = Context.defaultContext.Queue let config = Utils.defaultConfig -let makeTest<'a when 'a : struct> isEqual zero testFun (array: 'a [,]) = +let makeTest<'a when 'a: struct> isEqual zero testFun (array: 'a [,]) = - let matrix = Matrix.CSR.FromArray2D(array, isEqual zero) + let matrix = + Matrix.CSR.FromArray2D(array, isEqual zero) if matrix.NNZ > 0 then @@ -29,15 +30,19 @@ let makeTest<'a when 'a : struct> isEqual zero testFun (array: 'a [,]) = |> Expect.equal (Seq.length rows) (Array2D.length1 array) rows - |> Seq.iteri (fun index -> function - | Some (actualRow: ClVector.Sparse<_>) -> - let expectedRow = Vector.Sparse.FromArray(array.[index, *], (isEqual zero)) - let actualHost = actualRow.ToHost processor + |> Seq.iteri + (fun index -> + function + | Some (actualRow: ClVector.Sparse<_>) -> + let expectedRow = + Vector.Sparse.FromArray(array.[index, *], (isEqual zero)) - Utils.compareSparseVectors isEqual actualHost expectedRow - | None -> - "Expected row must be None" - |> Expect.isFalse (Array.exists ((<<) not <| isEqual zero) array.[index, *])) + let actualHost = actualRow.ToHost processor + + Utils.compareSparseVectors isEqual actualHost expectedRow + | None -> + "Expected row must be None" + |> Expect.isFalse (Array.exists ((<<) not <| isEqual zero) array.[index, *])) let createTest isEqual (zero: 'a) = CSR.Matrix.byRows context Utils.defaultWorkGroupSize @@ -48,7 +53,7 @@ let tests = [ createTest (=) 0 if Utils.isFloat64Available context.ClDevice then - createTest Utils.floatIsEqual 0.0 + createTest Utils.floatIsEqual 0.0 createTest Utils.float32IsEqual 0.0f createTest (=) false ] diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Convert.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Matrix/Convert.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Matrix/Convert.fs diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Map.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Matrix/Map.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map.fs diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map2.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Matrix/Map2.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map2.fs diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/RowsLengths.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Matrix/RowsLengths.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Matrix/RowsLengths.fs diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Expand.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Masked.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Masked.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Matrix/SpGeMM/Masked.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Masked.fs diff --git a/tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Transpose.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Matrix/Transpose.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Matrix/Transpose.fs diff --git a/tests/GraphBLAS-sharp.Tests/QuickGraph/Algorithms/BFS.fs b/tests/GraphBLAS-sharp.Tests/Backend/QuickGraph/Algorithms/BFS.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/QuickGraph/Algorithms/BFS.fs rename to tests/GraphBLAS-sharp.Tests/Backend/QuickGraph/Algorithms/BFS.fs diff --git a/tests/GraphBLAS-sharp.Tests/QuickGraph/Algorithms/ConnectedComponents.fs b/tests/GraphBLAS-sharp.Tests/Backend/QuickGraph/Algorithms/ConnectedComponents.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/QuickGraph/Algorithms/ConnectedComponents.fs rename to tests/GraphBLAS-sharp.Tests/Backend/QuickGraph/Algorithms/ConnectedComponents.fs diff --git a/tests/GraphBLAS-sharp.Tests/QuickGraph/CreateGraph.fs b/tests/GraphBLAS-sharp.Tests/Backend/QuickGraph/CreateGraph.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/QuickGraph/CreateGraph.fs rename to tests/GraphBLAS-sharp.Tests/Backend/QuickGraph/CreateGraph.fs diff --git a/tests/GraphBLAS-sharp.Tests/Vector/AssignByMask.fs b/tests/GraphBLAS-sharp.Tests/Backend/Vector/AssignByMask.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Vector/AssignByMask.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Vector/AssignByMask.fs diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Convert.fs b/tests/GraphBLAS-sharp.Tests/Backend/Vector/Convert.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Vector/Convert.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Vector/Convert.fs diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Copy.fs b/tests/GraphBLAS-sharp.Tests/Backend/Vector/Copy.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Vector/Copy.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Vector/Copy.fs diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Map2.fs b/tests/GraphBLAS-sharp.Tests/Backend/Vector/Map2.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Vector/Map2.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Vector/Map2.fs diff --git a/tests/GraphBLAS-sharp.Tests/Vector/OfList.fs b/tests/GraphBLAS-sharp.Tests/Backend/Vector/OfList.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Vector/OfList.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Vector/OfList.fs diff --git a/tests/GraphBLAS-sharp.Tests/Vector/Reduce.fs b/tests/GraphBLAS-sharp.Tests/Backend/Vector/Reduce.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Vector/Reduce.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Vector/Reduce.fs diff --git a/tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs b/tests/GraphBLAS-sharp.Tests/Backend/Vector/SpMV.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Vector/SpMV.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Vector/SpMV.fs diff --git a/tests/GraphBLAS-sharp.Tests/Vector/ZeroCreate.fs b/tests/GraphBLAS-sharp.Tests/Backend/Vector/ZeroCreate.fs similarity index 100% rename from tests/GraphBLAS-sharp.Tests/Vector/ZeroCreate.fs rename to tests/GraphBLAS-sharp.Tests/Backend/Vector/ZeroCreate.fs diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index b507283f..a3558eac 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -13,47 +13,51 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/GraphBLAS-sharp.Tests/Helpers.fs b/tests/GraphBLAS-sharp.Tests/Helpers.fs index 5325be0c..f12bada0 100644 --- a/tests/GraphBLAS-sharp.Tests/Helpers.fs +++ b/tests/GraphBLAS-sharp.Tests/Helpers.fs @@ -146,6 +146,22 @@ module Utils = <| actual.Rows <| expected.Rows + let compareCSRMatrix isEqual (actual: Matrix.CSR<'a>) (expected: Matrix.CSR<'a>) = + "Column count must be the same" + |> Expect.equal actual.ColumnCount expected.ColumnCount + + "Rows count must be the same" + |> Expect.equal actual.RowCount expected.RowCount + + "Values must be the same" + |> compareArrays isEqual actual.Values expected.Values + + "Column indices must be the same" + |> compareArrays (=) actual.ColumnIndices expected.ColumnIndices + + "Row pointers" + |> compareArrays (=) actual.RowPointers expected.RowPointers + let listOfUnionCases<'a> = FSharpType.GetUnionCases typeof<'a> |> Array.map (fun caseInfo -> FSharpValue.MakeUnion(caseInfo, [||]) :?> 'a) diff --git a/tests/GraphBLAS-sharp.Tests/Host/IO/Dataset/testMatrix.mtx b/tests/GraphBLAS-sharp.Tests/Host/IO/Dataset/testMatrix.mtx new file mode 100644 index 00000000..2af703b9 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Host/IO/Dataset/testMatrix.mtx @@ -0,0 +1,5 @@ +%%MatrixMarket matrix coordinate integer general +2 3 3 +1 2 3 +2 2 2 +2 3 1 diff --git a/tests/GraphBLAS-sharp.Tests/Host/IO/MtxReader.fs b/tests/GraphBLAS-sharp.Tests/Host/IO/MtxReader.fs new file mode 100644 index 00000000..54b91ed6 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Host/IO/MtxReader.fs @@ -0,0 +1,45 @@ +module GraphBLAS.FSharp.Tests.Host.IO.MtxReader + +open System.IO +open Expecto +open GraphBLAS.FSharp.IO + +let matrixName = "testMatrix.mtx" + +let path = + Path.Combine [| __SOURCE_DIRECTORY__ + "Dataset" + matrixName |] + +let test = + test "mtxReader test" { + let matrixReader = MtxReader(path) + + let shape = matrixReader.ReadMatrixShape() + + "Rows count must be the same" + |> Expect.equal shape.RowCount 2 + + "Columns count must be the same" + |> Expect.equal shape.ColumnCount 3 + + "NNZ count must be the same" + |> Expect.equal shape.NNZ 3 + + let matrix = matrixReader.ReadMatrix(int) + + "Matrix row count must be the same" + |> Expect.equal matrix.RowCount 2 + + "Matrix column count must be the same" + |> Expect.equal matrix.ColumnCount 3 + + "Matrix values must be the same" + |> Expect.sequenceEqual matrix.Values [| 3; 2; 1 |] + + "Matrix columns must be the same" + |> Expect.sequenceEqual matrix.Columns [| 1; 1; 2 |] + + "Matrix rows must be the same" + |> Expect.sequenceEqual matrix.Rows [| 0; 1; 1 |] + } diff --git a/tests/GraphBLAS-sharp.Tests/Host/Matrix/Convert.fs b/tests/GraphBLAS-sharp.Tests/Host/Matrix/Convert.fs new file mode 100644 index 00000000..358286a2 --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Host/Matrix/Convert.fs @@ -0,0 +1,25 @@ +module GraphBLAS.FSharp.Tests.Host.Matrix.Convert + +open Expecto +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Tests + +let makeTest isEqual zero (array: 'a [,]) = + let cooMatrix = + Matrix.COO.FromArray2D(array, isEqual zero) + + let actual = cooMatrix.ToCSR + + let expected = + Matrix.CSR.FromArray2D(array, isEqual zero) + + Utils.compareCSRMatrix isEqual actual expected + +let createTest<'a when 'a: struct> isEqual (zero: 'a) = + makeTest isEqual zero + |> testPropertyWithConfig Utils.defaultConfig $"%A{typeof<'a>}" + +let tests = + [ createTest (=) 0 + createTest (=) false ] + |> testList "Convert" diff --git a/tests/GraphBLAS-sharp.Tests/Host/Matrix/FromaArray2D.fs b/tests/GraphBLAS-sharp.Tests/Host/Matrix/FromaArray2D.fs new file mode 100644 index 00000000..7d2a3bdd --- /dev/null +++ b/tests/GraphBLAS-sharp.Tests/Host/Matrix/FromaArray2D.fs @@ -0,0 +1,169 @@ +module GraphBLAS.FSharp.Tests.Host.Matrix.FromArray2D + +open Expecto +open GraphBLAS.FSharp.Objects +open GraphBLAS.FSharp.Tests + +let config = Utils.defaultConfig + +let checkPointers isEqual zero array slice counter pointers (matrixValues: 'a []) (matrixIndices: int []) = + for i in 0 .. counter - 1 do + let expectedIndices, expectedValues = + slice array i + |> Array.mapi (fun index value -> (index, value)) + |> Array.filter (fun (_, value) -> ((<<) not <| isEqual zero) value) + |> Array.unzip + + let startRowPosition = Array.item i pointers + let endRowPosition = pointers.[i + 1] - 1 + + let actualValues = + matrixValues.[startRowPosition..endRowPosition] + + let actualIndices = + matrixIndices.[startRowPosition..endRowPosition] + + "Values must be the same" + |> Utils.compareArrays isEqual actualValues expectedValues + + "Indices must be the same" + |> Utils.compareArrays (=) actualIndices expectedIndices + +let makeTest isEqual zero createMatrix (array: 'a [,]) = + let matrix: Matrix<_> = createMatrix (isEqual zero) array + + let arrayRowCount = Array2D.length1 array + let arrayColumnCount = Array2D.length2 array + + "Row count must be the same" + |> Expect.equal matrix.RowCount arrayRowCount + + "Column count must be the same" + |> Expect.equal matrix.ColumnCount arrayColumnCount + + let nonZeroValues = + array + |> Seq.cast<'a> + |> Seq.filter ((<<) not <| isEqual zero) + |> Seq.toArray + + let checkPointers = checkPointers isEqual zero array + + match matrix with + | Matrix.CSR matrix -> + "Values must be the same" + |> Utils.compareArrays isEqual matrix.Values nonZeroValues + + "Row count invariant" + |> Expect.isTrue (matrix.RowPointers.Length = matrix.RowCount + 1) + + checkPointers + (fun (array: 'a [,]) i -> array.[i, *]) + arrayRowCount + matrix.RowPointers + matrix.Values + matrix.ColumnIndices + | Matrix.COO matrix -> + "Values must be the same" + |> Utils.compareArrays isEqual matrix.Values nonZeroValues + + let expectedColumns, expectedRows, expectedValues = + array + |> Seq.cast<'a> + |> Seq.mapi + (fun index value -> + let columnIndex = index % arrayColumnCount + let rowIndex = index / arrayColumnCount + + (columnIndex, rowIndex, value)) + |> Seq.filter (fun (_, _, value) -> ((<<) not <| isEqual zero) value) + |> Seq.toArray + |> Array.unzip3 + + "Values must be the same" + |> Utils.compareArrays isEqual matrix.Values expectedValues + + "Column indices must be the same" + |> Utils.compareArrays (=) matrix.Columns expectedColumns + + "Rows indices must be the same" + |> Utils.compareArrays (=) matrix.Rows expectedRows + | Matrix.CSC matrix -> + let expectedValues = + seq { + for i in 0 .. arrayColumnCount - 1 do + yield! array.[*, i] + } + |> Seq.filter ((<<) not <| isEqual zero) + |> Seq.toArray + + "Values must be the same" + |> Utils.compareArrays isEqual matrix.Values expectedValues + + "Row count invariant" + |> Expect.isTrue (matrix.ColumnPointers.Length = matrix.ColumnCount + 1) + + checkPointers + (fun array i -> array.[*, i]) + arrayColumnCount + matrix.ColumnPointers + matrix.Values + matrix.RowIndices + | Matrix.LIL matrix -> + "Rows count must be the same" + |> Expect.equal matrix.Rows.Length (Array2D.length1 array) + + matrix.Rows + |> Seq.iteri + (fun index -> + function + | Some actualRow -> + let expectedIndices, expectedValues = + array.[index, *] + |> Array.mapi (fun index value -> (index, value)) + |> Array.filter (fun (_, value) -> ((<<) not <| isEqual zero) value) + |> Array.unzip + + "Values must be the same" + |> Utils.compareArrays isEqual actualRow.Values expectedValues + + "Indices must be the same" + |> Utils.compareArrays (=) actualRow.Indices expectedIndices + | None -> + "No non zero items in row" + |> Expect.isFalse (Array.exists ((<<) not <| isEqual zero) array.[index, *])) + +let createTest name isEqual zero convert = + makeTest isEqual zero convert + |> testPropertyWithConfig config name + +let tests = + [ createTest + "CSR" + (=) + 0 + (fun isZero array -> + Matrix.CSR + <| Matrix.CSR.FromArray2D(array, isZero)) + createTest + "COO" + (=) + 0 + (fun isZero array -> + Matrix.COO + <| Matrix.COO.FromArray2D(array, isZero)) + createTest + "CSC" + (=) + 0 + (fun isZero array -> + Matrix.CSC + <| Matrix.CSC.FromArray2D(array, isZero)) + createTest + "LIL" + (=) + 0 + (fun isZero array -> + Matrix.LIL + <| Matrix.LIL.FromArray2D(array, isZero)) ] + |> testList "FromArray2D" diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index 0421f533..295430c8 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -2,6 +2,14 @@ open Expecto open GraphBLAS.FSharp.Tests.Backend open GraphBLAS.FSharp.Tests +let hostTests = + testList + "Host" + [ Host.Matrix.FromArray2D.tests + Host.Matrix.Convert.tests + Host.IO.MtxReader.test ] + |> testSequenced + let matrixTests = testList "Matrix tests" @@ -89,15 +97,21 @@ let algorithmsTests = testList "Algorithms tests" [ Algorithms.BFS.tests ] |> testSequenced -[] -let allTests = +let deviceTests = testList - "All tests" + "Device" [ matrixTests commonTests vectorTests algorithmsTests ] |> testSequenced +[] +let allTests = + testList "All tests" [ deviceTests; hostTests ] + |> testSequenced + [] -let main argv = allTests |> runTestsWithCLIArgs [] argv +let main argv = + Host.IO.MtxReader.test + |> runTestsWithCLIArgs [] argv From 29728030b6177bce5ecd8ab6261b35ff9cf7f952 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Tue, 25 Apr 2023 11:57:35 +0300 Subject: [PATCH 34/44] refactor: paths --- .../GraphBLAS-sharp.Tests.fsproj | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj index a3558eac..ae6b7678 100644 --- a/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj +++ b/tests/GraphBLAS-sharp.Tests/GraphBLAS-sharp.Tests.fsproj @@ -13,51 +13,51 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From efa50f4e09dec6e23e58be47ee9f7627df4cd243 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Tue, 25 Apr 2023 23:20:58 +0300 Subject: [PATCH 35/44] refactor: clean --- .../GraphBLAS-sharp.Benchmarks/Columns.fs | 2 +- .../GraphBLAS-sharp.Benchmarks/Helpers.fs | 74 ++----------------- 2 files changed, 6 insertions(+), 70 deletions(-) diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Columns.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Columns.fs index 2851fac4..0b2173ae 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Columns.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Columns.fs @@ -5,7 +5,7 @@ open BenchmarkDotNet.Reports open BenchmarkDotNet.Running open GraphBLAS.FSharp.IO -type CommonColumn<'a>(benchmarkCaseConvert, columnName: string, getShape: 'a -> 'b) = +type CommonColumn<'a>(benchmarkCaseConvert, columnName: string, getShape: 'a -> _) = interface IColumn with member this.AlwaysShow = true member this.Category = ColumnCategory.Params diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs index 8702d511..6ce43002 100644 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs +++ b/benchmarks/GraphBLAS-sharp.Benchmarks/Helpers.fs @@ -108,16 +108,12 @@ module Utils = let queue = context.QueueProvider.CreateQueue() { ClContext = context; Queue = queue }) - let result = - seq { - for wgSize in workGroupSizes do - for context in contexts do - yield (context, wgSize) - } - - printfn "result length: %A" <| Seq.length result + seq { + for wgSize in workGroupSizes do + for context in contexts do + yield (context, wgSize) + } - result let nextSingle (random: System.Random) = let buffer = Array.zeroCreate 4 random.NextBytes buffer @@ -155,63 +151,3 @@ module VectorGenerator = let createVector array = Utils.createVectorFromArray format array (fIsEqual 0.0) pairOfVectorsOfEqualSize Utils.normalFloatGenerator createVector - - -module MatrixGenerator = - let private pairOfMatricesOfEqualSizeGenerator (valuesGenerator: Gen<'a>) createMatrix = - gen { - let! rowsCount, columnsCount = Generators.dimension2DGenerator - let! matrixA = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) - let! matrixB = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) - return (createMatrix matrixA, createMatrix matrixB) - } - - let intPairOfEqualSizes format = - fun array -> Utils.createMatrixFromArray2D format array ((=) 0) - |> pairOfMatricesOfEqualSizeGenerator Arb.generate - - let floatPairOfEqualSizes format = - fun array -> Utils.createMatrixFromArray2D format array (Utils.fIsEqual 0.0) - |> pairOfMatricesOfEqualSizeGenerator Utils.normalFloatGenerator - - let private pairOfMatricesWithMaskOfEqualSizeGenerator (valuesGenerator: Gen<'a>) format createMatrix = - gen { - let! rowsCount, columnsCount = Generators.dimension2DGenerator - let! matrixA = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) - let! matrixB = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) - let! mask = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) - - return (createMatrix format matrixA, - createMatrix format matrixB, - createMatrix COO mask) - } - - let intPairWithMaskOfEqualSizes format = - fun format array -> Utils.createMatrixFromArray2D format array ((=) 0) - |> pairOfMatricesWithMaskOfEqualSizeGenerator Arb.generate format - - let floatPairWithMaskOfEqualSizes format = - fun format array -> Utils.createMatrixFromArray2D format array (Utils.fIsEqual 0.0) - |> pairOfMatricesWithMaskOfEqualSizeGenerator Utils.normalFloatGenerator format - -module MatrixVectorGenerator = - let private pairOfMatricesAndVectorGenerator (valuesGenerator: Gen<'a>) createVector createMatrix = - gen { - let! rowsCount, columnsCount = Generators.dimension2DGenerator - let! matrixA = valuesGenerator |> Gen.array2DOfDim (rowsCount, columnsCount) - let! vector = valuesGenerator |> Gen.arrayOfLength columnsCount - - return (createMatrix matrixA, createVector vector) - } - - let intPairOfCompatibleSizes matrixFormat vectorFormat = - let createVector array = Utils.createVectorFromArray vectorFormat array ((=) 0) - let createMatrix array = Utils.createMatrixFromArray2D matrixFormat array ((=) 0) - - pairOfMatricesAndVectorGenerator Arb.generate createVector createMatrix - - let floatPairOfCompatibleSizes matrixFormat vectorFormat = - let createVector array = Utils.createVectorFromArray vectorFormat array (Utils.floatIsEqual 0.0) - let createMatrix array = Utils.createMatrixFromArray2D matrixFormat array (Utils.floatIsEqual 0.0) - - pairOfMatricesAndVectorGenerator Utils.normalFloatGenerator createVector createMatrix From 655fe67dfee065bdb2a3fb38ccbb0d859dc0fd5b Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 28 Apr 2023 16:35:10 +0300 Subject: [PATCH 36/44] refactor: list instead array in LIL --- src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs | 5 +++-- src/GraphBLAS-sharp.Backend/Matrix/LIL/Matrix.fs | 9 +++++---- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 5 +---- src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs | 2 +- src/GraphBLAS-sharp.Backend/Objects/Matrix.fs | 2 +- src/GraphBLAS-sharp/Objects/Matrix.fs | 5 ++--- src/GraphBLAS-sharp/Objects/MatrixExtensions.fs | 2 +- tests/GraphBLAS-sharp.Tests/Helpers.fs | 2 +- 8 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 40095927..78ee25aa 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -149,14 +149,15 @@ module Matrix = fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> runLazy processor allocationMode matrix |> Seq.map (fun lazyValue -> lazyValue.Value) - |> Seq.toArray let toLIL (clContext: ClContext) workGroupSize = let byRows = byRows clContext workGroupSize fun (processor: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> - let rows = byRows processor allocationMode matrix + let rows = + byRows processor allocationMode matrix + |> Seq.toList { Context = clContext RowCount = matrix.RowCount diff --git a/src/GraphBLAS-sharp.Backend/Matrix/LIL/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/LIL/Matrix.fs index 4cc3944a..34eff782 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/LIL/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/LIL/Matrix.fs @@ -16,19 +16,20 @@ module Matrix = let rowsPointers = matrix.Rows - |> Array.map + |> List.map (function | None -> 0 | Some vector -> vector.Values.Length) + |> List.toArray // prefix sum |> Array.scan (+) 0 |> fun pointers -> clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, pointers) let valuesByRows, columnsIndicesByRows = matrix.Rows - |> Array.choose id - |> Array.map (fun vector -> vector.Values, vector.Indices) - |> Array.unzip + |> List.choose id + |> List.map (fun vector -> vector.Values, vector.Indices) + |> List.unzip let values = concatValues processor allocationMode valuesByRows diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index f3b39641..7e174bd8 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -46,10 +46,7 @@ module Matrix = Values = copyData processor allocationMode m.Values } | ClMatrix.LIL matrix -> matrix.Rows - |> Array.map ( - Option.bind - <| (Some << (vectorCopy processor allocationMode)) - ) + |> List.map (Option.map (vectorCopy processor allocationMode)) |> fun rows -> { Context = clContext RowCount = matrix.RowCount diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index 704c0a98..b4b14bad 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -310,7 +310,7 @@ module Expand = result) lazyRow.Value) - |> Seq.toArray + |> Seq.toList |> fun rows -> rightMatrixRowsLengths.Free processor diff --git a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs index 3ddb7cea..650c40b3 100644 --- a/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Objects/Matrix.fs @@ -86,7 +86,7 @@ module ClMatrix = { Context: ClContext RowCount: int ColumnCount: int - Rows: ClVector.Sparse<'elem> option [] + Rows: ClVector.Sparse<'elem> option list NNZ: int } interface IDeviceMemObject with diff --git a/src/GraphBLAS-sharp/Objects/Matrix.fs b/src/GraphBLAS-sharp/Objects/Matrix.fs index 558f965b..45754431 100644 --- a/src/GraphBLAS-sharp/Objects/Matrix.fs +++ b/src/GraphBLAS-sharp/Objects/Matrix.fs @@ -155,7 +155,7 @@ module Matrix = type LIL<'a when 'a: struct> = { RowCount: int ColumnCount: int - Rows: Vector.Sparse<'a> option [] + Rows: Vector.Sparse<'a> option list NNZ: int } static member FromArray2D(array: 'a [,], isZero: 'a -> bool) = @@ -172,7 +172,6 @@ module Matrix = Some vector else None ] - |> Array.ofList { RowCount = Array2D.length1 array ColumnCount = Array2D.length2 array @@ -183,7 +182,7 @@ module Matrix = let rows = this.Rows - |> Array.map (Option.bind (fun vector -> Some <| vector.ToDevice(context))) + |> List.map (Option.map (fun vector -> vector.ToDevice(context))) { Context = context RowCount = this.RowCount diff --git a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs index 47f987f8..d79a5d97 100644 --- a/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs +++ b/src/GraphBLAS-sharp/Objects/MatrixExtensions.fs @@ -36,7 +36,7 @@ module MatrixExtensions = ColumnCount = m.ColumnCount Rows = m.Rows - |> Array.map (Option.bind (fun row -> Some <| row.ToHost q)) + |> List.map (Option.map (fun row -> row.ToHost q)) NNZ = m.NNZ } |> Matrix.LIL diff --git a/tests/GraphBLAS-sharp.Tests/Helpers.fs b/tests/GraphBLAS-sharp.Tests/Helpers.fs index f12bada0..f2403ddc 100644 --- a/tests/GraphBLAS-sharp.Tests/Helpers.fs +++ b/tests/GraphBLAS-sharp.Tests/Helpers.fs @@ -137,7 +137,7 @@ module Utils = "Rows count must be the same" |> Expect.equal actual.RowCount expected.RowCount - Array.iter2 + List.iter2 (fun actualRow expected -> match actualRow, expected with | Some actualVector, Some expectedVector -> compareSparseVectors isEqual actualVector expectedVector From 7f3cb901fdf6850e77fe7d5d0799af53edbe5ec0 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 28 Apr 2023 20:37:25 +0300 Subject: [PATCH 37/44] refactor: SpGeMM.expand --- src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs index b4b14bad..38cb28bb 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/SpGeMM/Expand.fs @@ -10,7 +10,6 @@ open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions open GraphBLAS.FSharp.Backend.Objects open GraphBLAS.FSharp.Backend.Objects.ClCell open FSharp.Quotations -open GraphBLAS.FSharp.Backend.Vector.Sparse open GraphBLAS.FSharp.Backend.Objects.ClVector open GraphBLAS.FSharp.Backend.Objects.ClMatrix @@ -145,6 +144,8 @@ module Expand = .ToHostAndFree(processor) if resultLength = 0 then + positions.Free processor + None else let resultIndices = @@ -157,6 +158,8 @@ module Expand = assignValues processor firstValues secondValues positions resultValues + positions.Free processor + Some(resultValues, resultIndices) let sortByColumns (clContext: ClContext) workGroupSize = @@ -268,13 +271,12 @@ module Expand = // create sparse vector (TODO(empty vector)) reduceResult - |> Option.bind + |> Option.map (fun (values, columns) -> { Context = clContext Indices = columns Values = values - Size = rightMatrix.ColumnCount } - |> Some))) + Size = rightMatrix.ColumnCount }))) let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct> (clContext: ClContext) From bf1cd58376ea93564c265edeac90232f7f6cd5ec Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 28 Apr 2023 21:02:40 +0300 Subject: [PATCH 38/44] refactor: tests --- tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs | 6 +----- tests/GraphBLAS-sharp.Tests/Program.fs | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs index e187d118..35db28f7 100644 --- a/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs @@ -220,11 +220,7 @@ let makeGeneralTest<'a when 'a: struct> zero isEqual opMul opAdd testFun (leftAr let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = testFun opAddQ opMulQ context Utils.defaultWorkGroupSize |> makeGeneralTest<'a> zero isEqual opMul opAdd - |> testPropertyWithConfig - { config with - endSize = 1000 - maxTest = 2 } - $"test on %A{typeof<'a>}" + |> testPropertyWithConfig config $"test on %A{typeof<'a>}" let generalTests = [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index 295430c8..ccee444f 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -113,5 +113,4 @@ let allTests = [] let main argv = - Host.IO.MtxReader.test - |> runTestsWithCLIArgs [] argv + allTests |> runTestsWithCLIArgs [] argv From 76de19b71c37b88c5fb521a80abc186d13ba1fe2 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 28 Apr 2023 21:11:45 +0300 Subject: [PATCH 39/44] refactor: benchmark workflow --- .github/workflows/build-and-benchmark.yml | 2 +- .../BenchmarksTranspose.fs | 68 ------------------- 2 files changed, 1 insertion(+), 69 deletions(-) delete mode 100644 benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksTranspose.fs diff --git a/.github/workflows/build-and-benchmark.yml b/.github/workflows/build-and-benchmark.yml index ff8e88b4..2bde3398 100644 --- a/.github/workflows/build-and-benchmark.yml +++ b/.github/workflows/build-and-benchmark.yml @@ -36,7 +36,7 @@ jobs: with: name: BFS tool: 'benchmarkdotnet' - output-file-path: BenchmarkDotNet.Artifacts/results/GraphBLAS.FSharp.Benchmarks.BFSBenchmarksWithoutDataTransfer-report-brief.json + output-file-path: BenchmarkDotNet.Artifacts/results/GraphBLAS.FSharp.Benchmarks.BFSWithoutTransferBenchmarkInt32-report-brief.json # Access token to deploy GitHub Pages branch github-token: ${{ secrets._GITHUB_TOKEN }} # Push and deploy GitHub pages branch automatically diff --git a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksTranspose.fs b/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksTranspose.fs deleted file mode 100644 index 92a60f38..00000000 --- a/benchmarks/GraphBLAS-sharp.Benchmarks/BenchmarksTranspose.fs +++ /dev/null @@ -1,68 +0,0 @@ -namespace GraphBLAS.FSharp.Benchmarks - -open GraphBLAS.FSharp -open GraphBLAS.FSharp.Algorithms -open BenchmarkDotNet.Attributes -open BenchmarkDotNet.Configs -open BenchmarkDotNet.Columns -open System.IO -open System -open System.Text.RegularExpressions -open Brahma.FSharp.OpenCL -open OpenCL.Net -open GraphBLAS.FSharp.IO - -[)>] -type TransposeBenchmarks() = - let mutable matrix = Unchecked.defaultof> - - //TODO fix me - (* - [] - member val OclContext = Unchecked.defaultof with get, set - member this.Context = - let (ClContext context) = this.OclContext - context - - [] - member val InputMatrixReader = Unchecked.defaultof with get, set - - [] - member this.BuildMatrix() = - let inputMatrix = this.InputMatrixReader.ReadMatrixReal(float) - - matrix <- - graphblas { - return! Matrix.switch CSR inputMatrix - >>= Matrix.synchronizeAndReturn - } - |> EvalGB.withClContext this.Context - |> EvalGB.runSync - - [] - member this.Transpose() = - Matrix.transpose matrix - |> EvalGB.withClContext this.Context - |> EvalGB.runSync - - [] - member this.ClearBuffers() = - this.Context.Provider.CloseAllBuffers() - - [] - member this.ClearContext() = - let (ClContext context) = this.OclContext - context.Provider.Dispose() - - static member AvaliableContextsProvider = Utils.avaliableContexts - - static member InputMatricesProvider = - "Common.txt" - |> Utils.getMatricesFilenames - |> Seq.map - (fun matrixFilename -> - match Path.GetExtension matrixFilename with - | ".mtx" -> MtxReader(Utils.getFullPathToMatrix "Common" matrixFilename) - | _ -> failwith "Unsupported matrix format" - ) -*) \ No newline at end of file From 4ea099c0db1a556da99aa20cc63b94a1f7e31674 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Fri, 28 Apr 2023 21:17:02 +0300 Subject: [PATCH 40/44] refactor: formatting --- tests/GraphBLAS-sharp.Tests/Program.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index ccee444f..13b19cb8 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -112,5 +112,4 @@ let allTests = |> testSequenced [] -let main argv = - allTests |> runTestsWithCLIArgs [] argv +let main argv = allTests |> runTestsWithCLIArgs [] argv From ecb4eb56668b7531037c7dee89be87a438633416 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sat, 29 Apr 2023 00:59:49 +0300 Subject: [PATCH 41/44] refactor: remove *.map2ToCOO --- src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs | 17 +------ .../Matrix/CSR/Map2.fs | 17 +------ .../Matrix/CSR/Matrix.fs | 9 ---- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 41 ++++------------- .../Backend/Matrix/Map.fs | 9 ++-- .../Backend/Matrix/Map2.fs | 37 +++------------ .../Backend/Matrix/SpGeMM/Expand.fs | 2 +- .../Backend/Vector/Map2.fs | 21 ++++++--- tests/GraphBLAS-sharp.Tests/Program.fs | 46 ++++++++----------- 9 files changed, 57 insertions(+), 142 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs index 49336bf9..0ca4148f 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map.fs @@ -81,7 +81,7 @@ module internal Map = resultBitmap, resultValues, resultRows, resultColumns - let runToCOO<'a, 'b when 'a: struct and 'b: struct and 'b: equality> + let run<'a, 'b when 'a: struct and 'b: struct and 'b: equality> (opAdd: Expr<'a option -> 'b option>) (clContext: ClContext) workGroupSize @@ -112,18 +112,3 @@ module internal Map = Rows = resultRows Columns = resultColumns Values = resultValues } - - let run<'a, 'b when 'a: struct and 'b: struct and 'b: equality> - (opAdd: Expr<'a option -> 'b option>) - (clContext: ClContext) - workGroupSize - = - - let mapToCOO = runToCOO opAdd clContext workGroupSize - - let toCSRInPlace = - Matrix.toCSRInPlace clContext workGroupSize - - fun (queue: MailboxProcessor<_>) allocationMode (matrix: ClMatrix.CSR<'a>) -> - mapToCOO queue allocationMode matrix - |> toCSRInPlace queue allocationMode diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs index 2d6cb681..41d0171b 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs @@ -215,7 +215,7 @@ module internal Map2 = processor.Post(Msg.CreateRunMsg<_, _>(kernel)) rowPositions, allValues - let runToCOO<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> + let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> (opAdd: Expr<'a option -> 'b option -> 'c option>) (clContext: ClContext) workGroupSize @@ -257,18 +257,3 @@ module internal Map2 = Rows = resultRows Columns = resultColumns Values = resultValues } - - let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (opAdd: Expr<'a option -> 'b option -> 'c option>) - (clContext: ClContext) - workGroupSize - = - - let elementwiseToCOO = runToCOO opAdd clContext workGroupSize - - let toCSRInPlace = - Matrix.toCSRInPlace clContext workGroupSize - - fun (queue: MailboxProcessor<_>) allocationMode (matrixLeft: ClMatrix.CSR<'a>) (matrixRight: ClMatrix.CSR<'b>) -> - elementwiseToCOO queue allocationMode matrixLeft matrixRight - |> toCSRInPlace queue allocationMode diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index 97824b6a..e5f89e44 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -61,14 +61,6 @@ module Matrix = let map2 = Map2.run - let map2AtLeastOneToCOO<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (clContext: ClContext) - (opAdd: Expr -> 'c option>) - workGroupSize - = - - Map2.AtLeastOne.runToCOO (Convert.atLeastOneToOption opAdd) clContext workGroupSize - let map2AtLeastOne<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> (clContext: ClContext) (opAdd: Expr -> 'c option>) @@ -77,7 +69,6 @@ module Matrix = Map2.AtLeastOne.run (Convert.atLeastOneToOption opAdd) clContext workGroupSize - let transposeInPlace (clContext: ClContext) workGroupSize = let toCOOInPlace = toCOOInPlace clContext workGroupSize diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index 7e174bd8..79061a81 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -264,10 +264,10 @@ module Matrix = fun (processor: MailboxProcessor<_>) allocationMode matrix -> match matrix with | ClMatrix.COO m -> mapCOO processor allocationMode m |> ClMatrix.COO - | ClMatrix.CSR m -> mapCSR processor allocationMode m |> ClMatrix.CSR + | ClMatrix.CSR m -> mapCSR processor allocationMode m |> ClMatrix.COO | ClMatrix.CSC m -> - (mapCSR processor allocationMode m.ToCSR).ToCSC - |> ClMatrix.CSC + (mapCSR processor allocationMode m.ToCSR) + |> ClMatrix.COO | _ -> failwith "Not yet implemented" let map2 (opAdd: Expr<'a option -> 'b option -> 'c option>) (clContext: ClContext) workGroupSize = @@ -292,47 +292,22 @@ module Matrix = | _ -> failwith "Matrix formats are not matching" let map2AtLeastOne (opAdd: Expr -> 'c option>) (clContext: ClContext) workGroupSize = - let COOElementwise = + let COOMap2 = COO.Matrix.map2AtLeastOne clContext opAdd workGroupSize - let CSRElementwise = + let CSRMap2 = CSR.Matrix.map2AtLeastOne clContext opAdd workGroupSize fun (processor: MailboxProcessor<_>) allocationMode matrix1 matrix2 -> match matrix1, matrix2 with | ClMatrix.COO m1, ClMatrix.COO m2 -> - COOElementwise processor allocationMode m1 m2 - |> ClMatrix.COO - | ClMatrix.CSR m1, ClMatrix.CSR m2 -> - CSRElementwise processor allocationMode m1 m2 - |> ClMatrix.CSR - | ClMatrix.CSC m1, ClMatrix.CSC m2 -> - (CSRElementwise processor allocationMode m1.ToCSR m2.ToCSR) - .ToCSC - |> ClMatrix.CSC - | _ -> failwith "Matrix formats are not matching" - - let map2AtLeastOneToCOO (opAdd: Expr -> 'c option>) (clContext: ClContext) workGroupSize = - let COOElementwise = - COO.Matrix.map2AtLeastOne clContext opAdd workGroupSize - - let CSRElementwise = - CSR.Matrix.map2AtLeastOneToCOO clContext opAdd workGroupSize - - let transposeCOOInPlace = - COO.Matrix.transposeInPlace clContext workGroupSize - - fun (processor: MailboxProcessor<_>) allocationMode matrix1 matrix2 -> - match matrix1, matrix2 with - | ClMatrix.COO m1, ClMatrix.COO m2 -> - COOElementwise processor allocationMode m1 m2 + COOMap2 processor allocationMode m1 m2 |> ClMatrix.COO | ClMatrix.CSR m1, ClMatrix.CSR m2 -> - CSRElementwise processor allocationMode m1 m2 + CSRMap2 processor allocationMode m1 m2 |> ClMatrix.COO | ClMatrix.CSC m1, ClMatrix.CSC m2 -> - CSRElementwise processor allocationMode m1.ToCSR m2.ToCSR - |> transposeCOOInPlace processor + (CSRMap2 processor allocationMode m1.ToCSR m2.ToCSR) |> ClMatrix.COO | _ -> failwith "Matrix formats are not matching" diff --git a/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map.fs index 508f7d75..6276019b 100644 --- a/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map.fs +++ b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map.fs @@ -113,7 +113,7 @@ let testFixturesMapNot case = createTestMap case false true (fun _ -> not) (=) (fun _ _ -> ArithmeticOperations.notOption) ] let notTests = - operationGPUTests "Backend.Matrix.map not tests" testFixturesMapNot + operationGPUTests "not" testFixturesMapNot let testFixturesMapAdd case = [ let context = case.TestContext.ClContext @@ -130,7 +130,7 @@ let testFixturesMapAdd case = createTestMap case 0uy 10uy (+) (=) ArithmeticOperations.addLeftConst ] let addTests = - operationGPUTests "Backend.Matrix.map add tests" testFixturesMapAdd + operationGPUTests "add" testFixturesMapAdd let testFixturesMapMul case = [ let context = case.TestContext.ClContext @@ -147,4 +147,7 @@ let testFixturesMapMul case = createTestMap case 0uy 10uy (*) (=) ArithmeticOperations.mulLeftConst ] let mulTests = - operationGPUTests "Backend.Matrix.map mul tests" testFixturesMapMul + operationGPUTests "mul" testFixturesMapMul + +let allTests = + testList "Map" [ addTests; mulTests; notTests ] diff --git a/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map2.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map2.fs index da0fd3c3..1a8e2dab 100644 --- a/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map2.fs +++ b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/Map2.fs @@ -151,36 +151,6 @@ let testFixturesMap2AddAtLeastOne case = let addAtLeastOneTests = operationGPUTests "Backend.Matrix.map2AtLeastOne add tests" testFixturesMap2AddAtLeastOne -let testFixturesMap2AddAtLeastOneToCOO case = - [ let context = case.TestContext.ClContext - let q = case.TestContext.Queue - q.Error.Add(fun e -> failwithf "%A" e) - - creatTestMap2Add case false (||) (=) ArithmeticOperations.boolSumAtLeastOne Matrix.map2AtLeastOneToCOO - creatTestMap2Add case 0 (+) (=) ArithmeticOperations.intSumAtLeastOne Matrix.map2AtLeastOneToCOO - - if Utils.isFloat64Available context.ClDevice then - creatTestMap2Add - case - 0.0 - (+) - Utils.floatIsEqual - ArithmeticOperations.floatSumAtLeastOne - Matrix.map2AtLeastOneToCOO - - creatTestMap2Add - case - 0.0f - (+) - Utils.float32IsEqual - ArithmeticOperations.float32SumAtLeastOne - Matrix.map2AtLeastOneToCOO - - creatTestMap2Add case 0uy (+) (=) ArithmeticOperations.byteSumAtLeastOne Matrix.map2AtLeastOneToCOO ] - -let addAtLeastOneToCOOTests = - operationGPUTests "Backend.Matrix.map2AtLeastOneToCOO add tests" testFixturesMap2AddAtLeastOneToCOO - let testFixturesMap2MulAtLeastOne case = [ let context = case.TestContext.ClContext let q = case.TestContext.Queue @@ -204,3 +174,10 @@ let testFixturesMap2MulAtLeastOne case = let mulAtLeastOneTests = operationGPUTests "Backend.Matrix.map2AtLeastOne multiplication tests" testFixturesMap2MulAtLeastOne + +let allTests = + testList + "Map2" + [ addTests + addAtLeastOneTests + mulAtLeastOneTests ] diff --git a/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs index 35db28f7..5f7c1b78 100644 --- a/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs +++ b/tests/GraphBLAS-sharp.Tests/Backend/Matrix/SpGeMM/Expand.fs @@ -220,7 +220,7 @@ let makeGeneralTest<'a when 'a: struct> zero isEqual opMul opAdd testFun (leftAr let createGeneralTest (zero: 'a) isEqual (opAddQ, opAdd) (opMulQ, opMul) testFun = testFun opAddQ opMulQ context Utils.defaultWorkGroupSize |> makeGeneralTest<'a> zero isEqual opMul opAdd - |> testPropertyWithConfig config $"test on %A{typeof<'a>}" + |> testPropertyWithConfig { config with endSize = 500 } $"test on %A{typeof<'a>}" let generalTests = [ createGeneralTest 0 (=) ArithmeticOperations.intAdd ArithmeticOperations.intMul Matrix.SpGeMM.expand diff --git a/tests/GraphBLAS-sharp.Tests/Backend/Vector/Map2.fs b/tests/GraphBLAS-sharp.Tests/Backend/Vector/Map2.fs index fee9103a..e5eadaa4 100644 --- a/tests/GraphBLAS-sharp.Tests/Backend/Vector/Map2.fs +++ b/tests/GraphBLAS-sharp.Tests/Backend/Vector/Map2.fs @@ -110,8 +110,7 @@ let addTestFixtures case = createTest case (=) false (||) ArithmeticOperations.boolSumOption Vector.map2 createTest case (=) 0uy (+) ArithmeticOperations.byteSumOption Vector.map2 ] -let addTests = - operationGPUTests "Backend.Vector.Map2 add tests" addTestFixtures +let addTests = operationGPUTests "add" addTestFixtures let mulTestFixtures case = let context = case.TestContext.ClContext @@ -125,8 +124,7 @@ let mulTestFixtures case = createTest case (=) false (&&) ArithmeticOperations.boolMulOption Vector.map2 createTest case (=) 0uy (*) ArithmeticOperations.byteMulOption Vector.map2 ] -let mulTests = - operationGPUTests "Backend.Vector.map2 mul tests" addTestFixtures +let mulTests = operationGPUTests "mul" addTestFixtures let addAtLeastOneTestFixtures case = let context = case.TestContext.ClContext @@ -141,7 +139,7 @@ let addAtLeastOneTestFixtures case = createTest case (=) 0uy (+) ArithmeticOperations.byteSumAtLeastOne Vector.map2AtLeastOne ] let addAtLeastOneTests = - operationGPUTests "Backend.Vector.Map2LeastOne add tests" addTestFixtures + operationGPUTests "addAtLeastOne" addTestFixtures let mulAtLeastOneTestFixtures case = let context = case.TestContext.ClContext @@ -156,7 +154,7 @@ let mulAtLeastOneTestFixtures case = createTest case (=) 0uy (*) ArithmeticOperations.byteMulAtLeastOne Vector.map2AtLeastOne ] let mulAtLeastOneTests = - operationGPUTests "Backend.Vector.Map2AtLeasOne mul tests" mulTestFixtures + operationGPUTests "mulAtLeastOne" mulTestFixtures let fillSubVectorComplementedQ<'a, 'b> value = <@ fun (left: 'a option) (right: 'b option) -> @@ -199,4 +197,13 @@ let complementedGeneralTestFixtures case = let complementedGeneralTests = - operationGPUTests "Backend.Vector.Map2Gen mask tests" complementedGeneralTestFixtures + operationGPUTests "mask" complementedGeneralTestFixtures + +let allTests = + testList + "Map" + [ addTests + mulTests + addAtLeastOneTests + mulAtLeastOneTests + complementedGeneralTests ] diff --git a/tests/GraphBLAS-sharp.Tests/Program.fs b/tests/GraphBLAS-sharp.Tests/Program.fs index 1bcc77c1..f3dada66 100644 --- a/tests/GraphBLAS-sharp.Tests/Program.fs +++ b/tests/GraphBLAS-sharp.Tests/Program.fs @@ -2,31 +2,19 @@ open Expecto open GraphBLAS.FSharp.Tests.Backend open GraphBLAS.FSharp.Tests -let hostTests = - testList - "Host" - [ Host.Matrix.FromArray2D.tests - Host.Matrix.Convert.tests - Host.IO.MtxReader.test ] - |> testSequenced - let matrixTests = testList - "Matrix tests" + "Matrix" [ Matrix.Convert.tests - Matrix.Map2.addTests - Matrix.Map2.addAtLeastOneTests - Matrix.Map2.mulAtLeastOneTests - Matrix.Map2.addAtLeastOneToCOOTests - Matrix.Map.notTests - Matrix.Map.addTests - Matrix.Map.mulTests - Matrix.SpGeMM.Expand.generalTests - Matrix.SpGeMM.Masked.tests + Matrix.Map2.allTests + Matrix.Map.allTests Matrix.Merge.allTests Matrix.Transpose.tests Matrix.RowsLengths.tests - Matrix.ByRows.tests ] + Matrix.ByRows.tests + + Matrix.SpGeMM.Expand.generalTests + Matrix.SpGeMM.Masked.tests ] |> testSequenced let commonTests = @@ -67,7 +55,7 @@ let commonTests = Common.Sort.Radix.allTests ] testList - "Common tests" + "Common" [ Common.Scatter.allTests Common.Gather.allTests Common.Merge.tests @@ -79,17 +67,13 @@ let commonTests = let vectorTests = testList - "Vector tests" + "Vector" [ Vector.SpMV.tests Vector.ZeroCreate.tests Vector.OfList.tests Vector.Copy.tests Vector.Convert.tests - Vector.Map2.addTests - Vector.Map2.mulTests - Vector.Map2.addAtLeastOneTests - Vector.Map2.mulAtLeastOneTests - Vector.Map2.complementedGeneralTests + Vector.Map2.allTests Vector.AssignByMask.tests Vector.AssignByMask.complementedTests Vector.Reduce.tests @@ -109,9 +93,17 @@ let deviceTests = algorithmsTests ] |> testSequenced +let hostTests = + testList + "Host" + [ Host.Matrix.FromArray2D.tests + Host.Matrix.Convert.tests + Host.IO.MtxReader.test ] + |> testSequenced + [] let allTests = - testList "All tests" [ deviceTests; hostTests ] + testList "All" [ deviceTests; hostTests ] |> testSequenced [] From dffcb5f338567916d1f9053720bfec8bf58a0d52 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sat, 29 Apr 2023 11:27:13 +0300 Subject: [PATCH 42/44] refactor: Matrix.map*, ClArray.choose --- README.md | 4 +- src/GraphBLAS-sharp.Backend/Common/ClArray.fs | 15 +++-- .../Matrix/CSR/Map2.fs | 18 +---- .../Matrix/CSR/Matrix.fs | 2 - src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 13 +++- .../Vector/Dense/Vector.fs | 20 ++---- .../Backend/Common/ClArray/Choose.fs | 67 +++++++++---------- 7 files changed, 64 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index c58f7839..6ddbc2c0 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ GraphBLAS# is a GPGPU-based [GraphBLAS](https://graphblas.org/)-like API impleme | Left of 't1 | Right of 't2 ``` - So, type of matrix-matrix elementwise oertion is ```Matrix> -> Matrix> -> (AtLeastOne<'t1,'t2> -> Option<'t3>) -> Matrix>```. -- No semirings. Just functions. Ofcourse one can implement semirings on the top of provided API. + So, type of matrix-matrix elementwise operation is ```Matrix> -> Matrix> -> (AtLeastOne<'t1,'t2> -> Option<'t3>) -> Matrix>```. +- No semirings. Just functions. Of course one can implement semirings on the top of provided API. - Minimal core: high-order functions allows us to minimaze core by functions unification. For example, such functions as matrix-matrix addition, matrix-matrix element-wise multiplication, masking all are partial case of `map2` function. ### Operations diff --git a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs index 9763db01..b104ca55 100644 --- a/src/GraphBLAS-sharp.Backend/Common/ClArray.fs +++ b/src/GraphBLAS-sharp.Backend/Common/ClArray.fs @@ -390,12 +390,19 @@ module ClArray = (prefixSum processor positions) .ToHostAndFree(processor) - let result = - clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) + if resultLength = 0 then + positions.Free processor + + None + else + let result = + clContext.CreateClArrayWithSpecificAllocationMode(allocationMode, resultLength) - assignValues processor sourceValues positions result + assignValues processor sourceValues positions result - result + positions.Free processor + + Some result let assignOption2 (op: Expr<'a -> 'b -> 'c option>) (clContext: ClContext) workGroupSize = diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs index 41d0171b..bfd5f161 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Map2.fs @@ -94,7 +94,7 @@ module internal Map2 = ///. ///. ///Should be a power of 2 and greater than 1. - let runToCOO<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> + let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> (opAdd: Expr<'a option -> 'b option -> 'c option>) (clContext: ClContext) workGroupSize @@ -135,22 +135,6 @@ module internal Map2 = Columns = resultColumns Values = resultValues } - let run<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> - (opAdd: Expr<'a option -> 'b option -> 'c option>) - (clContext: ClContext) - workGroupSize - = - - let map2ToCOO = runToCOO opAdd clContext workGroupSize - - let toCSRInPlace = - Matrix.toCSRInPlace clContext workGroupSize - - fun (queue: MailboxProcessor<_>) allocationMode (matrixLeft: ClMatrix.CSR<'a>) (matrixRight: ClMatrix.CSR<'b>) -> - map2ToCOO queue allocationMode matrixLeft matrixRight - |> toCSRInPlace queue allocationMode - - module AtLeastOne = let preparePositions<'a, 'b, 'c when 'a: struct and 'b: struct and 'c: struct and 'c: equality> (opAdd: Expr<'a option -> 'b option -> 'c option>) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs index e5f89e44..dd41f748 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/CSR/Matrix.fs @@ -10,8 +10,6 @@ open GraphBLAS.FSharp.Backend.Objects.ClMatrix open GraphBLAS.FSharp.Backend.Objects.ClContext open GraphBLAS.FSharp.Backend.Objects.ClVector open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions -open GraphBLAS.FSharp.Backend.Objects.ArraysExtensions -open GraphBLAS.FSharp.Backend.Objects.ClCell module Matrix = diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index 79061a81..0501c882 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -261,12 +261,16 @@ module Matrix = let mapCSR = CSR.Matrix.map opAdd clContext workGroupSize + let transposeCOO = + COO.Matrix.transposeInPlace clContext workGroupSize + fun (processor: MailboxProcessor<_>) allocationMode matrix -> match matrix with | ClMatrix.COO m -> mapCOO processor allocationMode m |> ClMatrix.COO | ClMatrix.CSR m -> mapCSR processor allocationMode m |> ClMatrix.COO | ClMatrix.CSC m -> (mapCSR processor allocationMode m.ToCSR) + |> transposeCOO processor |> ClMatrix.COO | _ -> failwith "Not yet implemented" @@ -277,6 +281,9 @@ module Matrix = let map2CSR = CSR.Matrix.map2 opAdd clContext workGroupSize + let transposeCOO = + COO.Matrix.transposeInPlace clContext workGroupSize + fun (processor: MailboxProcessor<_>) allocationMode matrix1 matrix2 -> match matrix1, matrix2 with | ClMatrix.COO m1, ClMatrix.COO m2 -> @@ -284,11 +291,11 @@ module Matrix = |> ClMatrix.COO | ClMatrix.CSR m1, ClMatrix.CSR m2 -> map2CSR processor allocationMode m1 m2 - |> ClMatrix.CSR + |> ClMatrix.COO | ClMatrix.CSC m1, ClMatrix.CSC m2 -> (map2CSR processor allocationMode m1.ToCSR m2.ToCSR) - .ToCSC - |> ClMatrix.CSC + |> transposeCOO processor + |> ClMatrix.COO | _ -> failwith "Matrix formats are not matching" let map2AtLeastOne (opAdd: Expr -> 'c option>) (clContext: ClContext) workGroupSize = diff --git a/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs index 756de4bb..97570dcc 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs @@ -156,18 +156,12 @@ module Vector = fun (processor: MailboxProcessor<_>) (vector: ClArray<'a option>) -> - let notEmpty = - (containsNonZero processor vector) - .ToHostAndFree processor + choose processor DeviceOnly vector + |> function + | Some values -> + let result = reduce processor values - if notEmpty then - let values = choose processor DeviceOnly vector + processor.Post(Msg.CreateFreeMsg<_>(values)) - let result = reduce processor values - - processor.Post(Msg.CreateFreeMsg<_>(values)) - - result - - else - clContext.CreateClCell Unchecked.defaultof<'a> + result + | None -> clContext.CreateClCell Unchecked.defaultof<'a> diff --git a/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Choose.fs b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Choose.fs index 7fa142dd..c79d035f 100644 --- a/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Choose.fs +++ b/tests/GraphBLAS-sharp.Tests/Backend/Common/ClArray/Choose.fs @@ -13,37 +13,31 @@ let workGroupSize = Utils.defaultWorkGroupSize let config = Utils.defaultConfig -let context = Context.defaultContext.ClContext - -let processor = defaultContext.Queue +let makeTest<'a, 'b> testContext mapFun isEqual choose (array: 'a []) = + let context = testContext.ClContext + let q = testContext.Queue -let makeTest<'a, 'b> testContext choose mapFun isEqual (array: 'a []) = if array.Length > 0 then - let context = testContext.ClContext - let q = testContext.Queue - - let clArray = - context.CreateClArrayWithSpecificAllocationMode(DeviceOnly, array) - - let (clResult: ClArray<'b>) = choose q HostInterop clArray - let hostResult = Array.zeroCreate clResult.Length + let clArray = context.CreateClArray array - q.PostAndReply(fun ch -> Msg.CreateToHostMsg(clResult, hostResult, ch)) - |> ignore + let (clResult: ClArray<'b> option) = choose q HostInterop clArray let expectedResult = Array.choose mapFun array - "Result should be the same" - |> Utils.compareArrays isEqual hostResult expectedResult + match clResult with + | Some clResult -> + let hostResult = clResult.ToHostAndFree testContext.Queue -let createTest<'a, 'b> testContext mapFun mapFunQ isEqual = - let context = testContext.ClContext + "Result should be the same" + |> Utils.compareArrays isEqual hostResult expectedResult + | None -> + "Result must be empty" + |> Expect.isTrue (expectedResult.Length = 0) - let choose = - ClArray.choose mapFunQ context workGroupSize - - makeTest<'a, 'b> testContext choose mapFun isEqual +let createTest<'a, 'b> testContext mapFun mapFunQ isEqual = + ClArray.choose mapFunQ testContext.ClContext workGroupSize + |> makeTest<'a, 'b> testContext mapFun isEqual |> testPropertyWithConfig config $"test on %A{typeof<'a>} -> %A{typeof<'b>}" let testFixtures testContext = @@ -61,7 +55,10 @@ let testFixtures testContext = let tests = TestCases.gpuTests "choose id" testFixtures -let makeTest2 isEqual opMap testFun (firstArray: 'a [], secondArray: 'a []) = +let makeTest2 testContext isEqual opMap testFun (firstArray: 'a [], secondArray: 'a []) = + let context = testContext.ClContext + let processor = testContext.Queue + if firstArray.Length > 0 && secondArray.Length > 0 then let expected = @@ -81,21 +78,23 @@ let makeTest2 isEqual opMap testFun (firstArray: 'a [], secondArray: 'a []) = "Results must be the same" |> Utils.compareArrays isEqual actual expected -let createTest2 (isEqual: 'a -> 'a -> bool) (opMapQ, opMap) testFun = - let testFun = - testFun opMapQ context Utils.defaultWorkGroupSize - - makeTest2 isEqual opMap testFun +let createTest2 testsContext (isEqual: 'a -> 'a -> bool) (opMapQ, opMap) testFun = + testFun opMapQ testsContext.ClContext Utils.defaultWorkGroupSize + |> makeTest2 testsContext isEqual opMap |> testPropertyWithConfig config $"test on %A{typeof<'a>}" -let tests2 = - [ createTest2 (=) ArithmeticOperations.intAdd ClArray.choose2 +let testsFixtures2 testContext = + let context = testContext.ClContext + + [ createTest2 testContext (=) ArithmeticOperations.intAdd ClArray.choose2 if Utils.isFloat64Available context.ClDevice then - createTest2 (=) ArithmeticOperations.floatAdd ClArray.choose2 + createTest2 testContext (=) ArithmeticOperations.floatAdd ClArray.choose2 - createTest2 (=) ArithmeticOperations.float32Add ClArray.choose2 - createTest2 (=) ArithmeticOperations.boolAdd ClArray.choose2 ] - |> testList "choose2 add" + createTest2 testContext (=) ArithmeticOperations.float32Add ClArray.choose2 + createTest2 testContext (=) ArithmeticOperations.boolAdd ClArray.choose2 ] + +let tests2 = + TestCases.gpuTests "choose2 add" testsFixtures2 let allTests = testList "Choose" [ tests; tests2 ] From 1e3b53cd5263746c9de26b383ef5dc2fee144212 Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sat, 29 Apr 2023 11:44:27 +0300 Subject: [PATCH 43/44] refactor: Dense.reduce --- src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs index 97570dcc..53f8de3e 100644 --- a/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs +++ b/src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs @@ -151,11 +151,7 @@ module Vector = let reduce = Reduce.reduce opAdd clContext workGroupSize - let containsNonZero = - ClArray.exists Predicates.isSome clContext workGroupSize - fun (processor: MailboxProcessor<_>) (vector: ClArray<'a option>) -> - choose processor DeviceOnly vector |> function | Some values -> From 45e4536ab9d5fc517629a84a124d461cbd383aeb Mon Sep 17 00:00:00 2001 From: IgorErin Date: Sat, 29 Apr 2023 16:03:57 +0300 Subject: [PATCH 44/44] refactor: Matrix.AtLeastOne --- src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs index 0501c882..b8df2c6c 100644 --- a/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs +++ b/src/GraphBLAS-sharp.Backend/Matrix/Matrix.fs @@ -305,6 +305,9 @@ module Matrix = let CSRMap2 = CSR.Matrix.map2AtLeastOne clContext opAdd workGroupSize + let COOTranspose = + COO.Matrix.transposeInPlace clContext workGroupSize + fun (processor: MailboxProcessor<_>) allocationMode matrix1 matrix2 -> match matrix1, matrix2 with | ClMatrix.COO m1, ClMatrix.COO m2 -> @@ -315,6 +318,7 @@ module Matrix = |> ClMatrix.COO | ClMatrix.CSC m1, ClMatrix.CSC m2 -> (CSRMap2 processor allocationMode m1.ToCSR m2.ToCSR) + |> COOTranspose processor |> ClMatrix.COO | _ -> failwith "Matrix formats are not matching"