← Back to team overview

dolfin team mailing list archive

Re: Fwd: [Branch ~dolfin-core/dolfin/trunk] Rev 6630: Avoid unnessesary resize of result vector for A.mult(x, y)

 


On 8 Mar 2012, at 21:43, Johan Hake <hake.dev@xxxxxxxxx> wrote:

> On Thu, Mar 8, 2012 at 9:40 PM, Garth N. Wells <gnw20@xxxxxxxxx> wrote:
>> This change is not safe. For a matrix and a vector to be compatible in
>> parallel, it is not sufficient to check the global size.
> 
> True. The logic is that a user need to provide a result vector with
> correct size and parallell structure. If not just pass an empty
> vector. The problem with always resizing the result is that one loose
> performance for iterative solvers using A.mult(x, y).


The only proper solution that I see is that a user is responsible for making sure that the size is right and that the function do no resizing. The change is a half-way house, so I think that it should be reverted. The old code was safe, and the proper, efficient alternative is that no resizing be done.

Garth

> 
> Johan
> 
>> Garth
>> 
>> 
>> 
>> 
>> ---------- Forwarded message ----------
>> From:  <noreply@xxxxxxxxxxxxx>
>> Date: 8 March 2012 20:31
>> Subject: [Branch ~dolfin-core/dolfin/trunk] Rev 6630: Avoid
>> unnessesary resize of result vector for A.mult(x, y)
>> To: Garth Wells <gnw20@xxxxxxxxx>
>> 
>> 
>> ------------------------------------------------------------
>> revno: 6630
>> committer: Johan Hake <hake.dev@xxxxxxxxx>
>> branch nick: work-trunk
>> timestamp: Thu 2012-03-08 21:25:41 +0100
>> message:
>>  Avoid unnessesary resize of result vector for A.mult(x, y)
>>    -- Apply patch from Joachim
>> modified:
>>  ChangeLog
>>  dolfin/la/EpetraMatrix.cpp
>>  dolfin/la/GenericMatrix.h
>>  dolfin/la/PETScMatrix.cpp
>>  dolfin/la/uBLASMatrix.h
>>  dolfin/swig/la/post.i
>>  test/unit/la/python/KrylovSolver.py
>> 
>> 
>> --
>> lp:dolfin
>> https://code.launchpad.net/~dolfin-core/dolfin/trunk
>> 
>> Your team DOLFIN Core Team is subscribed to branch lp:dolfin.
>> To unsubscribe from this branch go to
>> https://code.launchpad.net/~dolfin-core/dolfin/trunk/+edit-subscription
>> 
>> === modified file 'ChangeLog'
>> --- ChangeLog   2012-02-13 21:49:10 +0000
>> +++ ChangeLog   2012-03-08 20:25:41 +0000
>> @@ -1,3 +1,4 @@
>> + - Avoid unnessesary resize of result vector for A*b
>>  - Major speed-up of mesh topology computation
>>  - Add simple 2D and 3D mesh generation (via CGAL)
>>  - Add creation of mesh from triangulations of points (via CGAL)
>> 
>> === modified file 'dolfin/la/EpetraMatrix.cpp'
>> --- dolfin/la/EpetraMatrix.cpp  2012-02-24 12:24:53 +0000
>> +++ dolfin/la/EpetraMatrix.cpp  2012-03-08 20:25:41 +0000
>> @@ -568,7 +568,17 @@
>>   }
>> 
>>   // Resize RHS
>> -  this->resize(Ax, 0);
>> +  if (Ax.size() == 0)
>> +  {
>> +    this->resize(Ax, 0);
>> +  }
>> +
>> +  if (Ax.size() != size(0))
>> +  {
>> +    dolfin_error("EpetraMatrix.cpp",
>> +                 "compute matrix-vector product with Epetra matrix",
>> +                 "Vector for matrix-vector result has wrong size");
>> +  }
>> 
>>   dolfin_assert(x.vec());
>>   dolfin_assert(Ax.vec());
>> @@ -595,7 +605,17 @@
>>   }
>> 
>>   // Resize RHS
>> -  this->resize(Ax, 1);
>> +  if (Ax.size() == 0)
>> +  {
>> +    this->resize(Ax, 1);
>> +  }
>> +
>> +  if (Ax.size() != size(1))
>> +  {
>> +    dolfin_error("EpetraMatrix.cpp",
>> +                 "compute transpose matrix-vector product with Epetra matrix",
>> +                 "Vector for transpose matrix-vector result has wrong size");
>> +  }
>> 
>>   const int err = A->Multiply(true, *(x.vec()), *(Ax.vec()));
>>   if (err != 0)
>> 
>> === modified file 'dolfin/la/GenericMatrix.h'
>> --- dolfin/la/GenericMatrix.h   2012-02-28 22:23:00 +0000
>> +++ dolfin/la/GenericMatrix.h   2012-03-08 20:25:41 +0000
>> @@ -137,10 +137,12 @@
>>     /// Set given rows to identity matrix
>>     virtual void ident(uint m, const uint* rows) = 0;
>> 
>> -    /// Matrix-vector product, y = Ax
>> +    /// Matrix-vector product, y = Ax. The y vector must either be zero-sized
>> +    /// or have correct size and parallel layout.
>>     virtual void mult(const GenericVector& x, GenericVector& y) const = 0;
>> 
>> -    /// Matrix-vector product, y = A^T x
>> +    /// Matrix-vector product, y = A^T x. The y vector must either be
>> +    /// zero-sized or have correct size and parallel layout.
>>     virtual void transpmult(const GenericVector& x, GenericVector& y) const = 0;
>> 
>>     /// Multiply matrix by given number
>> 
>> === modified file 'dolfin/la/PETScMatrix.cpp'
>> --- dolfin/la/PETScMatrix.cpp   2012-02-24 12:24:53 +0000
>> +++ dolfin/la/PETScMatrix.cpp   2012-03-08 20:25:41 +0000
>> @@ -393,8 +393,19 @@
>>                  "Non-matching dimensions for matrix-vector product");
>>   }
>> 
>> -  // Resize if dimensions does not match
>> -  resize(yy, 0);
>> +  // Resize RHS if empty
>> +  if (yy.size() == 0)
>> +  {
>> +    resize(yy, 0);
>> +  }
>> +
>> +  if (size(0) != yy.size())
>> +  {
>> +    dolfin_error("PETScMatrix.cpp",
>> +                 "compute matrix-vector product with PETSc matrix",
>> +                 "Vector for matrix-vector result has wrong size");
>> +  }
>> +
>>   MatMult(*A, *xx.vec(), *yy.vec());
>>  }
>>  //-----------------------------------------------------------------------------
>> @@ -412,7 +423,19 @@
>>                  "Non-matching dimensions for transpose matrix-vector product");
>>   }
>> 
>> -  resize(yy, 1);
>> +  // Resize RHS if empty
>> +  if (yy.size() == 0)
>> +  {
>> +    resize(yy, 1);
>> +  }
>> +
>> +  if (size(1) != yy.size())
>> +  {
>> +    dolfin_error("PETScMatrix.cpp",
>> +                 "compute transpose matrix-vector product with PETSc matrix",
>> +                 "Vector for transpose matrix-vector result has wrong size");
>> +  }
>> +
>>   MatMultTranspose(*A, *xx.vec(), *yy.vec());
>>  }
>>  //-----------------------------------------------------------------------------
>> 
>> === modified file 'dolfin/la/uBLASMatrix.h'
>> --- dolfin/la/uBLASMatrix.h     2012-02-24 12:24:53 +0000
>> +++ dolfin/la/uBLASMatrix.h     2012-03-08 20:25:41 +0000
>> @@ -461,7 +461,31 @@
>>   template <typename Mat>
>>   void uBLASMatrix<Mat>::mult(const GenericVector& x, GenericVector& y) const
>>   {
>> -    ublas::axpy_prod(A, x.down_cast<uBLASVector>().vec(),
>> y.down_cast<uBLASVector>().vec(), true);
>> +
>> +    const uBLASVector& xx = x.down_cast<uBLASVector>();
>> +    uBLASVector& yy = y.down_cast<uBLASVector>();
>> +
>> +    if (size(1) != xx.size())
>> +    {
>> +      dolfin_error("uBLASMatrix.cpp",
>> +                   "compute matrix-vector product with uBLAS matrix",
>> +                   "Non-matching dimensions for matrix-vector product");
>> +    }
>> +
>> +  // Resize RHS if empty
>> +  if (yy.size() == 0)
>> +  {
>> +    resize(yy, 0);
>> +  }
>> +
>> +  if (size(0) != yy.size())
>> +  {
>> +    dolfin_error("uBLASMatrix.cpp",
>> +                 "compute matrix-vector product with uBLAS matrix",
>> +                 "Vector for matrix-vector result has wrong size");
>> +  }
>> +
>> +    ublas::axpy_prod(A, xx.vec(), yy.vec(), true);
>>   }
>>   //-----------------------------------------------------------------------------
>>   template <typename Mat>
>> 
>> === modified file 'dolfin/swig/la/post.i'
>> --- dolfin/swig/la/post.i       2012-02-21 21:45:42 +0000
>> +++ dolfin/swig/la/post.i       2012-03-08 20:25:41 +0000
>> @@ -556,9 +556,9 @@
>>             if vector_type not in _matrix_vector_mul_map[matrix_type]:
>>                 raise TypeError, "Provide a Vector which can be
>> down_casted to ''"%vector_type.__name__
>>             if type(other) == Vector:
>> -                ret = Vector(self.size(0))
>> +                ret = Vector()
>>             else:
>> -                ret = vector_type(self.size(0))
>> +                ret = vector_type()
>>             self.mult(other, ret)
>>             return ret
>>         elif isinstance(other, ndarray):
>> 
>> === modified file 'test/unit/la/python/KrylovSolver.py'
>> --- test/unit/la/python/KrylovSolver.py 2012-02-29 18:44:36 +0000
>> +++ test/unit/la/python/KrylovSolver.py 2012-03-08 20:25:41 +0000
>> @@ -84,15 +84,12 @@
>>                 def __init__(self, A):
>>                     self.A = A
>> 
>> -                    # Use tmp vector as A.mult will resize the vector
>> -                    self.y_tmp = PETScVector()
>>                     PETScKrylovMatrix.__init__(self, A.size(0), A.size(1))
>> 
>>                 def mult(self, x, y):
>> 
>>                     # Make ordinary matrix vector product
>> -                    self.A.mult(x, self.y_tmp)
>> -                    y[:] = self.y_tmp
>> +                    self.A.mult(x, y)
>> 
>> 
>>             class MatrixFreeKrylovMatrix(PETScKrylovMatrix) :
>> 
>> _______________________________________________
>> Mailing list: https://launchpad.net/~dolfin
>> Post to     : dolfin@xxxxxxxxxxxxxxxxxxx
>> Unsubscribe : https://launchpad.net/~dolfin
>> More help   : https://help.launchpad.net/ListHelp
>> 


Follow ups

References