-
Notifications
You must be signed in to change notification settings - Fork 1
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
"Signaling Accumulators" #12
Comments
It would be difficult to implement this as the monoid of a semiring, inside a matrix multiply. It's a barrier for getting good performance in the parallel case. It's not clear from the example, but it looks like 'update' is being computed by the matrix-vector multiply. But your example only uses signaling_min in the ewise operation. How is it being computed by the matrix-vector multiply? |
In a matrix-vector multiply, you'd likely only ever want to use a signaling accumulator for the accumulator, not in the monoid. The purpose is to figure out whether Take SSSP. Suppose you're doing the following matrix-vector multiply (C API syntax now), where
What I'm suggesting (for C++) is you instead could use a wrapper around bool update = false;
// Wrap the `grb::min` operator.
// Write the value `true` to `update` if a value is updated
auto signaling_min = [&](auto&& a, auto&& b) {
auto min = grb::min{}(a, b);
if (min != a) {
update = true;
return min;
}; |
As I look back at my original example, I used |
Yes, that's where I was confused and thought you were using the update flag from signaling_min in the matrix-vector multiply, which then returned it as a scalar. So the return value of "update = grb::multiply (...)" is a vector, called 'update', right? In that case, a binary operator 'signaling_min' would be well-defined for an ewise operation, and not be hard to implement in parallel. It could also appear as the accumulator op in the matrix multiply, outside of the semiring. It would be very difficult inside a semiring, where it becomes ill-defined and gums up the implemenation particularly in the parallel case. It would be best not to assume a global value for the boolean 'update' flag, however. That would mess up the case where multiple user-threads are each doing their own calls to an ewise operation using signaling_min. |
Yes My idea was that the signaling accumulator would be a user-defined (or user-assisted op), and that users could pass in a reference to the location they want updated. (I suppose if you wanted to do this in C, you could pass in a pointer.) |
Although, unfortunately, I just realized that what I outlined above is not actually sufficient. We care not only about cases in which So, unless |
Yes, I thought about that too. perhaps a better solution would be some kind of way to tell GraphBLAS: "compute C += (stuff) and tell me if C changes at all" (where "+=" is any accumulator op). That would be more general than a signaling_min. I think it would require the accum operator to be present, at least to implement it efficiently. Then "stuff" could be anything at all, any GrB operation. The blocking/non-blocking case would be delicate for this output flag. What if the operation was non-blocking and the computation postponed? The "update" flag would have to force a block, if it were a non-opaque scalar. Gets gnarly... |
Yeah, I think this gets potentially very complicated in the mxm case. Not so much that it's a difficult thing to do, but that it's difficult to expose it in an elegant and thread-safe way. In the ewise case, you can use the behavior we want by also checking if the number of stored values has changed in a new output vector. (e.g. in SSSP in this C++ draft impl). However, element-wise creates a new object, and ideally you'd be able to avoid that by just using |
A "signaling accumulator" would be a useful concept for many graph algorithms where you want to keep track of whether an update has occurred in each iteration.
For example, in SSSP, we can test whether the algorithm has converged by checking whether any new updates were made to the distance vector during this iteration. Traditionally, you'd check this by performing an additional subtraction, or else otherwise checking whether the new distance vector has any new, shorter distances. Alternately, you could implement a new
min
operator that sets a flag if there's an update. If no update occurs, the algorithm has converged, and the algorithm can end.For GraphBLAS C++ 2.0, I would propose implementing a "signaling op" wrapper that indicates whether an update occurs when accumulating.
The text was updated successfully, but these errors were encountered: