Skip to content

Commit

Permalink
toSparse unsorted and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kirillgarbar committed Jun 2, 2024
1 parent fc0acd1 commit 050df59
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/GraphBLAS-sharp.Backend/Algorithms/BFS.fs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ module internal BFS =
let fillSubVectorInPlace =
Vector.assignByMaskInPlace (Mask.assign) clContext workGroupSize

let toSparse = Vector.toSparse clContext workGroupSize
let toSparse =
Vector.toSparseUnsorted clContext workGroupSize

let toDense = Vector.toDense clContext workGroupSize

Expand Down
56 changes: 56 additions & 0 deletions src/GraphBLAS-sharp.Backend/Vector/Dense/Vector.fs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,63 @@ module Vector =

valueCell.Free()

// TODO: toSparseUnsorted + bitonic probably would work faster
let toSparse<'a when 'a: struct> (clContext: ClContext) workGroupSize =
let scatterValues =
Common.Scatter.lastOccurrence clContext workGroupSize

let scatterIndices =
Common.Scatter.lastOccurrence clContext workGroupSize

let getBitmap =
Map.map (Map.option 1 0) clContext workGroupSize

let prefixSum =
Common.PrefixSum.standardExcludeInPlace clContext workGroupSize

let allIndices =
ClArray.init Map.id clContext workGroupSize

let allValues =
Map.map (Map.optionToValueOrZero Unchecked.defaultof<'a>) clContext workGroupSize

fun (processor: RawCommandQueue) allocationMode (vector: ClArray<'a option>) ->

let positions = getBitmap processor DeviceOnly vector

let resultLength =
(prefixSum processor positions)
.ToHostAndFree(processor)

// compute result indices
let resultIndices =
clContext.CreateClArrayWithSpecificAllocationMode<int>(allocationMode, resultLength)

let allIndices =
allIndices processor DeviceOnly vector.Length

scatterIndices processor positions allIndices resultIndices

allIndices.Free()

// compute result values
let resultValues =
clContext.CreateClArrayWithSpecificAllocationMode<'a>(allocationMode, resultLength)

let allValues = allValues processor DeviceOnly vector

scatterValues processor positions allValues resultValues

allValues.Free()

positions.Free()

{ Context = clContext
Indices = resultIndices
Values = resultValues
Size = vector.Length }

let toSparseUnsorted<'a when 'a: struct> (clContext: ClContext) workGroupSize =

let kernel =
<@ fun (ndRange: Range1D) (inputLength: int) (inputValues: ClArray<'a option>) (resultSize: ClCell<int>) (resultIndices: ClArray<int>) (resultValues: ClArray<'a>) ->
Expand Down
20 changes: 20 additions & 0 deletions src/GraphBLAS-sharp.Backend/Vector/Vector.fs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,26 @@ module Vector =
<| toSparse processor allocationMode vector
| ClVector.Sparse _ -> copy processor allocationMode vector

/// <summary>
/// Sparsifies the given vector if it is in a dense format.
/// If the given vector is already sparse, copies it.
/// Works faster than regular version, but indices of the sparse vector are unsorted.
/// </summary>
/// <param name="clContext">OpenCL context.</param>
/// <param name="workGroupSize">Should be a power of 2 and greater than 1.</param>
let toSparseUnsorted (clContext: ClContext) workGroupSize =
let toSparse =
Dense.Vector.toSparseUnsorted clContext workGroupSize

let copy = copy clContext workGroupSize

fun (processor: RawCommandQueue) allocationMode (vector: ClVector<'a>) ->
match vector with
| ClVector.Dense vector ->
ClVector.Sparse
<| toSparse processor allocationMode vector
| ClVector.Sparse _ -> copy processor allocationMode vector

/// <summary>
/// Densifies the given vector if it is in a sparse format.
/// If the given vector is already dense, copies it.
Expand Down
34 changes: 29 additions & 5 deletions tests/GraphBLAS-sharp.Tests/Backend/Vector/Convert.fs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ let wgSize = Constants.Common.defaultWorkGroupSize
let makeTest
formatFrom
(convertFun: RawCommandQueue -> AllocationFlag -> ClVector<'a> -> ClVector<'a>)
(convertFunUnsorted: option<RawCommandQueue -> AllocationFlag -> ClVector<'a> -> ClVector<'a>>)
isZero
case
(array: 'a [])
Expand All @@ -37,7 +38,7 @@ let makeTest

let actual =
let clVector = vector.ToDevice context
let convertedVector = convertFun q HostInterop clVector
let convertedVector = convertFun q DeviceOnly clVector

let res = convertedVector.ToHost q

Expand All @@ -56,6 +57,27 @@ let makeTest

Expect.equal actual expected "Vectors must be the same"

match convertFunUnsorted with
| None -> ()
| Some convertFunUnsorted ->
let clVector = vector.ToDevice context
let convertedVector = convertFunUnsorted q DeviceOnly clVector

let res = convertedVector.ToHost q

match res, expected with
| Vector.Sparse res, Vector.Sparse expected ->
let iv = Array.zip res.Indices res.Values
let resSorted = Array.sortBy (fun (i, v) -> i) iv
let indices, values = Array.unzip resSorted
Expect.equal indices expected.Indices "Indices must be the same"
Expect.equal values expected.Values "Values must be the same"
Expect.equal res.Size expected.Size "Size must be the same"
| _ -> ()

clVector.Dispose()
convertedVector.Dispose()

let testFixtures case =
let getCorrectnessTestName datatype formatFrom =
sprintf $"Correctness on %s{datatype}, %A{formatFrom} -> %A{case.Format}"
Expand All @@ -68,19 +90,21 @@ let testFixtures case =
match case.Format with
| Sparse ->
[ let convertFun = Vector.toSparse context wgSize
let convertFunUnsorted = Vector.toSparseUnsorted context wgSize

Utils.listOfUnionCases<VectorFormat>
|> List.map
(fun formatFrom ->
makeTest formatFrom convertFun ((=) 0) case
makeTest formatFrom convertFun (Some convertFunUnsorted) ((=) 0) case
|> testPropertyWithConfig config (getCorrectnessTestName "int" formatFrom))

let convertFun = Vector.toSparse context wgSize
let convertFunUnsorted = Vector.toSparseUnsorted context wgSize

Utils.listOfUnionCases<VectorFormat>
|> List.map
(fun formatFrom ->
makeTest formatFrom convertFun ((=) false) case
makeTest formatFrom convertFun (Some convertFunUnsorted) ((=) false) case
|> testPropertyWithConfig config (getCorrectnessTestName "bool" formatFrom)) ]
|> List.concat
| Dense ->
Expand All @@ -89,15 +113,15 @@ let testFixtures case =
Utils.listOfUnionCases<VectorFormat>
|> List.map
(fun formatFrom ->
makeTest formatFrom convertFun ((=) 0) case
makeTest formatFrom convertFun None ((=) 0) case
|> testPropertyWithConfig config (getCorrectnessTestName "int" formatFrom))

let convertFun = Vector.toDense context wgSize

Utils.listOfUnionCases<VectorFormat>
|> List.map
(fun formatFrom ->
makeTest formatFrom convertFun ((=) false) case
makeTest formatFrom convertFun None ((=) false) case
|> testPropertyWithConfig config (getCorrectnessTestName "bool" formatFrom)) ]
|> List.concat

Expand Down

0 comments on commit 050df59

Please sign in to comment.