-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PageRank #88
PageRank #88
Changes from 5 commits
faf242c
b278b7a
ebdb250
6f3819b
1ed601c
858cd82
0826562
b82fe68
c8f3042
0ab7361
97b6db4
f671a2e
6de410f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
namespace GraphBLAS.FSharp.Benchmarks.Algorithms.PageRank | ||
|
||
open System.IO | ||
open BenchmarkDotNet.Attributes | ||
open GraphBLAS.FSharp | ||
open GraphBLAS.FSharp.IO | ||
open Brahma.FSharp | ||
open Microsoft.FSharp.Core | ||
open GraphBLAS.FSharp.Objects.ArraysExtensions | ||
open GraphBLAS.FSharp.Benchmarks | ||
open GraphBLAS.FSharp.Objects | ||
|
||
[<AbstractClass>] | ||
[<IterationCount(10)>] | ||
[<WarmupCount(3)>] | ||
[<Config(typeof<Configs.Matrix>)>] | ||
type Benchmarks( | ||
buildFunToBenchmark, | ||
converter: string -> float32, | ||
binaryConverter, | ||
buildMatrix) | ||
= | ||
|
||
let mutable funToBenchmark = None | ||
let mutable matrix = Unchecked.defaultof<ClMatrix<float32>> | ||
let mutable matrixPrepared = Unchecked.defaultof<PageRankMatrix<float32>> | ||
let mutable matrixHost = Unchecked.defaultof<_> | ||
|
||
let accuracy = 0.00000001f | ||
|
||
member val Result = Unchecked.defaultof<ClVector<float32>> with get,set | ||
|
||
[<ParamsSource("AvailableContexts")>] | ||
member val OclContextInfo = Unchecked.defaultof<Utils.BenchmarkContext * int> with get, set | ||
|
||
[<ParamsSource("InputMatrixProvider")>] | ||
member val InputMatrixReader = Unchecked.defaultof<MtxReader> with get, set | ||
|
||
member this.OclContext = (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 = "" | ||
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.PageRank() = | ||
this.Result <- this.FunToBenchmark this.Processor matrixPrepared accuracy | ||
|
||
member this.ClearInputMatrix() = | ||
matrix.Dispose this.Processor | ||
|
||
member this.ClearPreparedMatrix() = | ||
matrixPrepared.Dispose this.Processor | ||
|
||
member this.ClearResult() = this.Result.Dispose this.Processor | ||
|
||
member this.ReadMatrix() = | ||
let converter = | ||
match this.InputMatrixReader.Field with | ||
| Pattern -> binaryConverter | ||
| _ -> converter | ||
|
||
matrixHost <- this.InputMatrixReader.ReadMatrix converter | ||
|
||
member this.LoadMatrixToGPU() = | ||
matrix <- buildMatrix this.OclContext matrixHost | ||
|
||
member this.PrepareMatrix() = | ||
matrixPrepared <- Algorithms.PageRank.prepareMatrix this.OclContext this.WorkGroupSize this.Processor matrix | ||
|
||
abstract member GlobalSetup : unit -> unit | ||
|
||
abstract member IterationCleanup : unit -> unit | ||
|
||
abstract member GlobalCleanup : unit -> unit | ||
|
||
abstract member Benchmark : unit -> unit | ||
|
||
type PageRankWithoutTransferBenchmarkFloat32() = | ||
|
||
inherit Benchmarks( | ||
Algorithms.PageRank.run, | ||
float32, | ||
(fun _ -> float32 <| Utils.nextInt (System.Random())), | ||
(fun context matrix -> ClMatrix.CSR <| matrix.ToCSR.ToDevice context)) | ||
|
||
static member InputMatrixProvider = | ||
Benchmarks.InputMatrixProviderBuilder "BFSBenchmarks.txt" | ||
|
||
[<GlobalSetup>] | ||
override this.GlobalSetup() = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've always thought about it. Don't you need to make the preparatory methods blocking? Then is it possible to avoid blocking in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a good idea to block after preparotory methods in case some of them are not blocking by itself, but blocking in the |
||
this.ReadMatrix() | ||
this.LoadMatrixToGPU() | ||
this.Processor.PostAndReply(Msg.MsgNotifyMe) | ||
this.PrepareMatrix() | ||
this.ClearInputMatrix() | ||
|
||
[<IterationCleanup>] | ||
override this.IterationCleanup() = | ||
this.ClearResult() | ||
|
||
[<GlobalCleanup>] | ||
override this.GlobalCleanup() = | ||
this.ClearPreparedMatrix() | ||
|
||
[<Benchmark>] | ||
override this.Benchmark() = | ||
this.PageRank() | ||
this.Processor.PostAndReply(Msg.MsgNotifyMe) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,3 +19,8 @@ module Algorithms = | |
|
||
module SSSP = | ||
let run = SSSP.run | ||
|
||
module PageRank = | ||
let run = PageRank.run | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think documentation is needed. At least we should say that matrix has to be prepared first by calling prepareMatrix method. |
||
|
||
let prepareMatrix = PageRank.prepareMatrix | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Always calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do we inform the user about this need? What guarantees are there that this condition will be met? We cannot afford to set such semantic traps at any level of abstraction. If a precondition arises, it must be expressed in types so that the user is not able to pass an unprepared matrix. Otherwise, any mention of functional style should be removed from the title of our work "graphblas in functional style". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe we do not need to inform user about it because it is not our goal to provide PageRank implementation but to provide enough building blocks to implement it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gsvgit What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ready-to-use garph analysis algorithms should be a part of library. It is the next (possibli highest) leyer of our solution (look at LaGraph). So, implementations of BFS, PAgeRank and other algorithms should be as clear and documented, as possible. Anyway, even basic implmenetation should be a clear anough to be a starting point for those who want ot develop new algorithms using provieed building blocks. Regarding types. I agree with @IgorErin: if we can express something using types, we should do it. Ofcourse we should find the best way to do it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are predefined constants in Expecto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still, why is it necessary separately? Perhaps we need to create a module with constants and actions on them in order to avoid mistakes in the future?
Abstract types could also be used here, so that they could be used only with the help of this most magical module.