-
Notifications
You must be signed in to change notification settings - Fork 12
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
Implement simple sequenced keys constraint #273
Conversation
9d0fd20
to
f3bd891
Compare
@@ -1272,6 +1274,9 @@ namespace ttg_parsec { | |||
|
|||
bool m_defer_writer = TTG_PARSEC_DEFER_WRITER; | |||
|
|||
std::vector<ttg::meta::detail::constraint_callback_t<keyT>> constraints_check; |
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'm not sure I see the difference between constraints_check
and constraints_complete
. It looks like we always push_back
a callback to both vectors (or to none), and sometimes we iterate over constraints_check
only, but since we appear to never remove the callback from either, I'm not sure I follow why we need both (not saying I found a problem, just wanting more explanations :) )
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'll put some comments there. These are two different callbacks:
constraints_check
hands the task over to the constraint, which will either tell us directly that it is not constrained (i.e., can be executed) or stores the key for later release through a callback (the listener action) and tells us that the key is indeed constrained.constraints_complete
tells the constraint that the task has executed (so that the constraint can check for new tasks to release through the listener action)
examples/spmm/spmm.cc
Outdated
@@ -292,11 +292,16 @@ class SpMM25D { | |||
, parallel_bcasts_(parallel_bcasts) { | |||
Edge<Key<2>, void> a_ctl, b_ctl; | |||
Edge<Key<2>, int> a_rowctl, b_colctl; // TODO: can we have multiple control inputs per TT? | |||
auto constraint = ttg::make_shared_constraint<ttg::SequencedKeysConstraint<Key<2>>>(); |
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.
That looks neat indeed.
I'm slightly worried about the limitation that the constraint needs to work on a single key type.
We don't need it in GEMM, because by constraining the broadcast tasks, we indirectly constrain the GEMM tasks, but let's say that I wanted to explicitly constrain the GEMM tasks too: I would need to define a new shared constraint with SequencedKeysConstraint<Key<3>>
and I would have to release the constraint on both shared constraints to make them progress simultaneously?
Also, I don't see in the GEMM code any explicit release of constraints? Who makes them progress?
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 agree. I have not found a good way to type pun the keys. Today, we couldn't include the gemm task in the constraint because the key types are different (Key<2>
and Key<3>
). I'm sure there is way to do that, I'm not sure about the complexity...
ttg/ttg/constraint.h
Outdated
/** | ||
* Used for external key mapper. | ||
*/ | ||
SequencedKeysConstraint() |
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 is not what I had in mind. Might work too, but let's go over it during the next meeting, to make sure it does what we want.
AFAICT, the SequencedKeyConstraint
makes sure tasks are released in the order of the integer returned by the mapping function; release of tasks can be paused (calling the stop()
method) and resumed (calling the start()
method), but I'm not sure what calls stop or stat in the GEMM example. It looks to me that with this implementation, if we discover enough BCastA / BCastB tasks, we'll push them in the right order in the scheduler (which is already a progress), but there is no mechanism to actually prevent a BCastA with a high 'k' to be scheduled if it is discovered first.
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.
In the SPMM example we attach the mapping function to the TT (the keys for BcastA/B are the same type but we need different information from them). We cannot pass one mapping here. The different check
functions below are conditionally enabled on whether a mapper was provided to the constraint or whether the TT has to provide the ordinal.
The constraints need to be ported to the MADNESS backend. I'd like to refactor the common parts out into the TT base class to avoid duplication yet another bunch of code. |
Signed-off-by: Joseph Schuchart <[email protected]>
Constraints should be checked in the order in which they were added. This avoids deadlocks if all constraints ensure progress (e.g., they don't wait for a specific task to appear) but may lead to different outcomes (execution orders) if the order of constraints changes. Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
Replaced by constraints. Signed-off-by: Joseph Schuchart <[email protected]>
Auto-release makes sure there are no deadlocks by enabling the next set of keys once the current ordinal is done. Without auto-release applications must release the next set explitly and ensure there are no deadlocks. Signed-off-by: Joseph Schuchart <[email protected]>
The constructor of the SequencedKeysConstraint takes a Boolean argument that determines whether tasks are automatically released or whether we depend on the application to release the next wave of tasks. Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
5d02164
to
99f03b6
Compare
Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
Constraints will be ignored in the MADNESS backend for now. Signed-off-by: Joseph Schuchart <[email protected]>
b22fd8d
to
a36a88b
Compare
Signed-off-by: Joseph Schuchart <[email protected]>
Constraints are a no-op in the madness backend so don't try to execute with them. Signed-off-by: Joseph Schuchart <[email protected]>
most importantly pulls in ValeevGroup/tiledarray#483 which solves linking errors due to missing fmt instantiations
We should consider this a hint and fall back to non-persistent values if the type is not derived from TTValue or we are running with madness. Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
We cannot fully serialize the DeviceTensor and we don't need the DeviceTensor in host execution. Signed-off-by: Joseph Schuchart <[email protected]>
Fixes issues in TA device header. Signed-off-by: Joseph Schuchart <[email protected]>
We should only call that when we run on the PaRSEC backend. Otherwise we'll pull the rug from under the madness backend. Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
Somehow this breaks the element-wise SPMM. Not sure why, and how to dig into that. Will need some time or volunteers :) |
Signed-off-by: Joseph Schuchart <[email protected]>
We have to provide our own check for equal based on the provided comparator. Signed-off-by: Joseph Schuchart <[email protected]>
Signed-off-by: Joseph Schuchart <[email protected]>
@evaleev Something is off with the Boosts in the Ubuntu CI:
I've seen similar issues on one of our machines. This PR bumps the minimum required to 1.81. What was the reason for that? |
Ubuntu provides too old of a Boost, which wreaks unseen levels of havoc (build succeeds but metadata in
tracking issues across the entirety of the stack is difficult. From what I recall some parts of boost 1.80 used Boost is hell. But reimplementing it is hell^2. |
Here is a first implementation of constraints. The flow is as follows:
k
is inkey[1]
, for B it's inkey[0]
). The mapper extracts the sequence number from the key and returns it as an ordinal to the constraint. The mapper can be either provided to the constraint directly or to the TT, which then passes it on to the constraint. That (and handlingvoid
:/) makes the code somewhat more complex than needed. Users probably will implement only one version for the configuration they need.User-defined constraints should inherit from
ConstraintBase
to get the listener handling and have to provide the propercheck
andcomplete
callbacks.I still need to remove the control flow we have today in SPMM and check that it works as expected. Overall, the user-facing interface is quite clean and the internal interface is not terrible (a win already).