Skip to content

Commit 438684e

Browse files
committed
Add MGTwoLevelTransferCopyToHost, a two level transfer class which permits transfer on device vectors via use of an internal MGTwoLevelTransfer class defined on the host.
1 parent b21f382 commit 438684e

File tree

5 files changed

+364
-42
lines changed

5 files changed

+364
-42
lines changed

include/deal.II/multigrid/mg_transfer_matrix_free.h

Lines changed: 313 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -133,26 +133,26 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
133133
"type LinearAlgebra::distributed::Vector.");
134134

135135
/**
136-
* The scalar type used by the vector-type template argument.
136+
* Partitioner needed by the intermediate vector.
137137
*/
138-
using Number = typename VectorType::value_type;
138+
std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_coarse;
139139

140140
/**
141-
* Default constructor.
141+
* Partitioner needed by the intermediate vector.
142142
*/
143-
MGTwoLevelTransferBase();
143+
std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_fine;
144144

145145
/**
146146
* Perform prolongation on a solution vector.
147147
*/
148-
void
149-
prolongate_and_add(VectorType &dst, const VectorType &src) const;
148+
virtual void
149+
prolongate_and_add(VectorType &dst, const VectorType &src) const = 0;
150150

151151
/**
152152
* Perform restriction on a residual vector.
153153
*/
154-
void
155-
restrict_and_add(VectorType &dst, const VectorType &src) const;
154+
virtual void
155+
restrict_and_add(VectorType &dst, const VectorType &src) const = 0;
156156

157157
/**
158158
* Perform interpolation of a solution vector from the fine level to the
@@ -181,6 +181,38 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
181181
*/
182182
virtual std::size_t
183183
memory_consumption() const = 0;
184+
};
185+
186+
187+
188+
/**
189+
* Base class for MGTwoLevelTransferNonNested and MGTwoLevelTransfer.
190+
*/
191+
template <typename VectorType>
192+
class MGTwoLevelTransferCore : public MGTwoLevelTransferBase<VectorType>
193+
{
194+
public:
195+
/**
196+
* The scalar type used by the vector-type template argument.
197+
*/
198+
using Number = typename VectorType::value_type;
199+
200+
/**
201+
* Default constructor.
202+
*/
203+
MGTwoLevelTransferCore();
204+
205+
/**
206+
* @copydoc MGTwoLevelTransferBase::prolongate_and_add
207+
*/
208+
void
209+
prolongate_and_add(VectorType &dst, const VectorType &src) const override;
210+
211+
/**
212+
* @copydoc MGTwoLevelTransferBase::restrict_and_add
213+
*/
214+
void
215+
restrict_and_add(VectorType &dst, const VectorType &src) const override;
184216

185217
protected:
186218
/**
@@ -242,17 +274,6 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
242274
*/
243275
bool fine_element_is_continuous;
244276

245-
public:
246-
/**
247-
* Partitioner needed by the intermediate vector.
248-
*/
249-
std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_coarse;
250-
251-
/**
252-
* Partitioner needed by the intermediate vector.
253-
*/
254-
std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_fine;
255-
256277
protected:
257278
/**
258279
* Internal vector on which the actual prolongation/restriction is performed.
@@ -327,7 +348,7 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
327348
* point, and we fall back to the first option in such a case.
328349
*/
329350
template <int dim, typename VectorType>
330-
class MGTwoLevelTransfer : public MGTwoLevelTransferBase<VectorType>
351+
class MGTwoLevelTransfer : public MGTwoLevelTransferCore<VectorType>
331352
{
332353
public:
333354
static_assert(
@@ -627,6 +648,133 @@ class MGTwoLevelTransfer : public MGTwoLevelTransferBase<VectorType>
627648

628649
friend class internal::MGTwoLevelTransferImplementation;
629650

651+
friend class MGTransferMatrixFree<dim, Number, MemorySpace::Host>;
652+
653+
friend class MGTransferMatrixFree<dim, Number, MemorySpace::Default>;
654+
};
655+
656+
657+
/**
658+
* A transfer class supporting device vectors via copying them to the host and
659+
* using an internal transfer of type MGTwoLevelTransfer defined on the
660+
* host.
661+
*/
662+
template <int dim, typename VectorType>
663+
class MGTwoLevelTransferCopyToHost : public MGTwoLevelTransferBase<VectorType>
664+
{
665+
public:
666+
static_assert(
667+
std::is_same_v<
668+
VectorType,
669+
LinearAlgebra::distributed::Vector<typename VectorType::value_type,
670+
MemorySpace::Default>>,
671+
"This class is currently only implemented for vectors of "
672+
"type LinearAlgebra::distributed::Vector, This class should not be initialized on the host as it will perform redundant transfers. Use MGTwoLevelTransfer instead.");
673+
674+
675+
/**
676+
* The scalar type used by the vector-type template argument.
677+
*/
678+
using Number = typename VectorType::value_type;
679+
680+
using VectorTypeHost =
681+
LinearAlgebra::distributed::Vector<Number, MemorySpace::Host>;
682+
/**
683+
* Default constructor.
684+
*/
685+
MGTwoLevelTransferCopyToHost() = default;
686+
687+
/**
688+
* @copydoc MGTwoLevelTransfer::reinit(const DoFHandler<dim>, const DoFHandler<dim>, const AffineConstraints<Number>, const AffineConstraints<Number>, const unsigned int, const unsigned int)
689+
*/
690+
void
691+
reinit(const DoFHandler<dim> &dof_handler_fine,
692+
const DoFHandler<dim> &dof_handler_coarse,
693+
const AffineConstraints<Number> &constraint_fine =
694+
AffineConstraints<Number>(),
695+
const AffineConstraints<Number> &constraint_coarse =
696+
AffineConstraints<Number>(),
697+
const unsigned int mg_level_fine = numbers::invalid_unsigned_int,
698+
const unsigned int mg_level_coarse = numbers::invalid_unsigned_int);
699+
700+
/**
701+
* @copydoc MGTwoLevelTransfer::reinit(const MatrixFree<dim, Number>, const unsigned int, const MatrixFree<dim, Number>, const unsigned int)
702+
*/
703+
void
704+
reinit(const MatrixFree<dim, Number> &matrix_free_fine,
705+
const unsigned int dof_no_fine,
706+
const MatrixFree<dim, Number> &matrix_free_coarse,
707+
const unsigned int dof_no_coarse);
708+
709+
/**
710+
* @copydoc MGTwoLevelTransfer::fast_polynomial_transfer_supported
711+
*/
712+
bool
713+
fast_polynomial_transfer_supported(const unsigned int fe_degree_fine,
714+
const unsigned int fe_degree_coarse);
715+
716+
/**
717+
* @copydoc MGTwoLevelTransfer::prolongate_and_add
718+
*/
719+
void
720+
prolongate_and_add(VectorType &dst, const VectorType &src) const override;
721+
722+
/**
723+
* @copydoc MGTwoLevelTransfer::restrict_and_add
724+
*/
725+
void
726+
restrict_and_add(VectorType &dst, const VectorType &src) const override;
727+
728+
/**
729+
* @copydoc MGTwoLevelTransfer::interpolate
730+
*/
731+
void
732+
interpolate(VectorType &dst, const VectorType &src) const override;
733+
734+
/**
735+
* @copydoc MGTwoLevelTransfer::enable_inplace_operations_if_possible
736+
*/
737+
std::pair<bool, bool>
738+
enable_inplace_operations_if_possible(
739+
const std::shared_ptr<const Utilities::MPI::Partitioner>
740+
&partitioner_coarse,
741+
const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner_fine)
742+
override;
743+
744+
/**
745+
* @copydoc MGTwoLevelTransfer::memory_consumption
746+
*/
747+
std::size_t
748+
memory_consumption() const override;
749+
750+
private:
751+
/**
752+
* The internal transfer defined on the host which handles all operations.
753+
*/
754+
MGTwoLevelTransfer<dim, VectorTypeHost> host_transfer;
755+
756+
/**
757+
* Vectors used for the host transfer.
758+
*/
759+
760+
mutable VectorTypeHost host_vector_coarse;
761+
762+
mutable VectorTypeHost host_vector_fine;
763+
764+
/**
765+
* Copies a device vector to a host vector.
766+
*/
767+
void
768+
copy_to_host(VectorTypeHost &dst, const VectorType &src) const;
769+
770+
/**
771+
* Copies a host vector to a device vector.
772+
*/
773+
void
774+
copy_from_host(VectorType &dst, const VectorTypeHost &src) const;
775+
776+
friend class internal::MGTwoLevelTransferImplementation;
777+
630778
friend class MGTransferMatrixFree<dim,
631779
Number,
632780
typename VectorType::memory_space>;
@@ -638,7 +786,7 @@ class MGTwoLevelTransfer : public MGTwoLevelTransferBase<VectorType>
638786
* Class for transfer between two non-nested multigrid levels.
639787
*/
640788
template <int dim, typename VectorType>
641-
class MGTwoLevelTransferNonNested : public MGTwoLevelTransferBase<VectorType>
789+
class MGTwoLevelTransferNonNested : public MGTwoLevelTransferCore<VectorType>
642790
{
643791
private:
644792
static_assert(
@@ -1451,6 +1599,150 @@ class MGTransferBlockMatrixFree
14511599

14521600
/* ----------------------- Inline functions --------------------------------- */
14531601

1602+
template <int dim, typename VectorType>
1603+
void
1604+
MGTwoLevelTransferCopyToHost<dim, VectorType>::reinit(
1605+
const DoFHandler<dim> &dof_handler_fine,
1606+
const DoFHandler<dim> &dof_handler_coarse,
1607+
const AffineConstraints<Number> &constraint_fine,
1608+
const AffineConstraints<Number> &constraint_coarse,
1609+
const unsigned int mg_level_fine,
1610+
const unsigned int mg_level_coarse)
1611+
{
1612+
host_transfer.reinit(dof_handler_fine,
1613+
dof_handler_coarse,
1614+
constraint_fine,
1615+
constraint_coarse,
1616+
mg_level_fine,
1617+
mg_level_coarse);
1618+
}
1619+
1620+
template <int dim, typename VectorType>
1621+
void
1622+
MGTwoLevelTransferCopyToHost<dim, VectorType>::reinit(
1623+
const MatrixFree<dim, Number> &matrix_free_fine,
1624+
const unsigned int dof_no_fine,
1625+
const MatrixFree<dim, Number> &matrix_free_coarse,
1626+
const unsigned int dof_no_coarse)
1627+
{
1628+
host_transfer.reinit(matrix_free_fine,
1629+
dof_no_fine,
1630+
matrix_free_coarse,
1631+
dof_no_coarse);
1632+
}
1633+
1634+
1635+
template <int dim, typename VectorType>
1636+
bool
1637+
MGTwoLevelTransferCopyToHost<dim, VectorType>::
1638+
fast_polynomial_transfer_supported(const unsigned int fe_degree_fine,
1639+
const unsigned int fe_degree_coarse)
1640+
{
1641+
return host_transfer.fast_polynomial_transfer_supported(fe_degree_fine,
1642+
fe_degree_coarse);
1643+
}
1644+
1645+
template <int dim, typename VectorType>
1646+
void
1647+
MGTwoLevelTransferCopyToHost<dim, VectorType>::prolongate_and_add(
1648+
VectorType &dst,
1649+
const VectorType &src) const
1650+
{
1651+
if (host_vector_coarse.size() == 0)
1652+
host_vector_coarse.reinit(src.get_partitioner());
1653+
if (host_vector_fine.size() == 0)
1654+
host_vector_fine.reinit(dst.get_partitioner());
1655+
1656+
copy_to_host(host_vector_fine, dst);
1657+
copy_to_host(host_vector_coarse, src);
1658+
1659+
host_transfer.prolongate_and_add(host_vector_fine, host_vector_coarse);
1660+
1661+
copy_from_host(dst, host_vector_fine);
1662+
}
1663+
1664+
template <int dim, typename VectorType>
1665+
void
1666+
MGTwoLevelTransferCopyToHost<dim, VectorType>::restrict_and_add(
1667+
VectorType &dst,
1668+
const VectorType &src) const
1669+
{
1670+
if (host_vector_coarse.size() == 0)
1671+
host_vector_coarse.reinit(dst.get_partitioner());
1672+
if (host_vector_fine.size() == 0)
1673+
host_vector_fine.reinit(src.get_partitioner());
1674+
1675+
copy_to_host(host_vector_coarse, dst);
1676+
copy_to_host(host_vector_fine, src);
1677+
1678+
host_transfer.restrict_and_add(host_vector_coarse, host_vector_fine);
1679+
1680+
copy_from_host(dst, host_vector_coarse);
1681+
}
1682+
1683+
template <int dim, typename VectorType>
1684+
void
1685+
MGTwoLevelTransferCopyToHost<dim, VectorType>::interpolate(
1686+
VectorType &dst,
1687+
const VectorType &src) const
1688+
{
1689+
if (host_vector_coarse.size() == 0)
1690+
host_vector_coarse.reinit(dst.get_partitioner());
1691+
if (host_vector_fine.size() == 0)
1692+
host_vector_fine.reinit(src.get_partitioner());
1693+
1694+
copy_to_host(host_vector_fine, src);
1695+
1696+
host_transfer.interpolate(host_vector_coarse, host_vector_fine);
1697+
1698+
copy_from_host(dst, host_vector_coarse);
1699+
}
1700+
1701+
template <int dim, typename VectorType>
1702+
std::pair<bool, bool>
1703+
MGTwoLevelTransferCopyToHost<dim, VectorType>::
1704+
enable_inplace_operations_if_possible(
1705+
const std::shared_ptr<const Utilities::MPI::Partitioner>
1706+
&partitioner_coarse,
1707+
const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner_fine)
1708+
{
1709+
return host_transfer.enable_inplace_operations_if_possible(partitioner_coarse,
1710+
partitioner_fine);
1711+
}
1712+
1713+
template <int dim, typename VectorType>
1714+
std::size_t
1715+
MGTwoLevelTransferCopyToHost<dim, VectorType>::memory_consumption() const
1716+
{
1717+
return host_transfer.memory_consumption();
1718+
}
1719+
1720+
template <int dim, typename VectorType>
1721+
void
1722+
MGTwoLevelTransferCopyToHost<dim, VectorType>::copy_to_host(
1723+
VectorTypeHost &dst,
1724+
const VectorType &src) const
1725+
{
1726+
LinearAlgebra::ReadWriteVector<Number> rw_vector(
1727+
src.get_partitioner()->locally_owned_range());
1728+
rw_vector.import_elements(src, VectorOperation::insert);
1729+
1730+
dst.import_elements(rw_vector, VectorOperation::insert);
1731+
}
1732+
1733+
template <int dim, typename VectorType>
1734+
void
1735+
MGTwoLevelTransferCopyToHost<dim, VectorType>::copy_from_host(
1736+
VectorType &dst,
1737+
const VectorTypeHost &src) const
1738+
{
1739+
LinearAlgebra::ReadWriteVector<Number> rw_vector(
1740+
src.get_partitioner()->locally_owned_range());
1741+
rw_vector.import_elements(src, VectorOperation::insert);
1742+
1743+
dst.import_elements(rw_vector, VectorOperation::insert);
1744+
}
1745+
14541746

14551747

14561748
template <int dim, typename Number, typename MemorySpace>

0 commit comments

Comments
 (0)