Skip to content

Commit f292c49

Browse files
authored
Merge pull request #513 from JuliaParallel/jps/docs-graphvizext
logging/viz: Some fixes, and more docstrings
2 parents ce80375 + e7d69bb commit f292c49

File tree

11 files changed

+112
-31
lines changed

11 files changed

+112
-31
lines changed

Diff for: docs/Project.toml

+3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
[deps]
22
Dagger = "d58978e5-989f-55fb-8d15-ea34adc7bf54"
33
DaggerWebDash = "cfc5aa84-1a2a-41ab-b391-ede92ecae40c"
4+
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
45
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
6+
GraphViz = "f526b714-d49f-11e8-06ff-31ed36ee7ee0"
7+
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
58
TimespanLogging = "a526e669-04d3-4846-9525-c66122c55f63"
69

710
[compat]

Diff for: docs/make.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
using Dagger, TimespanLogging, DaggerWebDash
1+
using Dagger, TimespanLogging, DaggerWebDash, GraphViz, Plots, DataFrames
2+
const GraphVizExt = something(Base.get_extension(Dagger, :GraphVizExt))
3+
const PlotsExt = something(Base.get_extension(Dagger, :PlotsExt))
24
using Documenter
35
import Documenter.Remotes: GitHub
46

57
makedocs(;
6-
modules = [Dagger, TimespanLogging, DaggerWebDash],
8+
modules = [Dagger, TimespanLogging, DaggerWebDash, GraphVizExt, PlotsExt],
79
authors = "JuliaParallel and contributors",
810
repo = GitHub("JuliaParallel", "Dagger.jl"),
911
sitename = "Dagger.jl",

Diff for: docs/src/api-timespanlogging/functions.md

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ Pages = ["functions.md"]
1212
timespan_start
1313
timespan_finish
1414
get_logs!
15-
make_timespan
1615
```
1716

1817
## Logging Metric Functions

Diff for: docs/src/api-timespanlogging/types.md

-6
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ LocalEventLog
1414
NoOpLog
1515
```
1616

17-
## Event Types
18-
```@docs
19-
Event
20-
```
21-
2217
## Built-in Event Types
2318
```@docs
2419
Events.CoreMetrics
@@ -31,4 +26,3 @@ Events.EventSaturation
3126
Events.DebugMetrics
3227
Events.LogWindow
3328
```
34-
```

Diff for: docs/src/logging-visualization.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ by libraries or directly by the user, using multiple dispatch on
1515
identifying the rendering mode to use. From the user's perspective, `show_logs`
1616
and `render_logs` take not a `Val` but a raw `Symbol`, which will be internally
1717
converted to a `Val` for dispatch purposes
18-
(i.e. `render_logs(logs::Dict, :myrenderer)` ->
19-
`render_logs(logs, Val{:myrenderer}())`).
18+
(i.e. `render_logs(logs::Dict, :myrenderer)` -> `render_logs(logs, Val{:myrenderer}())`).
2019

2120
Built-in rendering support exists for:
2221
- `render_logs(logs, :graphviz)` to generate a graph diagram of executed tasks and their dependencies

Diff for: ext/GraphVizExt.jl

+18-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ end
99
import Dagger
1010
import Dagger: EagerThunk, Chunk, Processor
1111
import Dagger.TimespanLogging: Timespan
12-
import Graphs: SimpleDiGraph, add_edge!, add_vertex!, inneighbors, outneighbors, vertices, is_directed, edges, nv
12+
import Graphs: SimpleDiGraph, add_edge!, add_vertex!, inneighbors, outneighbors, vertices, is_directed, edges, nv, src, dst
1313

1414
function pretty_time(t; digits=3)
1515
r(t) = round(t; digits)
@@ -23,6 +23,23 @@ function pretty_time(t; digits=3)
2323
"$(r(t)) ns"
2424
end
2525
end
26+
27+
"""
28+
Dagger.render_logs(logs::Dict, ::Val{:graphviz}; disconnected=false,
29+
color_by=:fn, layout_engine="dot",
30+
times::Bool=true, times_digits::Integer=3)
31+
32+
Render a graph of the task dependencies and data dependencies in `logs` using GraphViz.
33+
34+
Requires the following events enabled in `enable_logging!`: `taskdeps`, `tasknames`, `taskargs`, `taskargmoves`
35+
36+
Options:
37+
- `disconnected`: If `true`, render disconnected vertices (tasks or arguments without upstream/downstream dependencies)
38+
- `color_by`: How to color tasks; if `:fn`, then color by unique function name, if `:proc`, then color by unique processor
39+
- `layout_engine`: The layout engine to use for GraphViz
40+
- `times`: If `true`, annotate each task with its start and finish times
41+
- `times_digits`: Number of digits to display in the time annotations
42+
"""
2643
function Dagger.render_logs(logs::Dict, ::Val{:graphviz}; disconnected=false,
2744
color_by=:fn, layout_engine="dot",
2845
times::Bool=true, times_digits::Integer=3)

Diff for: ext/PlotsExt.jl

+5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ end
6767

6868
# Implementation adapted from:
6969
# https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/7
70+
"""
71+
Dagger.render_logs(logs::Dict, ::Val{:plots_gantt}; kwargs...)
72+
73+
Render a Gantt chart of task execution in `logs` using Plots. `kwargs` are passed to `plot` directly.
74+
"""
7075
function Dagger.render_logs(logs::Dict, ::Val{:plots_gantt}; kwargs...)
7176
df = logs_to_df(logs)
7277

Diff for: src/sch/dynamic.jl

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ struct ThunkID
77
ref::Union{DRef,Nothing}
88
end
99
ThunkID(id::Int) = ThunkID(id, nothing)
10+
Dagger.istask(::ThunkID) = true
1011

1112
"A handle to the scheduler, used by dynamic thunks."
1213
struct SchedulerHandle

Diff for: src/utils/logging-events.jl

+15-8
Original file line numberDiff line numberDiff line change
@@ -181,20 +181,27 @@ Records the dependencies of each submitted task.
181181
"""
182182
struct TaskDependencies end
183183
function (::TaskDependencies)(ev::Event{:start})
184-
if ev.category == :add_thunk
185-
deps = Int[]
186-
for dep in get(Set, ev.timeline.options, :syncdeps)
184+
local deps_tids::Vector{Int}
185+
function get_deps!(deps)
186+
for dep in deps
187187
dep = Dagger.unwrap_weak_checked(dep)
188188
if dep isa Dagger.Thunk || dep isa Dagger.Sch.ThunkID
189-
push!(deps, dep.id)
190-
elseif dep isa Dagger.EagerThunk
191-
# FIXME: Get TID
192-
#push!(deps, dep.uid)
189+
push!(deps_tids, dep.id)
190+
elseif dep isa Dagger.EagerThunk && myid() == 1
191+
tid = lock(Dagger.Sch.EAGER_ID_MAP) do id_map
192+
id_map[dep.uid]
193+
end
194+
push!(deps_tids, tid)
193195
else
194196
@warn "Unexpected dependency type: $dep"
195197
end
196198
end
197-
return ev.id.thunk_id => deps
199+
end
200+
if ev.category == :add_thunk
201+
deps_tids = Int[]
202+
get_deps!(Iterators.filter(Dagger.istask, Iterators.map(last, ev.timeline.args)))
203+
get_deps!(get(Set, ev.timeline.options, :syncdeps))
204+
return ev.id.thunk_id => deps_tids
198205
end
199206
return
200207
end

Diff for: src/utils/logging.jl

+34-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Logging utilities
22

3+
"""
4+
enable_logging!(;kwargs...)
5+
6+
Enables logging globally for all workers. Certain core events are always enabled by this call, but additional ones may be specified via `kwargs`.
7+
8+
Extra events:
9+
- `metrics::Bool`: Enables various utilization and allocation metrics
10+
- `timeline::Bool`: Enables raw "timeline" values, which are event-specific; not recommended except for debugging
11+
- `tasknames::Bool`: Enables generating unique task names for each task
12+
- `taskdeps::Bool`: Enables reporting of upstream task dependencies (as task IDs) for each task argument
13+
- `taskargs::Bool`: Enables reporting of upstream non-task dependencies (as `objectid` hash) for each task argument
14+
- `taskargmoves::Bool`: Enables reporting of copies of upstream dependencies (as original and copy `objectid` hashes) for each task argument
15+
- `profile::Bool`: Enables profiling of task execution; not currently recommended, as it adds significant overhead
16+
"""
317
function enable_logging!(;metrics::Bool=true,
418
timeline::Bool=false,
519
tasknames::Bool=true,
@@ -37,13 +51,30 @@ function enable_logging!(;metrics::Bool=true,
3751
ml[:psat] = Dagger.Events.ProcessorSaturation()
3852
end
3953
Dagger.Sch.eager_context().log_sink = ml
54+
return
4055
end
56+
57+
"""
58+
disable_logging!()
59+
60+
Disables logging previously enabled with `enable_logging!`.
61+
"""
4162
function disable_logging!()
4263
Dagger.Sch.eager_context().log_sink = TimespanLogging.NoOpLog()
64+
return
4365
end
44-
function fetch_logs!()
45-
return TimespanLogging.get_logs!(Dagger.Sch.eager_context())
46-
end
66+
67+
"""
68+
fetch_logs!() -> Dict{Int, Dict{Symbol, Vector}}
69+
70+
Fetches and returns the currently-accumulated logs for each worker. Each entry
71+
of the outer `Dict` is keyed on worker ID, so `logs[1]` are the logs for worker
72+
`1`.
73+
74+
Consider using `show_logs` or `render_logs` to generate a renderable display of
75+
these logs.
76+
"""
77+
fetch_logs!() = TimespanLogging.get_logs!(Dagger.Sch.eager_context())
4778

4879
function logs_event_pairs(f, logs::Dict)
4980
running_events = Dict{Tuple,Int}()

Diff for: src/visualization.jl

+31-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,34 @@
11
# Printable representation
22

3-
show_logs(io::IO, t, vizmode::Symbol; options...) =
4-
show_logs(io, t, Val{vizmode}(); options...)
3+
"""
4+
show_logs(io::IO, logs, vizmode::Symbol; options...)
5+
show_logs(io::IO, t, logs, vizmode::Symbol; options...)
6+
7+
Displays the logs of a task `t` and/or logs object `logs` using the visualization mode `vizmode`, which is written to the given IO stream `io`. `options` are specific to the visualization mode.
8+
9+
---
10+
11+
show_logs(logs, vizmode::Symbol; options...)
12+
show_logs(t, logs, vizmode::Symbol; options...)
13+
14+
Returns a string representation of the logs of a task `t` and/or logs object `logs` using the visualization mode `vizmode`. `options` are specific to the visualization mode.
15+
"""
16+
function show_logs end
17+
18+
show_logs(io::IO, logs, vizmode::Symbol; options...) =
19+
show_logs(io, logs, Val{vizmode}(); options...)
520
show_logs(io::IO, t, logs, vizmode::Symbol; options...) =
621
show_logs(io, t, Val{vizmode}(); options...)
722
show_logs(io::IO, ::T, ::Val{vizmode}; options...) where {T,vizmode} =
823
throw(ArgumentError("show_logs: Task/logs type `$T` not supported for visualization mode `$(repr(vizmode))`"))
924
show_logs(io::IO, ::T, ::Logs, ::Val{vizmode}; options...) where {T,Logs,vizmode} =
1025
throw(ArgumentError("show_logs: Task type `$T` and logs type `$Logs` not supported for visualization mode `$(repr(vizmode))`"))
1126

12-
show_logs(t, vizmode::Symbol; options...) =
13-
show_logs(t, Val{vizmode}(); options...)
27+
show_logs(logs, vizmode::Symbol; options...) =
28+
show_logs(logs, Val{vizmode}(); options...)
1429
show_logs(t, logs, vizmode::Symbol; options...) =
1530
show_logs(t, logs, Val{vizmode}(); options...)
16-
function show_logs(t, ::Val{vizmode}; options...) where vizmode
31+
function show_logs(logs, ::Val{vizmode}; options...) where vizmode
1732
iob = IOBuffer()
1833
show_logs(iob, t, Val{vizmode}(); options...)
1934
return String(take!(iob))
@@ -26,10 +41,18 @@ end
2641

2742
# Displayable representation
2843

29-
render_logs(t, vizmode::Symbol; options...) =
30-
render_logs(t, Val{vizmode}(); options...)
44+
"""
45+
render_logs(logs, vizmode::Symbol; options...)
46+
render_logs(t, logs, vizmode::Symbol; options...)
47+
48+
Returns a displayable representation of the logs of a task `t` and/or logs object `logs` using the visualization mode `vizmode`. `options` are specific to the visualization mode.
49+
"""
50+
function render_logs end
51+
52+
render_logs(logs, vizmode::Symbol; options...) =
53+
render_logs(logs, Val{vizmode}(); options...)
3154
render_logs(t, logs, vizmode::Symbol; options...) =
32-
render_logs(t, Val{vizmode}(); options...)
55+
render_logs(t, logs, Val{vizmode}(); options...)
3356
render_logs(::T, ::Val{vizmode}; options...) where {T,vizmode} =
3457
throw(ArgumentError("render_logs: Task/logs type `$T` not supported for visualization mode `$(repr(vizmode))`"))
3558
render_logs(::T, ::Logs, ::Val{vizmode}; options...) where {T,Logs,vizmode} =

0 commit comments

Comments
 (0)