-
Notifications
You must be signed in to change notification settings - Fork 38
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
New implementations of kernel 2 and 3 for graph500 #388
base: main
Are you sure you want to change the base?
New implementations of kernel 2 and 3 for graph500 #388
Conversation
let rec run_dijkstra g v intree parents (distance : float array) = | ||
match (is_tree_complete intree v) with | ||
| true -> (parents, distance) | ||
| false -> begin |
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.
I think an if-then-else
would be cleaner here than match ... with true -> ... | false -> ...
.
if is_tree_complete intree v then
(parents, distance)
else begin
...
end
@@ -0,0 +1,3 @@ | |||
val to_file : filename:string -> 'a -> unit | |||
|
|||
val from_file : string -> 'a |
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.
I believe the Marshal
usage came from previous work, but it is rather unsafe as it stands, because it doesn't (and cannot) check that the value returned is of the correct type. You could make it safer in a number of ways. I'd perhaps recommend finding a library that offers a type safe version of marshaling/serialization/pickling.
let nvertices = SparseGraphSeq.num_vertices g in | ||
let parent_arr = Array.init nvertices (fun _ -> -1) in | ||
let discovery_arr = Array.init nvertices (fun _ -> false) in | ||
let q = ref (Queue.create ()) in |
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.
This use of ref
seems superfluous. This could be just let q = Queue.create () in ...
and then references of !q
can be replaced with q
in the code that follows.
|
||
let () = | ||
Random.self_init (); | ||
Arg.parse [] (fun filename -> files := filename::!files) usage_msg; |
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.
For a very simple program like this, one could parse the command line arguments using a match expression:
match Sys.argv with
| [| _; sparse_graph_filename; samples_input_filename |] ->
...
| _ ->
Printf.eprintf "Usage: %s <...> <...>" (Filename.basename Sys.executable_name)
But there are also many libraries for parsing command line arguments that can e.g. provide completion.
if sparse_graph_input_filename = "" then begin | ||
Printf.eprintf "Must provide sparse graph input file argument.\n"; exit 1 | ||
end; | ||
if sparse_graph_input_filename = "" then begin |
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.
This should probably refer to samples_input_filename
?
|
||
let dijkstra g start = | ||
let nvertices = SparseGraphSeq.num_vertices g in | ||
let distance = Array.init nvertices (fun _ -> Float.infinity) in |
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.
Array.make nvertices Float.infinity
would be a bit simpler here.
(** Takes a sparse graph g and a vertex v and returns the next edgenode | ||
res in the edgenode list of v and changes the state of g with res removed | ||
from the edgenode list of v. *) | ||
val get_next_edgenode : t -> vertex -> (vertex * weight) |
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.
It could make sense to introduce a type like
type edgenode = {vertex: vertex; weight: weight}
rather than use a tuple.
Is this worthwhile to pickup again and get it merged @polytypic @Sudha247 @punchagan ? |
Introduction
This PR is a follow-up to #371 . There are 4 major addtions to graph500 in this PR.
Search Keys Sampler
The search key sampler produces 64 sample search key for vertices that kernel 2 and kernel 3 will start at. These sample search keys are chosen such that they have no self-loops. Given that
sparse.data
has been produced by kernel 1, the sample search key data is produced as follows.Kernel 1 Update
With this PR, we can now output the sparse graph produced by kernel 1 to a file. To do so we use the
-o
flag followed by the name of the output file. For example, the following command will convert the edge representation inedges.data
to an adjacency-list sparse graph representation insparse.data
.Note About running
kernel[2,3]_run.exe
andkernel[2,3]_run_multicore.exe
In order to run the executable wrappers for kernel 2 and 3 we have to provide
sparse.data
andsamples.data
as inputs in a specific order. The following example with sequential kernel 2 make this clear.For multicore kernel 2 we would do the same thing but we can also specify the number of domains using the flag
-ndmoains
followed by the number of domains as follows.kernel 3 is obviously used in the same way.
Note: The output flag is important in kernel 1 because the sparse graph representation in
sparse.data
has to be fed into kernel 2 and kernel 3. The outputs of kernel 2 and kernel 3 don't need to be used for now so their executables do not have an optional output flag.Performance
Note: I have a four-core machine.
Kernel 2
Kernel 2 has both a parallel and a sequential version. The difference between the sequential and parallel versions is how the samples array is operated upon. It's operated upon sequentially and in parallel respectively. I ran sequential kernel 2 on my machine with a graph of scale=20. This produced the following results.
My machine
The results for the parallel version of kernel 2 on the same graph were the following.
Godel
I omitted the sequential version on godel because I didn't think it would be really useful here.
Kernel 3
Currently kernel 3 runs in quadratic time but I think it can be improved by using a priority-queue data structure in place of the current data structure from which the min can only be extracted in linear time. Because of this, I have chosen to let scale=15 for the tests below.
The difference between the sequential and parallel versions of kernel 3 is essentially the same as in kernel 2.
My machine
Godel
Omitted the sequential version here too.