Mixed-precision improvements - #7224
Conversation
|
jenkins build this please |
|
You can now select mixed-precision |
|
Just rebased on master branch |
|
Anything happening with this one? |
|
@nrseman I just built it to have a sense of the speed up, but I did not have a detailed look besides skimming its contents to switch on/off the vector dot product. I got the impression this is not ready for review because it is still not rebased to master (parts of its contents are already merged) and there are some comments that seem to be for debugging or forgotten. Could you have a look at that? I noticed that there is duplication of some algorithms where their only change are the vector length specific calls. Do you think is there a way to unify those? That would make these functions significantly more maintainable. In my testing, the specialization of the scalar vector dot product seems to be fine in parallel but it is slower in sequential mode, at least for NORNE. I mentioned this to you before holidays, did you have a look at why is that? |
|
Welcome back @SoilRos! Here are my responses to your comments:
I have rebased the code on master twice since I created the PR. OPM is a fast-moving project and I do not rebase on an ongoing basis unless I am aware of breaking changes. If you run into a situation where rebasing is required to review the code, just drop a comment in the PR. To avoid any confusion in the future, I never submit a PR unless I consider the code ready for review. I have just rebased for a third time, so right now everything should be up to date. I'll try to find and delete the comments you are alluding to.
Specialization is the name of the game to squeeze performance out of the hardware. Can you please be more specific on which algorithms you are referring to? Only then can I assess whether or not they can be unified.
Do you mean the opposite? Both the plot you sent me and my own testing shows that in sequential mode NORNE is faster when using my dot product instead of the default. In parallel there are only tiny performance differences. Of course, NORNE runs more or less entirely in-cache and detailed profiling shows significant MPI overhead which dwarfs any improvements to the dot product. |
SoilRos
left a comment
There was a problem hiding this comment.
To avoid any confusion in the future, I never submit a PR unless I consider the code ready for review.
Alright, no problem, I was not aware this is how you operate.
Can you please be more specific on which algorithms you are referring to? Only then can I assess whether or not they can be unified.
I am talking about the mixed BiCGStab, ILU and DILU algorithms. Their (non-trivial) logic is repeated several times with virtually no changes between them, aside of a different function call names. To unify them, templates are your friend. There are many ways to do it, this is just an example:
template<int B>
static void prec_mapplyc(rec_t *P, double *x) {
// switch specialized implementation
}
template<int B>
static void bsr_vmspmv(bsr_matrix *A, const double *x, double *y) {
// switch specialized implementation
}
template<int B>
int bslv_pbicgstabm(bslv_memory *mem, bsr_matrix *A, const double *b, double *x)
{
// ...
mem->use_dilu ? prec_dilu_factorize<B>(P,A) : prec_ilu0_factorize<B>(P,A); // choose
// ...
for(j=0;j<max_iter;j++)
{
prec_mapplyc<B>(P,q_j); //q_j=P.q_j;
bsr_vmspmv<B>(A,q_j,v_j); //v_j= A.q_j
// ...
}
prec_mapplyc<B>(P,x_j); //x_j=P.x_j;
// ...
}Do you mean the opposite?
Yes, sorry. You are right, is the parallel version the slow one. Could you find a case where you parallel dot product is faster? Otherwise is hard to justify adding code that does the same thing.
Could you add some tests that touch this code during testing? For example, by running a system/regression test that already works, but with these solvers instead.
SoilRos
left a comment
There was a problem hiding this comment.
There seem to be a lot of comments from my side, but worry not, most of them are minor issues. All in all, the PR looks good and there is a good case to merge it. It is also nice to see more integration with the linear solver classes.
| std::shared_ptr<AbstractScalarProductType> scalar_product_; | ||
| double const *double_data_; | ||
|
|
||
| int *local_; |
There was a problem hiding this comment.
This looks like a bit set, right? If so, please use std::vector<bool> or std::vector<int>. Note that std::vector<bool> is a funny type and will allocate N bits instead of N sizeof(bool), thus saving storage, but it will give you proxy objects to modify them (i.e., you do not get a proper pointer for the actual data). In either case, that should be the right tool for bit fields in C++.
There was a problem hiding this comment.
Let's hold off on addressing this until we've had a discussion on index sets. Depending on the solution, this variable may disappear altogether.
| /// and eliminate the use of a mask to exclude ghost entries from being | ||
| /// included in the scalar product | ||
| template<class Vector, class Comm> | ||
| class GhostLastScalarProduct : public ScalarProduct<Vector> |
There was a problem hiding this comment.
Similar comments to this class, block_sizes may be private, and virtual keyword is superfluous.
There was a problem hiding this comment.
@blattms may I ask you to review this class? I do not have enough experience with the parallel index sets to assess what is going on here with confidence.
|
Regarding GhostLastScalarProduct:
My testing shows that my implementation consistently beats the default implementation. Below are a few results for Results using GhostLastScalarProduct Results using default scalar product |
|
Regarding unifying algorithms
I'm not a big fan of using templates (or C++ for that matter) for performance critical code. The reason why is that it makes studying the generated assembly code a small nightmare. Instead, I would prefer to use other techniques to unify the algorithms:
I suggest we leave this for a future PR to avoid scope creep. |
|
Regarding adding tests
Yes, I absolutely want to do this. In fact, it is something I have mentioned to Markus before. However, my preference is to do this through a dedicated PR. |
|
Regarding tests, I think we can delay them given that your first implementation of mixed-precision already set a precedent. However, please do not make this a habit for future contributions. The intended workflow for collaboration is that PRs need to be accompanied with their respective tests right away, not later. I strongly suggest that we address the unification of algorithms within the scope of this PR. Your suggestion to delay this is exactly how technical debt is accumulated and I am not comfortable with that here. Using templates was just a suggestion as we already use C++, but other options are also welcomed! |
I got my results with a tolerance of 1e-4, but I do not think that explains our different numbers. In fact, we are getting contradictory results and, as you said, this mostly demonstrate why |
|
I'd also like to check that the two new block sizes at least run on my side. What cases are you using to check those? |
I use the following test cases from
Matthew also provided scaled up version of the above cases for our joint ECMOR paper. |
|
Regarding tests
The questions on tests came up during the previous mixed-precision PR. I outlined the following plan in an email to Markus and yourself on July 8:
The current PR is the first of the two additional PRs referred to in the email. Given that there were no objections at the time, I am simply following the plan. I appreciate that you are not flipping the tables on me now. |
|
Regarding GhostLastScalarProduct:
I did test with I also ran Results using GhostLastScalarProduct Results using default scalar product |
|
Regarding unifying algorithms:
I just pushed a commit that unifies the Technical debt is to a large extent subjective and I have yet to work on a project that does not allow some degree of code duplication if it enhances performance or simplifies the mental map required to work in the code. PS! Note that the |
|
Regarding unifying algorithms: I just pushed a commit that uses function pointers to provide a generic implementation of the legacy |
There was a problem hiding this comment.
Thanks for all the nice updates and clean ups, that's very much appreciated!
I got the different blocks working for me locally and while compiling I found a warning that should be easy to fix (see comment below: #7224 (comment)). So that looks good. I am currently trying to set up the SPE10 but I am having troubles with a keyword that is unrelated to this PR. Your results already look good though. You are running the cartesian model 2 from opm-test, right?
I am primarily running model2 from You may run into the same negative endpoint issue I did. Seems like a bug. My ugly hack is captured by the diff below. That got the case running. diff --git a/opm/simulators/utils/satfunc/OilPhaseConsistencyChecks.cpp b/opm/simulators/utils/satfunc/OilPhaseConsistencyChecks.cpp
index df45ad042..c07db44e7 100644
--- a/opm/simulators/utils/satfunc/OilPhaseConsistencyChecks.cpp
+++ b/opm/simulators/utils/satfunc/OilPhaseConsistencyChecks.cpp
@@ -31,7 +31,7 @@ template <typename Scalar>
void Opm::Satfunc::PhaseChecks::Oil::SOcr_GO<Scalar>::
testImpl(const EclEpsScalingPointsInfo<Scalar>& endPoints)
{
- this->sogcr_ = endPoints.Sogcr;
+ this->sogcr_ = 0;//endPoints.Sogcr;
if (! std::isfinite(this->sogcr_)) {
this->setViolated(); |
|
jenkins build this please |
|
@nrseman The CI seems to be passing with no problem. Just for reference. @nrseman and I met and walked through the differences in how we made our measurements. It turns out that our BIOS settings were different, which really affected the |
This PR provides several improvements to the mixed-precision BiCGSTAB implementation:
SPMVandILU0/DILUimplementations for4x4blocksSPMVandILU0/DILUimplementations for2x2blocksSPMVandILU0/DILUfornxnblocks withn > 4GhostLastMatrixAdapterWellModelGhostLastMatrixAdapterThe impact of all these changes are:
ILU0/DILUsmoothers in theCPR+AMGpreconditionerFor more information on how to run the
opmsimulator with mixed-precision, please seeopm/simulators/linalg/mixed/READAME.mdUPDATE:
You can now select mixed-precision
cprfrom the command line using the--linear-solver=mixed-cprwoption