Skip to content

Commit dec5ba8

Browse files
committed
Add half of mxv algo; add fair algebraic structures
1 parent ff5d55c commit dec5ba8

23 files changed

Lines changed: 407 additions & 251 deletions

File tree

src/GraphBLAS-sharp/AlgebraicStructures.fs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,58 @@ type BinaryOp<'a, 'b, 'c> = BinaryOp of Expr<'a -> 'b -> 'c>
88
type ClosedUnaryOp<'a> = ClosedUnaryOp of Expr<'a -> 'a>
99
type ClosedBinaryOp<'a> = ClosedBinaryOp of Expr<'a -> 'a -> 'a>
1010

11-
// associative closed bin op (magma with associative)
11+
/// Magma with associative (magma is set with closed binary operator)
1212
type ISemigroup<'a> =
13-
abstract Plus: ClosedBinaryOp<'a>
13+
abstract Op: ClosedBinaryOp<'a>
1414

1515
/// Semigroup with identity
1616
type IMonoid<'a> =
17-
inherit ISemigroup<'a>
17+
abstract Plus: ClosedBinaryOp<'a>
1818
abstract Zero: 'a
1919

20+
/// Monoid with associative binary operator,
21+
/// for wich Zero is annihilator
2022
type ISemiring<'a> =
21-
inherit IMonoid<'a>
23+
abstract Zero: 'a
24+
abstract Plus: ClosedBinaryOp<'a>
2225
abstract Times: ClosedBinaryOp<'a>
2326

27+
type Semigroup<'a> =
28+
{
29+
AssociativeOp: ClosedBinaryOp<'a>
30+
}
31+
32+
interface ISemigroup<'a> with
33+
member this.Op = this.AssociativeOp
34+
35+
type Monoid<'a> =
36+
{
37+
AssociativeOp: ClosedBinaryOp<'a>
38+
Identity: 'a
39+
}
40+
41+
interface ISemigroup<'a> with
42+
member this.Op = this.AssociativeOp
43+
44+
interface IMonoid<'a> with
45+
member this.Plus = this.AssociativeOp
46+
member this.Zero = this.Identity
47+
48+
type Semiring<'a> =
49+
{
50+
PlusMonoid: Monoid<'a>
51+
TimesSemigroup: Semigroup<'a>
52+
}
53+
54+
interface IMonoid<'a> with
55+
member this.Zero = this.PlusMonoid.Identity
56+
member this.Plus = this.PlusMonoid.AssociativeOp
57+
58+
interface ISemiring<'a> with
59+
member this.Times = this.TimesSemigroup.AssociativeOp
60+
member this.Zero = this.PlusMonoid.Identity
61+
member this.Plus = this.PlusMonoid.AssociativeOp
62+
2463
(*
2564
мотивация:
2665
хотим, чтобы ноль был нулем (даже если он явно в матрице хранится)

src/GraphBLAS-sharp/Backend/COOMatrix/EWiseAdd.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ open GraphBLAS.FSharp.Backend.Common
66
open GraphBLAS.FSharp.Backend.COOMatrix.Utilities
77

88
module internal EWiseAdd =
9-
let private runNonEmpty (matrixLeft: COOMatrix<'a>) (matrixRight: COOMatrix<'a>) (mask: Mask2D option) (semiring: ISemiring<'a>) = opencl {
9+
let private runNonEmpty (matrixLeft: COOMatrix<'a>) (matrixRight: COOMatrix<'a>) (mask: Mask2D option) (monoid: IMonoid<'a>) = opencl {
1010
let! allRows, allColumns, allValues = merge matrixLeft matrixRight mask
1111

12-
let (ClosedBinaryOp plus) = semiring.Plus
12+
let (ClosedBinaryOp plus) = monoid.Plus
1313
let! rawPositions = preparePositions allRows allColumns allValues plus
1414
let! resultRows, resultColumns, resultValues = setPositions allRows allColumns allValues rawPositions
1515

@@ -22,7 +22,7 @@ module internal EWiseAdd =
2222
}
2323
}
2424

25-
let run (matrixLeft: COOMatrix<'a>) (matrixRight: COOMatrix<'a>) (mask: Mask2D option) (semiring: ISemiring<'a>) =
25+
let run (matrixLeft: COOMatrix<'a>) (matrixRight: COOMatrix<'a>) (mask: Mask2D option) (monoid: IMonoid<'a>) =
2626
if matrixLeft.Values.Length = 0 then
2727
opencl {
2828
let! resultRows = Copy.run matrixRight.Rows
@@ -54,4 +54,4 @@ module internal EWiseAdd =
5454
}
5555

5656
else
57-
runNonEmpty matrixLeft matrixRight mask semiring
57+
runNonEmpty matrixLeft matrixRight mask monoid

src/GraphBLAS-sharp/Backend/COOMatrix/Utilities/SetPositions.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ module internal SetPositions =
3636

3737
let resultLength = Array.zeroCreate 1
3838

39-
do! PrefixSum.run positions resultLength
39+
do! PrefixSum.runInplace positions resultLength
4040
let! _ = ToHost resultLength
4141
let resultLength = resultLength.[0]
4242

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ module internal SetPositions =
3030

3131
let resultLength = Array.zeroCreate 1
3232

33-
do! PrefixSum.run positions resultLength
33+
do! PrefixSum.runInplace positions resultLength
3434
let! _ = ToHost resultLength
3535
let resultLength = resultLength.[0]
3636

src/GraphBLAS-sharp/Backend/CSRMatrix/Mxv.fs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,70 @@ open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
44
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
55
open GraphBLAS.FSharp
66
open GraphBLAS.FSharp.Backend.Common
7+
open Brahma.OpenCL
78

89
module internal Mxv =
9-
()
10+
let pcsr (matrix: CSRMatrix<'a>) (vector: BitmapVector<'a>) mask (semiring: ISemiring<'a>) = opencl {
11+
let (ClosedBinaryOp plus) = semiring.Plus
12+
let (ClosedBinaryOp times) = semiring.Times
13+
14+
let matrixLength = matrix.Values.Length
15+
16+
let kernel1 =
17+
<@
18+
fun (ndRange: _1D)
19+
(matrixColumns: int[])
20+
(matrixValues: 'a[])
21+
(vectorBitmap: bool[])
22+
(vectorValues: 'a[])
23+
(intermediateArray: 'a[]) ->
24+
25+
let i = ndRange.GlobalID0
26+
if i < matrixLength && vectorBitmap.[i] then
27+
let value = matrixValues.[i]
28+
let column = matrixColumns.[i]
29+
intermediateArray.[i] <- (%times) value vectorValues.[column]
30+
@>
31+
32+
let kernel2 =
33+
<@
34+
fun (ndRange: _1D)
35+
(intermediateArray: 'a[])
36+
(matrixPtr: int[])
37+
(outputVector: 'a[]) ->
38+
39+
let gid = ndRange.GlobalID0
40+
let lid = ndRange.LocalID0
41+
42+
let localPtr = localArray<int> (Utils.workGroupSize + 1)
43+
localPtr.[lid] <- matrixPtr.[gid]
44+
if lid = 0 then
45+
localPtr.[Utils.workGroupSize] <- matrixPtr.[gid + Utils.workGroupSize]
46+
barrier ()
47+
@>
48+
49+
let intermediateArray = Array.zeroCreate<'a> matrixLength
50+
do! RunCommand kernel1 <| fun kernelPrepare ->
51+
let range = _1D(Utils.workSize matrixLength, Utils.workGroupSize)
52+
kernelPrepare
53+
range
54+
matrix.ColumnIndices
55+
matrix.Values
56+
vector.Bitmap
57+
vector.Values
58+
intermediateArray
59+
60+
let outputVector = Array.zeroCreate<'a> matrix.RowCount
61+
do! RunCommand kernel2 <| fun kernelPrepare ->
62+
let range = _1D(Utils.workSize matrixLength, Utils.workGroupSize)
63+
kernelPrepare
64+
range
65+
intermediateArray
66+
matrix.RowPointers
67+
outputVector
68+
69+
return {
70+
Bitmap = vector.Bitmap
71+
Values = outputVector
72+
}
73+
}

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@ namespace GraphBLAS.FSharp.Backend.Common
22

33
open Brahma.OpenCL
44
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
5-
open Utils
65

7-
module internal Copy =
8-
let runNotEmpty (inputArray: 'a[]) = opencl {
6+
module internal rec Copy =
7+
let run (inputArray: 'a[]) =
8+
if inputArray.Length = 0 then
9+
opencl { return [||] }
10+
else
11+
runNotEmpty inputArray
12+
13+
let private runNotEmpty (inputArray: 'a[]) = opencl {
914
let inputArrayLength = inputArray.Length
1015
let copy =
1116
<@
@@ -21,9 +26,7 @@ module internal Copy =
2126
let outputArray = Array.zeroCreate inputArray.Length
2227

2328
do! RunCommand copy <| fun kernelPrepare ->
24-
let ndRange = _1D(workSize inputArray.Length, workGroupSize)
29+
let ndRange = _1D(Utils.workSize inputArray.Length, Utils.workGroupSize)
2530
kernelPrepare ndRange inputArray outputArray
2631
return outputArray
2732
}
28-
29-
let run (inputArray: 'a[]) = if inputArray.Length = 0 then opencl { return [||] } else runNotEmpty inputArray

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

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,32 @@ namespace GraphBLAS.FSharp.Backend.Common
22

33
open Brahma.OpenCL
44
open Brahma.FSharp.OpenCL.WorkflowBuilder.Basic
5-
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
65

7-
// functions in mudule could be named run\get\if\it\t
8-
// like mentioned here https://www.reddit.com/r/fsharp/comments/5kvsyk/modules_or_namespaces/dbt0zf7?utm_source=share&utm_medium=web2x&context=3
9-
module internal PrefixSum =
10-
let scan (inputArray: int[]) (inputArrayLength: int) (vertices: int[]) (verticesLength: int) (totalSum: int[]) = opencl {
6+
module internal rec PrefixSum =
7+
let runInplace (inputArray: int[]) (totalSum: int[]) = opencl {
8+
let workGroupSize = Utils.workGroupSize
9+
10+
let firstVertices = Array.zeroCreate <| (inputArray.Length - 1) / workGroupSize + 1
11+
let secondVertices = Array.zeroCreate <| (firstVertices.Length - 1) / workGroupSize + 1
12+
let mutable verticesArrays = firstVertices, secondVertices
13+
let swap (a, b) = (b, a)
14+
15+
let mutable verticesLength = (inputArray.Length - 1) / workGroupSize + 1
16+
let mutable bunchLength = workGroupSize
17+
18+
do! scan inputArray inputArray.Length (fst verticesArrays) verticesLength totalSum
19+
while verticesLength > 1 do
20+
let fstVertices = fst verticesArrays
21+
let sndVertices = snd verticesArrays
22+
do! scan fstVertices verticesLength sndVertices ((verticesLength - 1) / workGroupSize + 1) totalSum
23+
do! update inputArray inputArray.Length fstVertices bunchLength
24+
25+
bunchLength <- bunchLength * workGroupSize
26+
verticesArrays <- swap verticesArrays
27+
verticesLength <- (verticesLength - 1) / workGroupSize + 1
28+
}
29+
30+
let private scan (inputArray: int[]) (inputArrayLength: int) (vertices: int[]) (verticesLength: int) (totalSum: int[]) = opencl {
1131
let workGroupSize = Utils.workGroupSize
1232

1333
let scan =
@@ -62,7 +82,7 @@ module internal PrefixSum =
6282
totalSum
6383
}
6484

65-
let update (inputArray: int[]) (inputArrayLength: int) (vertices: int[]) (bunchLength: int) = opencl {
85+
let private update (inputArray: int[]) (inputArrayLength: int) (vertices: int[]) (bunchLength: int) = opencl {
6686
let workGroupSize = Utils.workGroupSize
6787

6888
let update =
@@ -83,30 +103,3 @@ module internal PrefixSum =
83103
inputArray
84104
vertices
85105
}
86-
87-
// Changes received arrays
88-
let run (inputArray: int[]) (totalSum: int[]) = opencl {
89-
let workGroupSize = Utils.workGroupSize
90-
91-
let firstVertices = Array.zeroCreate <| (inputArray.Length - 1) / workGroupSize + 1
92-
let secondVertices = Array.zeroCreate <| (firstVertices.Length - 1) / workGroupSize + 1
93-
let mutable verticesArrays = firstVertices, secondVertices
94-
let swap (a, b) = (b, a)
95-
96-
let mutable verticesLength = (inputArray.Length - 1) / workGroupSize + 1
97-
let mutable bunchLength = workGroupSize
98-
99-
do! scan inputArray inputArray.Length (fst verticesArrays) verticesLength totalSum
100-
while verticesLength > 1 do
101-
let fstVertices = fst verticesArrays
102-
let sndVertices = snd verticesArrays
103-
do! scan fstVertices verticesLength sndVertices ((verticesLength - 1) / workGroupSize + 1) totalSum
104-
do! update inputArray inputArray.Length fstVertices bunchLength
105-
106-
bunchLength <- bunchLength * workGroupSize
107-
verticesArrays <- swap verticesArrays
108-
verticesLength <- (verticesLength - 1) / workGroupSize + 1
109-
}
110-
111-
// сделать не inplace prefixSum
112-
// если функции вспомогательные, то лучше сделат их private

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ module internal RemoveDuplicates =
3737
kernelPrepare ndRange array bitmap
3838

3939
let resultLength = Array.zeroCreate 1
40-
do! PrefixSum.run bitmap resultLength
40+
do! PrefixSum.runInplace bitmap resultLength
4141
let! _ = ToHost resultLength
4242
let resultLength = resultLength.[0]
4343

src/GraphBLAS-sharp/GraphblasEvaluation.fs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ type GraphblasContext =
1212
type GraphblasEvaluation<'a> = EvalGB of (GraphblasContext -> 'a)
1313

1414
module EvalGB =
15-
let defaultEnv = {
16-
ClContext = OpenCLEvaluationContext()
17-
}
15+
let defaultEnv = { ClContext = OpenCLEvaluationContext() }
1816

1917
let private runCl env (OpenCLEvaluation f) = f env
2018

src/GraphBLAS-sharp/Helpers.fs

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

3-
open Brahma.FSharp.OpenCL.WorkflowBuilder.Evaluation
4-
open OpenCL.Net
5-
open System.Text.RegularExpressions
6-
73
[<AutoOpen>]
84
module Helpers =
95
let inline (!>) (x: ^a) : ^b = (^a: (static member op_Implicit : ^a -> ^b) x)
106

117
let inline (^) f x = f x
12-
13-
module Utils =
14-
let avaliableContexts (platformRegex: string) =
15-
let mutable e = ErrorCode.Unknown
16-
Cl.GetPlatformIDs &e
17-
|> Array.collect (fun platform -> Cl.GetDeviceIDs(platform, DeviceType.All, &e))
18-
|> Seq.ofArray
19-
|> Seq.distinctBy (fun device -> Cl.GetDeviceInfo(device, DeviceInfo.Name, &e).ToString())
20-
|> Seq.filter
21-
(fun device ->
22-
let platform = Cl.GetDeviceInfo(device, DeviceInfo.Platform, &e).CastTo<Platform>()
23-
let platformName = Cl.GetPlatformInfo(platform, PlatformInfo.Name, &e).ToString()
24-
(Regex platformRegex).IsMatch platformName
25-
)
26-
|> Seq.map
27-
(fun device ->
28-
let platform = Cl.GetDeviceInfo(device, DeviceInfo.Platform, &e).CastTo<Platform>()
29-
let platformName = Cl.GetPlatformInfo(platform, PlatformInfo.Name, &e).ToString()
30-
let deviceType = Cl.GetDeviceInfo(device, DeviceInfo.Type, &e).CastTo<DeviceType>()
31-
OpenCLEvaluationContext(platformName, deviceType)
32-
)

0 commit comments

Comments
 (0)