-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Compilation Time reporting is broken on Julia 1.7, due to Task Migration #41739
Comments
So, it seems to me that:
Does that seem like a reasonable approach to everyone? Remove the per-thread aspect of this measurement, make it global, and protect it with atomics, similar to what was done in #41612? (I'll probably make that change by adapting #41733 to this purpose, and then use atomic increment/decrement for the feature, to make it reentrant.) Sound good? |
Jep sounds sensible to me. Without the ability to inherit data from your
parent, which is a whole other can of worms, this seems like the best
solution for now.
…On Fri, Jul 30, 2021, 23:34 Nathan Daly ***@***.***> wrote:
So, it seems to me that:
1. Per-thread measurements of compilation time are just not very
useful, at least certainly aren't what a user wants when they call
@time.
2. It's hard to get useful per-task measurements, since you have the
problem that anything that happens in *child tasks* is not attributed
to you (as we discussed yesterday).
3. Since all of the other metrics that we currently report
(allocations, bytes, time, gc time) are all global measurements, that we
should just make this a global metric as well.
Does that seem like a reasonable approach to everyone? Remove the
per-thread aspect of this measurement, make it global, and protect it with
atomics, similar to what was done in #41612
<#41612>?
(I'll probably make that change by adapting #41733
<#41733> to this purpose, and then
use atomic increment/decrement for the feature, to make it reentrant.)
Sound good?
CC: @IanButterworth <https://github.com/IanButterworth>, @vtjnash
<https://github.com/vtjnash>, @vchuravy <https://github.com/vchuravy>
CC: @rgankema <https://github.com/rgankema>, @ElSeidy
<https://github.com/ElSeidy>, since this is related to #41271
<#41271>.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#41739 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AABDO2S6O3M434HMMDMDV3DT2MLFLANCNFSM5BJCH4MQ>
.
|
I guess this makes sense, but for the specific performance measurements I'd like to do, global allocation and compilation time measurements are not very useful. Can I hope for additional task-level measurements at some point in time, or would that be unrealistic? |
I would second @rgankema in that too. I am also interested in I hope thats feasible too :) |
The trouble is that, like I said in Like, do you really only want the compilation time in that single task? Or do you want compilation time in that task and all tasks that it spawned? Or that task + all the tasks that it waited on? Or only the tasks that it waited on, that were spawned by it? I think the main thing blocking support for this feature is just deciding as a group what we want the semantics to mean. I think it should be okay to implement it, we just need to decide what we want to measure. That said, ++ i think we all want to have some task-accounting for things like this, yeah. 👍 👍 |
Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("/Users/nathandaly/Downloads/compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("/Users/nathandaly/Downloads/compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ```
Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("/Users/nathandaly/Downloads/compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("/Users/nathandaly/Downloads/compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ```
@NHDaly , thats a good point. In my opinion, the way I think about it is similar to execution time (total/breakdowns). I would define it as the total time for compilation taken for a task to finish (including any subtasks spawned by it and it waited on). I think, its up to the developer/instrumenter to be able to extract the any breakdowns (just like we do in the tracers' execution time). |
@NHDaly, to be accurate, I am also assuming here that I can compute the compilation time for a portion within a single task too like # task 1
@compilation_time begin. # block1
#some computations for block1 (in task1)
....
@compilation_time begin # block2
# some other computation for block2 (in task1)
.....
end
# task 2
@sync @spawn begin
@compilation_time begin # block3
# some other computation for block3 (in task2)
....
end
end
end here the compilation time for |
Now, multiple tasks (on the same or different Threads) can start and stop compilation time measurement, without interrupting each other. Add `cumulative_compile_time_ns()` to return the cumulative compile time for a thread without stopping measurement. ```julia julia> Base.cumulative_compile_time_ns_before() # enable constantly measuring compilation time 0x0000000000000000 julia> @time @eval module M ; f(x) = 2+x; end 0.006730 seconds (919 allocations: 55.212 KiB, 57.20% compilation time) Main.M julia> Base.cumulative_compile_time_ns() 0x00000000075246b3 julia> @time 2+2 0.000000 seconds 4 julia> Base.cumulative_compile_time_ns() 0x0000000007fe4a46 julia> @time @eval M.f(2) 0.003538 seconds (750 allocations: 46.247 KiB, 94.64% compilation time) 4 julia> Base.cumulative_compile_time_ns() 0x000000000831619e ``` Make jl_cumulative_compile_time_ns into a global, atomic variable. Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("./compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("./compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ```
@NHDaly That's a great point, I should have been more precise :) I'd be interested in compilation time for that task and all tasks it spawned. Of course, if that's feasible at all! To express that more high-level: when I run a piece of code, I want to know all the compilation costs that were incurred as a result of running that code. So that means that if that code spawns new tasks, those tasks are interesting as well. But other tasks that just happen to be running at the same time (which I guess is what we'd measure with global measurements), are tasks I don't want to measure. |
Now, multiple tasks (on the same or different Threads) can start and stop compilation time measurement, without interrupting each other. Add `cumulative_compile_time_ns()` to return the cumulative compile time for a thread without stopping measurement. ```julia julia> Base.cumulative_compile_time_ns_before() # enable constantly measuring compilation time 0x0000000000000000 julia> @time @eval module M ; f(x) = 2+x; end 0.006730 seconds (919 allocations: 55.212 KiB, 57.20% compilation time) Main.M julia> Base.cumulative_compile_time_ns() 0x00000000075246b3 julia> @time 2+2 0.000000 seconds 4 julia> Base.cumulative_compile_time_ns() 0x0000000007fe4a46 julia> @time @eval M.f(2) 0.003538 seconds (750 allocations: 46.247 KiB, 94.64% compilation time) 4 julia> Base.cumulative_compile_time_ns() 0x000000000831619e ``` Make jl_cumulative_compile_time_ns into a global, atomic variable. Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("./compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("./compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ```
Now, multiple tasks (on the same or different Threads) can start and stop compilation time measurement, without interrupting each other. Add `cumulative_compile_time_ns()` to return the cumulative compile time for a thread without stopping measurement. ```julia julia> Base.cumulative_compile_time_ns_before() # enable constantly measuring compilation time 0x0000000000000000 julia> @time @eval module M ; f(x) = 2+x; end 0.006730 seconds (919 allocations: 55.212 KiB, 57.20% compilation time) Main.M julia> Base.cumulative_compile_time_ns() 0x00000000075246b3 julia> @time 2+2 0.000000 seconds 4 julia> Base.cumulative_compile_time_ns() 0x0000000007fe4a46 julia> @time @eval M.f(2) 0.003538 seconds (750 allocations: 46.247 KiB, 94.64% compilation time) 4 julia> Base.cumulative_compile_time_ns() 0x000000000831619e ``` Make jl_cumulative_compile_time_ns into a global, atomic variable. Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("./compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("./compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ```
Now, multiple tasks (on the same or different Threads) can start and stop compilation time measurement, without interrupting each other. * Makes jl_cumulative_compile_time_ns into a global, atomic variable. Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("./compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("./compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ``` Compilation time measurement originally added in: JuliaLang#38885 Problems addressed: - This fixes JuliaLang#41739, meaning it fixes compilation time reporting in 1.7 after task migration was enabled. - It also fixes the race condition that existed previously, even on 1.6, where multiple Tasks on the thread measuring `@time` could break the measurement, as identified in (JuliaLang#41271 (comment)). - It fixes reentrant `@time` by making the `enable` flag a _counter,_ instead of a boolean. - It fixes `@time` called from multiple threads by making that flag thread-safe (via atomics).
Now, multiple tasks (on the same or different Threads) can start and stop compilation time measurement, without interrupting each other. * Makes jl_cumulative_compile_time_ns into a global, atomic variable. Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("./compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("./compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ``` Compilation time measurement originally added in: JuliaLang#38885 Problems addressed: - This fixes JuliaLang#41739, meaning it fixes compilation time reporting in 1.7 after task migration was enabled. - It also fixes the race condition that existed previously, even on 1.6, where multiple Tasks on the thread measuring `@time` could break the measurement, as identified in (JuliaLang#41271 (comment)). - It fixes reentrant `@time` by making the `enable` flag a _counter,_ instead of a boolean. - It fixes `@time` called from multiple threads by making that flag thread-safe (via atomics).
Now, multiple tasks (on the same or different Threads) can start and stop compilation time measurement, without interrupting each other. * Makes jl_cumulative_compile_time_ns into a global, atomic variable. Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes #41739 ```julia julia> include("./compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("./compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ``` Compilation time measurement originally added in: #38885 Problems addressed: - This fixes #41739, meaning it fixes compilation time reporting in 1.7 after task migration was enabled. - It also fixes the race condition that existed previously, even on 1.6, where multiple Tasks on the thread measuring `@time` could break the measurement, as identified in (#41271 (comment)). - It fixes reentrant `@time` by making the `enable` flag a _counter,_ instead of a boolean. - It fixes `@time` called from multiple threads by making that flag thread-safe (via atomics). (cherry picked from commit b4ca196)
Now, multiple tasks (on the same or different Threads) can start and stop compilation time measurement, without interrupting each other. * Makes jl_cumulative_compile_time_ns into a global, atomic variable. Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("./compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("./compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ``` Compilation time measurement originally added in: JuliaLang#38885 Problems addressed: - This fixes JuliaLang#41739, meaning it fixes compilation time reporting in 1.7 after task migration was enabled. - It also fixes the race condition that existed previously, even on 1.6, where multiple Tasks on the thread measuring `@time` could break the measurement, as identified in (JuliaLang#41271 (comment)). - It fixes reentrant `@time` by making the `enable` flag a _counter,_ instead of a boolean. - It fixes `@time` called from multiple threads by making that flag thread-safe (via atomics).
Now, multiple tasks (on the same or different Threads) can start and stop compilation time measurement, without interrupting each other. * Makes jl_cumulative_compile_time_ns into a global, atomic variable. Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("./compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("./compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ``` Compilation time measurement originally added in: JuliaLang#38885 Problems addressed: - This fixes JuliaLang#41739, meaning it fixes compilation time reporting in 1.7 after task migration was enabled. - It also fixes the race condition that existed previously, even on 1.6, where multiple Tasks on the thread measuring `@time` could break the measurement, as identified in (JuliaLang#41271 (comment)). - It fixes reentrant `@time` by making the `enable` flag a _counter,_ instead of a boolean. - It fixes `@time` called from multiple threads by making that flag thread-safe (via atomics).
Now, multiple tasks (on the same or different Threads) can start and stop compilation time measurement, without interrupting each other. * Makes jl_cumulative_compile_time_ns into a global, atomic variable. Instead of keeping per-task compilation time, this change keeps a global counter of compilation time, protected with atomic mutations. Fixes JuliaLang#41739 ```julia julia> include("./compilation-task-migration-17-example.jl") start thread: 2 end thread: 2 5.185706 seconds (3.53 M allocations: 2.570 GiB, 7.34% gc time, 15.57% compilation time) julia> include("./compilation-task-migration-17-example.jl") start thread: 3 WARNING: replacing module M. end thread: 1 4.110316 seconds (18.23 k allocations: 2.391 GiB, 5.67% gc time, 0.24% compilation time) ``` Compilation time measurement originally added in: JuliaLang#38885 Problems addressed: - This fixes JuliaLang#41739, meaning it fixes compilation time reporting in 1.7 after task migration was enabled. - It also fixes the race condition that existed previously, even on 1.6, where multiple Tasks on the thread measuring `@time` could break the measurement, as identified in (JuliaLang#41271 (comment)). - It fixes reentrant `@time` by making the `enable` flag a _counter,_ instead of a boolean. - It fixes `@time` called from multiple threads by making that flag thread-safe (via atomics).
Consider this small example, which
@time
s within a Task, allows the Task to migrate threads, and then shows that the results are garbage when it switches threads:One time it reported 0% compilation time, the next time it reports 4327426979.58% compilation time 😅
(For completeness, here's the same test on julia 1.6):
The text was updated successfully, but these errors were encountered: