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

docs/Project.toml

Lines changed: 3 additions & 0 deletions
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]

docs/make.jl

Lines changed: 4 additions & 2 deletions
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",

docs/src/api-timespanlogging/functions.md

Lines changed: 0 additions & 1 deletion
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

docs/src/api-timespanlogging/types.md

Lines changed: 0 additions & 6 deletions
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-
```

docs/src/logging-visualization.md

Lines changed: 1 addition & 2 deletions
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

ext/GraphVizExt.jl

Lines changed: 18 additions & 1 deletion
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)

ext/PlotsExt.jl

Lines changed: 5 additions & 0 deletions
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

src/sch/dynamic.jl

Lines changed: 1 addition & 0 deletions
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

src/utils/logging-events.jl

Lines changed: 15 additions & 8 deletions
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

src/utils/logging.jl

Lines changed: 34 additions & 3 deletions
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}()

0 commit comments

Comments
 (0)