]> https://gitweb.dealii.org/ - dealii.git/commitdiff
working
authorDaniel Arndt <arndtd@ornl.gov>
Thu, 1 Dec 2022 20:14:40 +0000 (20:14 +0000)
committerDaniel Arndt <arndtd@ornl.gov>
Thu, 8 Dec 2022 22:13:15 +0000 (17:13 -0500)
include/deal.II/base/memory_space_data.h
include/deal.II/lac/la_parallel_vector.templates.h
source/base/kokkos.cc

index da0b809c8dd87f9b5fcc3ba361e1457710bbc1e5..6daecffd5ac465f141394880e3cd7e964352256a 100644 (file)
@@ -23,7 +23,9 @@
 #include <deal.II/base/exceptions.h>
 #include <deal.II/base/kokkos.h>
 
+DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
 #include <Kokkos_Core.hpp>
+DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
 
 #include <functional>
 #include <memory>
@@ -35,37 +37,47 @@ DEAL_II_NAMESPACE_OPEN
 namespace MemorySpace
 {
   /**
-   * Structure which stores data on the host or the device depending on the
-   * template parameter @p MemorySpace. The data is copied into the structure
-   * which then owns the data and will release the memory when the destructor is
-   * called.
+   * Data structure
    */
   template <typename T, typename MemorySpace>
   struct MemorySpaceData
   {
-    MemorySpaceData();
+    MemorySpaceData()
+    {
+      static_assert(std::is_same<MemorySpace, Host>::value ||
+                      std::is_same<MemorySpace, Device>::value,
+                    "MemorySpace should be Host or Device");
+    }
 
     /**
      * Copy the active data (values for Host and values_dev for Device) to @p begin.
      * If the data is on the device it is moved to the host.
      */
     void
-    copy_to(T *begin, const std::size_t n_elements);
+    copy_to(T *begin, std::size_t n_elements)
+    {
+      (void)begin;
+      (void)n_elements;
+    }
 
     /**
      * Copy the data in @p begin to the active data of the structure (values for
      * Host and values_dev for Device). The pointer @p begin must be on the host.
      */
     void
-    copy_from(const T *begin, const std::size_t n_elements);
+    copy_from(T *begin, std::size_t n_elements)
+    {
+      (void)begin;
+      (void)n_elements;
+    }
 
     /**
-     * Kokkos View to the data on the host
+     * Pointer to data on the host.
      */
     Kokkos::View<T *, Kokkos::HostSpace> values;
 
     /**
-     * Kokkos View to the data on the device
+     * Pointer to data on the device.
      */
     Kokkos::View<T *, typename MemorySpace::kokkos_space> values_dev;
 
@@ -76,12 +88,12 @@ namespace MemorySpace
     // The pointer is shared so that MemorySpaceData can be copied and
     // MemorySpaceData::values can be used in Kokkos::parallel_for. This
     // pointer owns the data when using shared memory with MPI. In this case,
-    // the Kokkos::View in non-owning. When shared memory with MPI is not used,
-    // the pointer is not used.
+    // the (host) Kokkos::View is non-owning. When shared memory with MPI is not
+    // used, the pointer is not used.
     std::shared_ptr<T> values_sm_ptr;
 
     /**
-     * Pointers to the data of the processes sharing the same memory.
+     * Pointers to the data of the processes sharing the same memory. Not used for MemorySpace::Device.
      */
     std::vector<ArrayView<const T>> values_sm;
   };
@@ -93,77 +105,146 @@ namespace MemorySpace
    */
   template <typename T, typename MemorySpace>
   inline void
-  swap(MemorySpaceData<T, MemorySpace> &u, MemorySpaceData<T, MemorySpace> &v);
-
+  swap(MemorySpaceData<T, MemorySpace> &,
+       MemorySpaceData<T, MemorySpace> &)
+  {
+    static_assert(std::is_same<MemorySpace, Host>::value ||
+                    std::is_same<MemorySpace, Device>::value,
+                  "MemorySpace should be Host or Device");
+  }
 
 #ifndef DOXYGEN
 
-  template <typename T, typename MemorySpace>
-  MemorySpaceData<T, MemorySpace>::MemorySpaceData()
+  template <typename T>
+  struct MemorySpaceData<T, Host>
+  {
+    using MemorySpace = Host;
+
+    MemorySpaceData()
     : values((dealii::Impl::ensure_kokkos_initialized(),
               Kokkos::View<T *, Kokkos::HostSpace>("host data", 0)))
-    , values_dev(Kokkos::View<T *, typename MemorySpace::kokkos_space>(
-        "memoryspace data",
-        0))
-  {}
+    {}
 
+    void
+    copy_to(T *begin, std::size_t n_elements)
+    {
+      Assert(n_elements <= values.extent(0),
+             ExcMessage("n_elements greater than the size of values."));
+      using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space;
+      Kokkos::
+        View<T *, Kokkos::HostSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>
+          begin_view(begin, n_elements);
+      Kokkos::deep_copy(
+        ExecutionSpace{},
+        begin_view,
+        Kokkos::subview(values, Kokkos::make_pair(std::size_t(0), n_elements)));
+      ExecutionSpace{}.fence();
+    }
 
+    void
+    copy_from(T *begin, std::size_t n_elements)
+    {
+      Assert(n_elements <= values.extent(0),
+             ExcMessage("n_elements greater than the size of values."));
+      using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space;
+      Kokkos::View<const T *,
+                   Kokkos::HostSpace,
+                   Kokkos::MemoryTraits<Kokkos::Unmanaged>>
+        begin_view(begin, n_elements);
+      Kokkos::deep_copy(
+        ExecutionSpace{},
+        Kokkos::subview(values, Kokkos::make_pair(std::size_t(0), n_elements)),
+        begin_view);
+      ExecutionSpace{}.fence();
+    }
 
-  template <typename T, typename MemorySpace>
-  void
-  MemorySpaceData<T, MemorySpace>::copy_to(T *               begin,
-                                           const std::size_t n_elements)
+    Kokkos::View<T *, Kokkos::HostSpace> values;
+
+    // unused
+    Kokkos::View<T *, typename MemorySpace::kokkos_space> values_dev;
+
+    std::shared_ptr<T> values_sm_ptr;
+
+    std::vector<ArrayView<const T>> values_sm;
+  };
+
+
+
+  template <typename T>
+  inline void
+  swap(MemorySpaceData<T, Host> &u, MemorySpaceData<T, Host> &v)
   {
-    Assert(n_elements <= values.extent(0),
-           ExcMessage("n_elements greater than the size of values."));
-    using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space;
-    Kokkos::
-      View<T *, Kokkos::HostSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>
-        begin_view(begin, n_elements);
-    Kokkos::deep_copy(
-      ExecutionSpace{},
-      begin_view,
-      Kokkos::subview(values, Kokkos::make_pair(std::size_t(0), n_elements)));
-    ExecutionSpace{}.fence();
+    std::swap(u.values, v.values);
+    std::swap(u.values_sm_ptr, v.values_sm_ptr);
   }
 
 
 
-  template <typename T, typename MemorySpace>
-  void
-  MemorySpaceData<T, MemorySpace>::copy_from(const T *         begin,
-                                             const std::size_t n_elements)
+  template <typename T>
+  struct MemorySpaceData<T, Device>
   {
-    Assert(n_elements <= values.extent(0),
-           ExcMessage("n_elements greater than the size of values."));
-    using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space;
-    Kokkos::View<const T *,
-                 Kokkos::HostSpace,
-                 Kokkos::MemoryTraits<Kokkos::Unmanaged>>
-      begin_view(begin, n_elements);
-    Kokkos::deep_copy(
-      ExecutionSpace{},
-      Kokkos::subview(values, Kokkos::make_pair(std::size_t(0), n_elements)),
-      begin_view);
-    ExecutionSpace{}.fence();
-  }
+    using MemorySpace = Device;
 
+    MemorySpaceData()
+    : values((dealii::Impl::ensure_kokkos_initialized(),
+              Kokkos::View<T *, Kokkos::HostSpace>("host data", 0)))
+    , values_dev(Kokkos::View<T *, typename MemorySpace::kokkos_space>(
+        "memoryspace data",
+        0))
+    {}
 
+    void
+    copy_to(T *begin, std::size_t n_elements)
+    {
+      Assert(n_elements <= values_dev.extent(0),
+             ExcMessage("n_elements greater than the size of values."));
+      using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space;
+      Kokkos::
+        View<T *, Kokkos::HostSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged>>
+          begin_view(begin, n_elements);
+      Kokkos::deep_copy(
+        ExecutionSpace{},
+        begin_view,
+        Kokkos::subview(values_dev, Kokkos::make_pair(std::size_t(0), n_elements)));
+      ExecutionSpace{}.fence();
+    }
 
-  /**
-   * Swap function similar to std::swap.
-   */
-  template <typename T, typename MemorySpace>
+    void
+    copy_from(T *begin, std::size_t n_elements)
+    {
+      Assert(n_elements <= values_dev.extent(0),
+             ExcMessage("n_elements greater than the size of values."));
+      using ExecutionSpace = typename MemorySpace::kokkos_space::execution_space;
+      Kokkos::View<const T *,
+                   Kokkos::HostSpace,
+                   Kokkos::MemoryTraits<Kokkos::Unmanaged>>
+        begin_view(begin, n_elements);
+      Kokkos::deep_copy(
+        ExecutionSpace{},
+        Kokkos::subview(values_dev, Kokkos::make_pair(std::size_t(0), n_elements)),
+        begin_view);
+      ExecutionSpace{}.fence();
+    }
+
+    Kokkos::View<T *, Kokkos::HostSpace> values;
+    
+    Kokkos::View<T *, typename MemorySpace::kokkos_space> values_dev;
+    
+    // unused
+    std::shared_ptr<T> values_sm_ptr;
+  
+    // unused  
+    std::vector<ArrayView<const T>> values_sm;
+  };
+
+
+
+  template <typename T>
   inline void
-  swap(MemorySpaceData<T, MemorySpace> &u, MemorySpaceData<T, MemorySpace> &v)
+  swap(MemorySpaceData<T, Device> &u, MemorySpaceData<T, Device> &v)
   {
-    auto u_copy = Kokkos::create_mirror(Kokkos::WithoutInitializing, u);
-    typename MemorySpace::execution_space exec_space;
-    // The first two calls to Kokkos::deep_copy are asynchronous. The last call
-    // will wait for the three deep_copy to be done before returning.
-    Kokkos::deep_copy(exec_space, u_copy, u);
-    Kokkos::deep_copy(exec_space, u, v);
-    Kokkos::deep_copy(v, u_copy);
+    std::swap(u.values, v.values);
+    std::swap(u.values_dev, v.values_dev);
   }
 
 #endif
index 4f0375f03e691a7c0c2d575df732abf86c8cc9d8..1537aef5961f9375a070d2e54b2e9400bf9f8473 100644 (file)
@@ -1131,7 +1131,7 @@ namespace LinearAlgebra
         {
 #  if defined(DEAL_II_COMPILER_CUDA_AWARE) && \
     defined(DEAL_II_MPI_WITH_CUDA_SUPPORT)
-          Assert(
+               Assert(
             (std::is_same<MemorySpaceType, dealii::MemorySpace::CUDA>::value),
             ExcMessage(
               "Using MemorySpace::CUDA only allowed if the code is compiled with a CUDA compiler!"));
@@ -1148,17 +1148,40 @@ namespace LinearAlgebra
 #  endif
         }
 
+      if (std::is_same_v<MemorySpaceType, MemorySpace::Device>)
+             std::cout << "device" << std::endl;
+       if (std::is_same_v<MemorySpaceType, MemorySpace::Host>)
+              std::cout << "host" << std::endl;
+     std::cout << "size_dev: " <<  data.values_dev.extent(0) << " " << partitioner->locally_owned_size() << std::endl;
+     std::cout << "size_host: " <<  data.values.extent(0) << " " << partitioner->locally_owned_size() << std::endl;
+
 #  if defined DEAL_II_COMPILER_CUDA_AWARE && \
     !defined(DEAL_II_MPI_WITH_CUDA_SUPPORT)
-      // Move the data to the host and then move it back to the
-      // device. We use values to store the elements because the function
-      // uses a view of the array and thus we need the data on the host to
-      // outlive the scope of the function.
-      data.values = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, data.values_dev);
+     if (std::is_same_v<MemorySpaceType, MemorySpace::CUDA>) { 
+       // Move the data to the host and then move it back to the
+       // device. We use values to store the elements because the function
+       // uses a view of the array and thus we need the data on the host to
+       // outlive the scope of the function.
+       data.values = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, data.values_dev);
+     }
 #  endif
 
-#  if !(defined(DEAL_II_COMPILER_CUDA_AWARE) && \
-        defined(DEAL_II_MPI_WITH_CUDA_SUPPORT))
+#  if defined(DEAL_II_COMPILER_CUDA_AWARE) && \
+        defined(DEAL_II_MPI_WITH_CUDA_SUPPORT)
+          if (std::is_same_v<MemorySpaceType, MemorySpace::CUDA>) {
+ partitioner->export_to_ghosted_array_start<Number, MemorySpace::CUDA>(
+        communication_channel,
+        ArrayView<const Number, MemorySpace::CUDA>(
+          data.values_dev.data(), partitioner->locally_owned_size()),
+        ArrayView<Number, MemorySpace::CUDA>(import_data.values_dev.data(),
+                                             partitioner->n_import_indices()),
+        ArrayView<Number, MemorySpace::CUDA>(
+          data.values_dev.data() + partitioner->locally_owned_size(),
+          partitioner->n_ghost_indices()),
+        update_ghost_values_requests);
+    } else
+#else
+ {
       partitioner->export_to_ghosted_array_start<Number, MemorySpace::Host>(
         communication_channel,
         ArrayView<const Number, MemorySpace::Host>(
@@ -1169,17 +1192,7 @@ namespace LinearAlgebra
           data.values.data() + partitioner->locally_owned_size(),
           partitioner->n_ghost_indices()),
         update_ghost_values_requests);
-#  else
-      partitioner->export_to_ghosted_array_start<Number, MemorySpace::CUDA>(
-        communication_channel,
-        ArrayView<const Number, MemorySpace::CUDA>(
-          data.values_dev.data(), partitioner->locally_owned_size()),
-        ArrayView<Number, MemorySpace::CUDA>(import_data.values_dev.data(),
-                                             partitioner->n_import_indices()),
-        ArrayView<Number, MemorySpace::CUDA>(
-          data.values_dev.data() + partitioner->locally_owned_size(),
-          partitioner->n_ghost_indices()),
-        update_ghost_values_requests);
+ }
 #  endif
 
 #else
@@ -1204,19 +1217,24 @@ namespace LinearAlgebra
           // make this function thread safe
           std::lock_guard<std::mutex> lock(mutex);
 
-#  if !(defined(DEAL_II_COMPILER_CUDA_AWARE) && \
-        defined(DEAL_II_MPI_WITH_CUDA_SUPPORT))
+#  if defined(DEAL_II_COMPILER_CUDA_AWARE) && \
+        defined(DEAL_II_MPI_WITH_CUDA_SUPPORT)
+               if (std::is_same<MemorySpaceType, MemorySpace::CUDA>::value)
+               {
+          partitioner->export_to_ghosted_array_finish(
+            ArrayView<Number, MemorySpace::CUDA>(
+              data.values_dev.data() + partitioner->locally_owned_size(),
+              partitioner->n_ghost_indices()),
+            update_ghost_values_requests);     
+               } else
+#else
+               {
           partitioner->export_to_ghosted_array_finish(
             ArrayView<Number, MemorySpace::Host>(
               data.values.data() + partitioner->locally_owned_size(),
               partitioner->n_ghost_indices()),
             update_ghost_values_requests);
-#  else
-          partitioner->export_to_ghosted_array_finish(
-            ArrayView<Number, MemorySpace::CUDA>(
-              data.values_dev.data() + partitioner->locally_owned_size(),
-              partitioner->n_ghost_indices()),
-            update_ghost_values_requests);
+               }
 #  endif
         }
 
index 629c0063d17d3bcc8404de85e3957e88dbede61e..77321393bd4b514da0880638da412cc69610ab38 100644 (file)
@@ -28,7 +28,8 @@ namespace Impl
   ensure_kokkos_initialized()
   {
     if (!Kokkos::is_initialized())
-      GrowingVectorMemory<
+    {
+           GrowingVectorMemory<
         LinearAlgebra::distributed::Vector<double, MemorySpace::Host>>{};
     GrowingVectorMemory<
       LinearAlgebra::distributed::Vector<float, MemorySpace::Host>>{};
@@ -55,5 +56,6 @@ namespace Impl
     Kokkos::initialize();
     std::atexit(Kokkos::finalize);
   }
+  }
 } // namespace Impl
 DEAL_II_NAMESPACE_CLOSE

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.