Skip to content

Commit 80576a3

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 80576a3

File tree

2 files changed

+319
-28
lines changed

2 files changed

+319
-28
lines changed

include/deal.II/multigrid/mg_transfer_matrix_free.h

Lines changed: 303 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -131,28 +131,33 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
131131
MemorySpace::Default>>,
132132
"This class is currently only implemented for vectors of "
133133
"type LinearAlgebra::distributed::Vector.");
134+
/**
135+
* Partitioner needed by the intermediate vector.
136+
*/
137+
std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_coarse;
134138

135139
/**
136-
* The scalar type used by the vector-type template argument.
140+
* Partitioner needed by the intermediate vector.
137141
*/
138-
using Number = typename VectorType::value_type;
142+
std::shared_ptr<const Utilities::MPI::Partitioner> partitioner_fine;
139143

140144
/**
141145
* Default constructor.
142146
*/
143-
MGTwoLevelTransferBase();
147+
MGTwoLevelTransferBase()
148+
{}
144149

145150
/**
146151
* Perform prolongation on a solution vector.
147152
*/
148-
void
149-
prolongate_and_add(VectorType &dst, const VectorType &src) const;
153+
virtual void
154+
prolongate_and_add(VectorType &dst, const VectorType &src) const = 0;
150155

151156
/**
152157
* Perform restriction on a residual vector.
153158
*/
154-
void
155-
restrict_and_add(VectorType &dst, const VectorType &src) const;
159+
virtual void
160+
restrict_and_add(VectorType &dst, const VectorType &src) const = 0;
156161

157162
/**
158163
* Perform interpolation of a solution vector from the fine level to the
@@ -181,6 +186,51 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
181186
*/
182187
virtual std::size_t
183188
memory_consumption() const = 0;
189+
};
190+
191+
192+
193+
/**
194+
* A class which provides extra functionality used by several MGTwoLevelTransfer
195+
* schemes.
196+
*/
197+
template <typename VectorType>
198+
class MGTwoLevelTransferCore : public MGTwoLevelTransferBase<VectorType>
199+
{
200+
public:
201+
static_assert(
202+
std::is_same_v<
203+
VectorType,
204+
LinearAlgebra::distributed::Vector<typename VectorType::value_type,
205+
MemorySpace::Host>> ||
206+
std::is_same_v<
207+
VectorType,
208+
LinearAlgebra::distributed::Vector<typename VectorType::value_type,
209+
MemorySpace::Default>>,
210+
"This class is currently only implemented for vectors of "
211+
"type LinearAlgebra::distributed::Vector.");
212+
213+
/**
214+
* The scalar type used by the vector-type template argument.
215+
*/
216+
using Number = typename VectorType::value_type;
217+
218+
/**
219+
* Default constructor.
220+
*/
221+
MGTwoLevelTransferCore();
222+
223+
/**
224+
* @copydoc MGTwoLevelTransferBase::prolongate_and_add
225+
*/
226+
void
227+
prolongate_and_add(VectorType &dst, const VectorType &src) const override;
228+
229+
/**
230+
* @copydoc MGTwoLevelTransferBase::restrict_and_add
231+
*/
232+
void
233+
restrict_and_add(VectorType &dst, const VectorType &src) const override;
184234

185235
protected:
186236
/**
@@ -242,17 +292,6 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
242292
*/
243293
bool fine_element_is_continuous;
244294

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-
256295
protected:
257296
/**
258297
* Internal vector on which the actual prolongation/restriction is performed.
@@ -327,7 +366,7 @@ class MGTwoLevelTransferBase : public EnableObserverPointer
327366
* point, and we fall back to the first option in such a case.
328367
*/
329368
template <int dim, typename VectorType>
330-
class MGTwoLevelTransfer : public MGTwoLevelTransferBase<VectorType>
369+
class MGTwoLevelTransfer : public MGTwoLevelTransferCore<VectorType>
331370
{
332371
public:
333372
static_assert(
@@ -627,6 +666,250 @@ class MGTwoLevelTransfer : public MGTwoLevelTransferBase<VectorType>
627666

628667
friend class internal::MGTwoLevelTransferImplementation;
629668

669+
friend class MGTransferMatrixFree<dim, Number, MemorySpace::Host>;
670+
671+
friend class MGTransferMatrixFree<dim, Number, MemorySpace::Default>;
672+
};
673+
674+
675+
/**
676+
* A transfer class supporting device vectors via copying them to the host and
677+
* using an internal trasfer of type MGTwoLevelTransfer defined on the
678+
* host.
679+
*/
680+
template <int dim, typename VectorType>
681+
class MGTwoLevelTransferCopyToHost : public MGTwoLevelTransferBase<VectorType>
682+
{
683+
public:
684+
static_assert(
685+
std::is_same_v<
686+
VectorType,
687+
LinearAlgebra::distributed::Vector<typename VectorType::value_type,
688+
MemorySpace::Host>> ||
689+
std::is_same_v<
690+
VectorType,
691+
LinearAlgebra::distributed::Vector<typename VectorType::value_type,
692+
MemorySpace::Default>>,
693+
"This class is currently only implemented for vectors of "
694+
"type LinearAlgebra::distributed::Vector.");
695+
696+
697+
/**
698+
* The scalar type used by the vector-type template argument.
699+
*/
700+
using Number = typename VectorType::value_type;
701+
702+
using VectorTypeHost = LinearAlgebra::distributed::Vector<Number>;
703+
/**
704+
* Default constructor.
705+
*/
706+
MGTwoLevelTransferCopyToHost()
707+
: host_transfer()
708+
{}
709+
710+
/**
711+
* @copydoc MGTwoLevelTransfer::reinit_geometric_transfer
712+
*/
713+
void
714+
reinit_geometric_transfer(
715+
const DoFHandler<dim> &dof_handler_fine,
716+
const DoFHandler<dim> &dof_handler_coarse,
717+
const AffineConstraints<Number> &constraint_fine =
718+
AffineConstraints<Number>(),
719+
const AffineConstraints<Number> &constraint_coarse =
720+
AffineConstraints<Number>(),
721+
const unsigned int mg_level_fine = numbers::invalid_unsigned_int,
722+
const unsigned int mg_level_coarse = numbers::invalid_unsigned_int)
723+
{
724+
host_transfer.reinit_geometric_transfer(dof_handler_fine,
725+
dof_handler_coarse,
726+
constraint_fine,
727+
constraint_coarse,
728+
mg_level_fine,
729+
mg_level_coarse);
730+
}
731+
732+
/**
733+
* @copydoc MGTwoLevelTransfer::reinit_polynomial_transfer
734+
*/
735+
void
736+
reinit_polynomial_transfer(
737+
const DoFHandler<dim> &dof_handler_fine,
738+
const DoFHandler<dim> &dof_handler_coarse,
739+
const AffineConstraints<Number> &constraint_fine =
740+
AffineConstraints<Number>(),
741+
const AffineConstraints<Number> &constraint_coarse =
742+
AffineConstraints<Number>(),
743+
const unsigned int mg_level_fine = numbers::invalid_unsigned_int,
744+
const unsigned int mg_level_coarse = numbers::invalid_unsigned_int)
745+
{
746+
host_transfer.reinit_polynomial_transfer(dof_handler_fine,
747+
dof_handler_coarse,
748+
constraint_fine,
749+
constraint_coarse,
750+
mg_level_fine,
751+
mg_level_coarse);
752+
}
753+
754+
/**
755+
* @copydoc MGTwoLevelTransfer::reinit(const DoFHandler<dim>, const DoFHandler<dim>, const AffineConstraints<Number>, const AffineConstraints<Number>, const unsigned int, const unsigned int)
756+
*/
757+
void
758+
reinit(const DoFHandler<dim> &dof_handler_fine,
759+
const DoFHandler<dim> &dof_handler_coarse,
760+
const AffineConstraints<Number> &constraint_fine =
761+
AffineConstraints<Number>(),
762+
const AffineConstraints<Number> &constraint_coarse =
763+
AffineConstraints<Number>(),
764+
const unsigned int mg_level_fine = numbers::invalid_unsigned_int,
765+
const unsigned int mg_level_coarse = numbers::invalid_unsigned_int)
766+
{
767+
host_transfer.reinit(dof_handler_fine,
768+
dof_handler_coarse,
769+
constraint_fine,
770+
constraint_coarse,
771+
mg_level_fine,
772+
mg_level_coarse);
773+
}
774+
775+
/**
776+
* @copydoc MGTwoLevelTransfer::reinit(const MatrixFree<dim, Number>, const unsigned int, const MatrixFree<dim, Number>, const unsigned int)
777+
*/
778+
void
779+
reinit(const MatrixFree<dim, Number> &matrix_free_fine,
780+
const unsigned int dof_no_fine,
781+
const MatrixFree<dim, Number> &matrix_free_coarse,
782+
const unsigned int dof_no_coarse)
783+
{
784+
host_transfer.reinit(matrix_free_fine,
785+
dof_no_fine,
786+
matrix_free_coarse,
787+
dof_no_coarse);
788+
}
789+
790+
/**
791+
* @copydoc MGTwoLevelTransfer::fast_polynomial_transfer_supported
792+
*/
793+
bool
794+
fast_polynomial_transfer_supported(const unsigned int fe_degree_fine,
795+
const unsigned int fe_degree_coarse)
796+
{
797+
return host_transfer.fast_polynomial_transfer_supported(fe_degree_fine,
798+
fe_degree_coarse);
799+
}
800+
801+
/**
802+
* @copydoc MGTwoLevelTransfer::prolongate_and_add
803+
*/
804+
void
805+
prolongate_and_add(VectorType &dst, const VectorType &src) const override
806+
{
807+
VectorTypeHost dst_host;
808+
VectorTypeHost src_host;
809+
810+
dst_host.reinit(dst.get_partitioner());
811+
copy_to_host(src_host, src);
812+
813+
host_transfer.prolongate_and_add(dst_host, src_host);
814+
815+
copy_from_host(dst, dst_host);
816+
}
817+
818+
/**
819+
* @copydoc MGTwoLevelTransfer::restrict_and_add
820+
*/
821+
void
822+
restrict_and_add(VectorType &dst, const VectorType &src) const override
823+
{
824+
VectorTypeHost dst_host;
825+
VectorTypeHost src_host;
826+
827+
copy_to_host(dst_host, dst);
828+
copy_to_host(src_host, src);
829+
830+
host_transfer.restrict_and_add(dst_host, src_host);
831+
832+
copy_from_host(dst, dst_host);
833+
}
834+
835+
/**
836+
* @copydoc MGTwoLevelTransfer::interpolate
837+
*/
838+
void
839+
interpolate(VectorType &dst, const VectorType &src) const override
840+
{
841+
VectorTypeHost dst_host;
842+
VectorTypeHost src_host;
843+
844+
copy_to_host(dst_host, dst);
845+
copy_to_host(src_host, src);
846+
847+
host_transfer.interpolate(dst_host, src_host);
848+
849+
copy_from_host(dst, dst_host);
850+
}
851+
852+
/**
853+
* @copydoc MGTwoLevelTransfer::enable_inplace_operations_if_possible
854+
*/
855+
std::pair<bool, bool>
856+
enable_inplace_operations_if_possible(
857+
const std::shared_ptr<const Utilities::MPI::Partitioner>
858+
&partitioner_coarse,
859+
const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner_fine)
860+
override
861+
{
862+
return host_transfer.enable_inplace_operations_if_possible(
863+
partitioner_coarse, partitioner_fine);
864+
}
865+
866+
/**
867+
* @copydoc MGTwoLevelTransfer::memory_consumption
868+
*/
869+
std::size_t
870+
memory_consumption() const override
871+
{
872+
return host_transfer.memory_consumption();
873+
}
874+
875+
private:
876+
/**
877+
* The internal transfer defined on the host which handles all operations.
878+
*/
879+
MGTwoLevelTransfer<dim, VectorTypeHost> host_transfer;
880+
881+
882+
/**
883+
* Copies a device vector to a host vector.
884+
*/
885+
void
886+
copy_to_host(VectorTypeHost &dst, const VectorType &src) const
887+
{
888+
LinearAlgebra::ReadWriteVector<Number> rw_vector(
889+
src.get_partitioner()->locally_owned_range());
890+
rw_vector.import_elements(src, VectorOperation::insert);
891+
892+
dst.reinit(src.get_partitioner());
893+
dst.import_elements(rw_vector, VectorOperation::insert);
894+
}
895+
896+
/**
897+
* Copies a host vector to a device vector.
898+
*/
899+
void
900+
copy_from_host(VectorType &dst, const VectorTypeHost &src) const
901+
{
902+
LinearAlgebra::ReadWriteVector<Number> rw_vector(
903+
src.get_partitioner()->locally_owned_range());
904+
rw_vector.import_elements(src, VectorOperation::insert);
905+
906+
if (dst.size() == 0)
907+
dst.reinit(src.get_partitioner());
908+
dst.import_elements(rw_vector, VectorOperation::insert);
909+
}
910+
911+
friend class internal::MGTwoLevelTransferImplementation;
912+
630913
friend class MGTransferMatrixFree<dim,
631914
Number,
632915
typename VectorType::memory_space>;
@@ -638,7 +921,7 @@ class MGTwoLevelTransfer : public MGTwoLevelTransferBase<VectorType>
638921
* Class for transfer between two non-nested multigrid levels.
639922
*/
640923
template <int dim, typename VectorType>
641-
class MGTwoLevelTransferNonNested : public MGTwoLevelTransferBase<VectorType>
924+
class MGTwoLevelTransferNonNested : public MGTwoLevelTransferCore<VectorType>
642925
{
643926
private:
644927
static_assert(

0 commit comments

Comments
 (0)