-
-
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
Experimental Tapir support #31086
Experimental Tapir support #31086
Conversation
4156e00
to
1755d4c
Compare
Some fun numbers with the function fib(N)
if N <= 1
return N
end
token = @syncregion()
x1 = Ref{Int64}()
@spawn token begin
x1[] = fib(N-1)
end
x2 = fib(N-2)
@sync_end token
return x1[] + x2
end 1 Workers
2 Workers (Note my machine has 2 Cores, SMT-2)
4 Workers (Note my machine has 2 Cores, SMT-2)
|
How is this positioned with regards to partr? |
Technically, it's independent of partr. It does impact considerations for the design of the threading API, however, so there's some interaction there. Still mostly independent though. |
This looks really interesting. How does it relate to the structured concurrency ideas expressed in Trio and libdill et al.? (Described, for example in https://trio.discourse.group/t/structured-concurrency-resources/21 and https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful) |
bc956d1
to
472b26d
Compare
This reverts commit 121b6bf.
Superseded by #39773 |
Introduction -- What is Tapir
Tapir is a parallel IR extension to LLVM. For the interested I recommend
perusing the Tapir paper. The key takeaway is that parallel (non-concurrent) programs, can be effectively model with cilk-style task parallelism and that given the serial-projection property (serial execution is always a valid execution), it is possible to reason about parallelism in the LLVM compiler.
By doing so Tapir solves one primary problem: Traditionally introducing parallelism into a program, inhibits compiler optimisations. This is due to a variety of reasons, but chiefly that most implementations of parallelism choose to do early-outlining of parallel thunks. Causing the optimizer to only see calls into the runtime/program thunks without context. A classical optimisation that is inhibited by this is loop-invariant-code-movement. In Julia we encounter a different problem (#15276) in which using a closure to outline a thunk can cause performance issues.
Tapir concepts
Syncregion
An opaque token that is used to associate the various parallel IR statements with each other, so that during
sync
only synchronizes tasks that it is responsible for. Important for nested parallelism and inlining of functions containing parallel constructs.Detach
Think of this as a "function call" to the parallel region.
detach within %syncregion, %label, %reattach
. Thelabel
points to the basic-block that starts-off the parallel region and thereattach
label points past areattach
statement and represents the execution on the task that is spawning the parallel region.Reattach
This is the "return" of a parallel region. It reattaches the parallel region to the original code and the
label
should point to the same basic-block that thereattach
label indetach
is pointing to.Sync
Synchronises all tasks with the same
syncregion
Goal of this PR
This is very much ongoing research on how to best integrate the ideas from Tapir and the technology behind it into Julia. I want to lay a foundation on which we can build and experiment in the future. While the full-benefits will only be realised if one uses a Tapir enabled LLVM build, one
of my goals is to bring the concepts of tapir into the Julia IR and thereby enable us to do optimizations on parallel code in the Julia IR even on a LLVM that doesn't have the Tapir extension. Right now we are in the very early stages of supporting Tapir in Julia.
It is important to note that the semantics of this representation are parallel and not concurrent,
by this extent this will not and cannot replace Julia Tasks. In order to exemplify this issue see the following Julia task code:
Doing a serial projection of this code leads to a deadlock.
User interface
In
test/tapir.jl
I have placed some functions that I have been experimenting with. I do not expect users to directly use@syncregion
,@spawn
and@sync_end
, but rather I think the prototype implementation of a parallel for loop and@sync
,@spawn
.Changes/Current Status
syncregion
: Obtain a token to synchronize spawned tasksspawn
: Spawn a block in a tasksync
: Synchronize all tasks using the same tokendetach
: Detach a parallel regionreattach
: Join a parallel regionsyncregion
,detach
,reattach
,sync
Examples
TODO:
fib2
Notes
Make.user
Acknowledgments
Many thanks to T.B. Schardl (@neboat) for the many discussions around Tapir and LLVM.