Skip to content
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

ScaLAPACKMatrix: add functions to perform addition, multiplication and row/column scaling #5869

Merged
merged 7 commits into from
Feb 19, 2018

Conversation

BenBrands
Copy link
Contributor

No description provided.

Copy link
Contributor

@davydden davydden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for improvements 👍 few minor comments. Just wanted to raise the discussion on naming, so don't rush in re-naming anything.

p.s. also add a changelog for the new functionality

*
* The matrices <tt>A</tt> and <tt>B</tt> must have the same process grid
*
* Following alignment conditions have to be fulfilled: MB_A = NB_B and NB_A = MB_B
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in class description we have

...into $MB$ by $NB$ blocks...

not sure how it renders, but probably you should do $MB_A$ and alike here and below in this PR to keep it consistent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

full stop

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will change it at the one point in the class description, if that is fine with you.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would actually prefer the opposite, i think it will render better as latex formula. Otherwise you have it as a text MB_A

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p.s. that's also how we do it all other places inside ScaLAPACK, including the most recent PR with some docu changes #5875

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right ...

/**
* Transposing assignment: <i>A = B<sup>T</sup></i>
*
* The matrices <tt>A</tt> and <tt>B</tt> must have the same process grid
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

full stop

*
* else <i>op(B) = B</i>
*
* The matrices <tt>A</tt> and <tt>B</tt> must have the same process grid
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

full stop

* | false | MB_A = MB_B <br> NB_A = NB_B |
* | true | MB_A = NB_B <br> NB_A = MB_B |
*/
void add(const ScaLAPACKMatrix<NumberType> &B,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now i see what you wanted to implement, elsewhere (for vector classes) we call this:

sadd (const Number s, const Number a, const VectorSpaceVector< Number > & V)

since other matrix classes don't support this operation, i would rather stick with

sadd (const .. s, const ... a,const ... B, const bool transpose_B = false)

@dealii/dealii any opinions on naming of this matrix operation?

*
* The matrices <tt>A</tt>, <tt>B</tt> and <tt>C</tt> must have the same process grid.
*/
void mult(ScaLAPACKMatrix<NumberType> &C,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dealii/dealii this is kind of smult (scale matrix and add multiplication). For consistency with vectors, i would probably move two numbers in front i.e. (const NumberType s, const NumberType a, const Matrix....).
But then it would be inconsistent with FullMatrix

void mmult (FullMatrix< number2 > &C, const FullMatrix< number2 > &B, const bool adding=false) const;

hm...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We used to have similar functions in some of the vector classes (e.g here), so I would say that the factors and matrices should be ordered according to the operation along with the input matrices, even if that means that we lose the default values. Does a default value of 0 for b make sense anyway? This then just becomes an assignment operation.

Assert(this->row_block_size==B.column_block_size,ExcDimensionMismatch(this->column_block_size,B.row_block_size));
Assert(B.row_block_size==C.column_block_size,ExcDimensionMismatch(B.column_block_size,C.column_block_size));
}
Threads::Mutex::ScopedLock lock (mutex);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need mutex only when mutable member variables like work array are being used. I think you don't need it here.

if (this->grid->mpi_process_is_active)
{
for (int i=0; i<n_local_rows; ++i)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't need these brackets

{
for (int i=0; i<n_local_rows; ++i)
{
for (int j=0; j<n_local_columns; ++j)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should probably loop over columns first, take value and multiply all row elements.

const int glob_i = global_row(i);
for (int j=0; j<n_local_columns; ++j)
{
local_el(i,j) *= factors[glob_i];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just do const NumberType & s = factors[global_row(i)];

{
const int glob_i = global_row(i);
for (int j=0; j<n_local_columns; ++j)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and remove these brackets

@davydden
Copy link
Contributor

davydden commented Feb 6, 2018

/run-tests

Copy link
Contributor

@davydden davydden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@davydden
Copy link
Contributor

@dealii/dealii can someone please have a look at the documentation here and the chosen names/arguments for member functions?

*
* The matrices <tt>A</tt> and <tt>B</tt> must have the same process grid.
*
* Following alignment conditions have to be fulfilled: $MB_A$ = $NB_B$ and $NB_A$ = $MB_B$
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Say "The following ...". I had to think about whether "following" is a verb or adjective. Same in a few places below.

Also end the sentence with a period.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You beat me to it! I was also going to make the suggestion that the style of all of the documentation be made more consistent with that of the rest of the class. The conditions can also be put in a @note.

/**
* Matrix-addition:
*
* <i>A = a A + b op(B)</i>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the empty line so that this reads back to back

think about whether you could do the same in the following lines

*
* Copies of @p factors have to available on all processes of the underlying MPI communicator
*/
void scale_columns(std::vector<NumberType> &factors);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make the argument const

*
* Copies of @p factors have to available on all processes of the underlying MPI communicator
*/
void scale_rows(std::vector<NumberType> &factors);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, we should probably use Vector<NumberType> instead here. It won't make much of a difference at the end of the day, but is probably more consistent representation of a diagonal matrix used here as pre/post multiplication.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is Vector<NumberType> more consistent than std::vector<NumberType>?
We do not use Vector<NumberType> in ScaLAPACKMatrix unlike std::vector<NumberType>, which is used at three places.
We could provide two public interfaces and use one private function (working with pointers) internally.

Copy link
Contributor

@davydden davydden Feb 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we may seek just a few eigenvalues or all eigenvalues of a matrix. In other places (like Arpack for sparse large matrices) we also use std::vector<> which is problably ok.

Here, however, this vector has to have as many elements as matrix rows/columns. So in case of a square matrix, this is simply a diagonal matrix represented by a vector. With other matrix classes AFAIK we never use std::vector<> to represent a diagonal, i.e. https://www.dealii.org/developer/doxygen/deal.II/classSparseMatrix.html#a07ba942c5b7466b3895fed3104fbcc26

// https://www.ibm.com/support/knowledgecenter/SSNR5K_4.2.0/com.ibm.cluster.pessl.v4r2.pssl100.doc/am6gr_lgemm.htm
if (!transpose_A && !transpose_B)
{
Assert(this->n_columns==B.n_rows,ExcDimensionMismatch(this->n_columns,B.n_rows));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for adding all of these asserts!

@jppelteret
Copy link
Member

@BenBrands I'll take a look through the documentation tomorrow!

@jppelteret
Copy link
Member

Ok, so @bangerth happened post an initial few comment just commented, but I'll stand by my initial commitment and will give it a proper look tomorrow.

*
* The matrices <tt>A</tt> and <tt>B</tt> must have the same process grid.
*
* Following alignment conditions have to be fulfilled: $MB_A$ = $NB_B$ and $NB_A$ = $MB_B$
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that for all of the functions that you're documented, the style could be made a bit more similar to that of the existing document. So here, for example, you could consider writing it as follows:

Copy the transpose of the contents of the distributed matrix @p B into this one.

This transpose assignment operation modifies the calling matrix @p A such 
that $A = B^{T}$.

@note The matrices @p A and @p B must have the same process grid.
The following alignment conditions also have to be fulfilled: 
$MB_A = NB_B$ and $NB_A = MB_B$.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note also that $MB_A$ = $NB_B$ should be $MB_A = NB_B$ so that the equals is also rendered using LaTeX. Same applies below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discussed with @davydden the documentation of ScaLAPACKMatrix and we agree that it has to be reworked to make it uniform. I will do that in a different PR based on the style used for the doc in this PR.

/**
* Transposing assignment: <i>A = B<sup>T</sup></i>
*
* The matrices <tt>A</tt> and <tt>B</tt> must have the same process grid.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have you used HTML as opposed to LaTeX formatting (both here and below)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use @p to format the parameters of a function, i.e. @p A and @p B, when inline with other text.

Same applies below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am also in favour of LaTeX, but we have a mixture of the two, apparently #5897

*
* if(transpose_B) <i>op(B) = B<sup>T</sup></i>
*
* else <i>op(B) = B</i>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer for this to be expressed in words rather than as pseudo-code. i.e.

If the @p transpose_B is set then the transpose of @p B is used.
That is to say that the operation $op(B)$ corresponds to $B^{T}$. 
If this flag is set to false, then $op(B)$ applies @p B with its default ordering.

This also applies below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would favor the pseudo-code as it is short and precise.
But I can adapt it if wanted.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that the pseudo-code is consistent with LapackFullMatrix and elements of the Vector class. Although I'm not a huge fan of it, I'm not going to push the issue since there's precedent for it.

*
* The matrices <tt>A</tt>, <tt>B</tt> and <tt>C</tt> must have the same process grid.
*/
void mult(ScaLAPACKMatrix<NumberType> &C,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We used to have similar functions in some of the vector classes (e.g here), so I would say that the factors and matrices should be ordered according to the operation along with the input matrices, even if that means that we lose the default values. Does a default value of 0 for b make sense anyway? This then just becomes an assignment operation.

/**
* Matrix-matrix-multiplication.
*
* The optional parameter <tt>adding</tt> determines, whether the result is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no comma

*
* else <i>C = A<sup>T</sup>*B</i>
*
* Assumes that <tt>A</tt> and <tt>B</tt> have compatible sizes and that
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is assumed that...

@@ -389,6 +546,24 @@ class ScaLAPACKMatrix : protected TransposeTable<NumberType>
*/
NumberType &local_el(const unsigned int loc_row, const unsigned int loc_column);

/**
* Scale the columns of the distributed matrix by scalars in array @p factors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by the scalars provided in the array

*
* The array @p factors must have as many entries as the matrix columns.
*
* Copies of @p factors have to available on all processes of the underlying MPI communicator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have to be; fullstop at end of sentence.

*
* The array @p factors must have as many entries as the matrix rows.
*
* Copies of @p factors have to available on all processes of the underlying MPI communicator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have to be; fullstop at end of sentence.

void scale_columns(std::vector<NumberType> &factors);

/**
* Scale the rows of the distributed matrix by scalars in array @p factors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by the scalars provided in the array

@jppelteret
Copy link
Member

Thanks for taking the time to add this functionality @BenBrands! Since @davydden checked the implementation already, lets clean up the documentation a little bit and then I think that this is good to go!

@BenBrands
Copy link
Contributor Author

Thank you all for your comments.
The documentation for this class needs an update, I would like to do so in a different PR (based on the doc in this PR and #5898).

@BenBrands
Copy link
Contributor Author

The functions scale_columns() and scale_rows() take const ArrayView<const NumberType> as input!

@jppelteret
Copy link
Member

@BenBrands Thanks again for the contribution. I've created an issue for the proposed documentation enhancements.

@jppelteret
Copy link
Member

@davydden @BenBrands Lets discuss the changes made to scale_columns and scale_rows before we merge this. This did not work out quite as I thought it would. I guess that we would need to more closely follow the idiom used here and here to achieve it.

*
* | transpose_B | Block Sizes | Operation |
* | :---------: | :--------------------------: | :-------------------------------------------: |
* | false | $MB_A=MB_B$ <br> $NB_A=NB_B$ | $\mathbf{A} = a \mathbf{A} + b \mathbf{B}$ |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in another PR #5899 (comment) @kronbichler raised the point whether we shall use bold symbols (\mathbf) for matrices and vectors.

Personally, I don't mind sticking with plain LaTeX A, B, c for linear algebra, probably with \cdots to denote multiplication. Downside is that we won't distinguish between scalars and vectors in this notation.

@dealii/dealii thoughts?

template <typename Number>
inline
ArrayView<const Number>
make_array_view (const ArrayView<Number> &array_view)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@masterleinad I think that you added some of the other make_array_view functions previously. Are you happy with these two additions (they help instantiation of some functions)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. In the end, I prefer to have external make_array_functions instead of modifying the class ArrayView itself. If this helps with compatibility, I am totally fine with it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks for the confirmation!

@jppelteret
Copy link
Member

Ok, so I think that this is ready to merge but since I've contributed directly to this PR it would be more appropriate for someone else to make the final call.


const std::vector<unsigned int> sizes = {{400,500}};

// test A = alpha A + beta B
Copy link
Contributor

@davydden davydden Feb 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please split this test into 2 (each does different operation), previous into 4 (one operation in each test) and the next one into two (rows/cols). If/when something goes south, it's much easier to debug a small tests as opposed to a huge one which covers all the cases .

void ScaLAPACKMatrix<NumberType>::scale_columns(const InputVector &factors)
{
internal::scale_columns(*this, make_array_view(factors),
this->grid->mpi_process_is_active);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor nitpick, i think it's easier to read as

  if (this->grid->mpi_process_is_active)
    internal::scale_columns(...);

that is, when you move that if outside of internal function which actually does the job.

@davydden davydden merged commit abd4921 into dealii:master Feb 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants