Skip to content

Commit 9d55398

Browse files
committed
Adding DualView examples for constexpr (17) and the copy constructor. WIP on the view with two meshes
1 parent 3c7394d commit 9d55398

5 files changed

Lines changed: 333 additions & 88 deletions

File tree

CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
project(mesh_prototype)
3+
4+
set(CMAKE_CXX_STANDARD 17)
5+
set(CMAKE_CXX_EXTENSIONS OFF)
6+
7+
find_package(MPI REQUIRED)
8+
find_package(Kokkos REQUIRED)
9+
find_package(CUDA REQUIRED)
10+
11+
add_executable(mesh_DV_constexpr mesh_DV_constexpr.cc)
12+
target_link_libraries(mesh_DV_constexpr PUBLIC Kokkos::kokkoscore)
13+
14+
add_executable(mesh_DV_layer mesh_DV_layer.cc)
15+
target_link_libraries(mesh_DV_layer PUBLIC Kokkos::kokkoscore)

base_class_example.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
template<typename Data, typename ExecutionSpace = Kokkos::DefaultExecutionSpace>
2+
struct CSR;
3+
4+
5+
//
6+
// Note, this API is consistent with amanzi/ecoon/mesh_refactor src/mesh/MeshCache.hh API.
7+
//
8+
// If it helped, these could be dual views?
9+
//
10+
template<typename ExecutionSpace = Kokkos::DefaultExecutionSpace>
11+
struct MeshCache {
12+
13+
using Double_View = Kokkos::View<double*, ExecutionSpace>; // ?????
14+
using cDouble_View = Kokkos::View<const double*, ExecutionSpace>; // ?????
15+
using Entity_ID_View = Kokkos::View<Entity_ID*, ExecutionSpace>;
16+
using cEntity_ID_View = Kokkos::View<const Entity_ID*, ExecutionSpace>;
17+
18+
MeshCache(Teuchos::RCP<MeshFramework>& mf); // note, feel free to make shared_ptr or raw ptr for now...
19+
20+
double getCellVolume(const Entity_ID c) const;
21+
Double_View cell_volumes; // note, this is public and can be used inside kernels directly
22+
// is there a const problem with exposing this directly? Specifically,
23+
// assume you have a const MeshCache. Can you still change
24+
// mc.cell_volumes(3) = 1? Should this be cDoubleView?
25+
26+
std::size_t getCellNumFaces(const Entity_ID c) const;
27+
cEntity_ID_View getCellFaces(const Entity_ID c) const;
28+
Entity_ID getCellFace(Entity_ID c, std::size_t i) const;
29+
CRS<Entity_ID, ExecutionSpace> cell_faces;
30+
}

mesh_kokkos.cc renamed to mesh_DV_constexpr.cc

Lines changed: 79 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,59 @@
11
#include "Kokkos_Core.hpp"
22
#include "Kokkos_DualView.hpp"
33

4+
using Entity_ID = int;
5+
6+
enum memory {host, device};
7+
8+
49
//
510
// Note, this API is consistent with amanzi/ecoon/mesh_refactor src/mesh/MeshFramework.hh API
611
//
712
struct MeshFramework {
813
MeshFramework(const int size): mesh_size_(size) {}
914

1015
// In MeshFramework this function "compute" the result on Host
11-
int getCellVolume(const int i) const {
16+
double getCellVolume(const Entity_ID i) const {
1217
return i;
1318
}
1419

1520
// In MeshFramework this function "compute" the result on Host
16-
void getCellFaces(const int id, Kokkos::View<const int*,Kokkos::HostSpace>& ret) const {
21+
Kokkos::View<const Entity_ID*,Kokkos::HostSpace> getCellFaces(const Entity_ID id) const {
1722
// 2 Elements per entries
18-
Kokkos::View<int*, Kokkos::HostSpace> tmp("",2);
23+
Kokkos::View<Entity_ID*, Kokkos::HostSpace> tmp("",2);
1924
for(int i = 0 ; i < 2; ++i){
2025
tmp(i) = value*i;
2126
}
22-
ret = tmp;
27+
return tmp;
2328
}
2429

25-
int meshSize() const { return mesh_size_; }
30+
Entity_ID getCellFace(Entity_ID c, std::size_t i) const {
31+
return value*i;
32+
}
33+
34+
Entity_ID meshSize() const { return mesh_size_; }
2635

2736
private:
28-
const int value = 10;
37+
const Entity_ID value = 10;
2938
int mesh_size_;
3039
};
3140

32-
33-
// NOTE: need this...
34-
template<typename Data, typename ExecutionSpace = Kokkos::DefaultExecutionSpace>
35-
struct CSR;
36-
37-
38-
using Entity_ID = int;
39-
40-
//
41-
// Note, this API is consistent with amanzi/ecoon/mesh_refactor src/mesh/MeshCache.hh API.
42-
//
43-
// If it helped, these could be dual views?
44-
//
41+
// MeshCache templated on the memory type
42+
// Defaulted to the device memory space
4543
template<typename ExecutionSpace = Kokkos::DefaultExecutionSpace>
4644
struct MeshCache {
45+
4746
using Double_View = Kokkos::View<double*, ExecutionSpace>; // ?????
4847
using cDouble_View = Kokkos::View<const double*, ExecutionSpace>; // ?????
4948
using Entity_ID_View = Kokkos::View<Entity_ID*, ExecutionSpace>;
5049
using cEntity_ID_View = Kokkos::View<const Entity_ID*, ExecutionSpace>;
5150

52-
MeshCache(Teuchos::RCP<MeshFramework>& mf); // note, feel free to make shared_ptr or raw ptr for now...
53-
54-
double getCellVolume(const Entity_ID c) const;
55-
Double_View cell_volumes; // note, this is public and can be used inside kernels directly
56-
// is there a const problem with exposing this directly? Specifically,
57-
// assume you have a const MeshCache. Can you still change
58-
// mc.cell_volumes(3) = 1? Should this be cDoubleView?
59-
60-
std::size_t getCellNumFaces(const Entity_ID c) const;
61-
cEntity_ID_View getCellFaces(const Entity_ID c) const;
62-
Entity_ID getCellFace(Entity_ID c, std::size_t i) const;
63-
CRS<Entity_ID, ExecutionSpace> cell_faces;
64-
}
65-
66-
67-
68-
69-
// MeshCache templated on the memory type
70-
// Defaulted to the device memory space
71-
template<typename ExecutionSpace = Kokkos::DefaultExecutionSpace>
72-
struct MeshCache {
7351

7452
// Type to get CRS on DualViews
75-
template<typename T, typename ExecutionSpace>
53+
template<typename T, typename ES>
7654
struct DualCrs{
77-
Kokkos::DualView<int*, ExecutionSpace> row_map;
78-
Kokkos::DualView<T, ExecutionSpace> entries;
55+
Kokkos::DualView<int*, ES> row_map;
56+
Kokkos::DualView<T, ES> entries;
7957
};
8058

8159
// Building a Mesh Cache on ExecutionSpace memory space.
@@ -91,7 +69,7 @@ struct MeshCache {
9169
for(int i = 0 ; i < mesh_size_ ; ++i){
9270
value_2d_.row_map.view_host()(i) = i*2;
9371
Kokkos::View<const int*, Kokkos::HostSpace> tmp;
94-
mf->getCellFaces(i,tmp);
72+
tmp = mf->getCellFaces(i);
9573
for(int j = 0 ; j < 2; ++j){
9674
value_2d_.entries.view_host()(i*2+j) = tmp(j);
9775
}
@@ -104,51 +82,50 @@ struct MeshCache {
10482
}
10583

10684
// This function can just be overloaded with the Kokkos::View type.
107-
KOKKOS_INLINE_FUNCTION void getCellFaces(int id, Kokkos::View<const int*,ExecutionSpace>& ret) const {
108-
ret = Kokkos::subview(value_2d_.entries.view_device(),
85+
template<memory MEM = device>
86+
KOKKOS_INLINE_FUNCTION auto getCellFaces(Entity_ID id) const {
87+
if constexpr (MEM == device){
88+
Kokkos::View<const int*,ExecutionSpace> ret = Kokkos::subview(value_2d_.entries.view_device(),
10989
Kokkos::make_pair(value_2d_.row_map.view_device()(id),
11090
value_2d_.row_map.view_device()(id + 1)));
111-
}
112-
void getCellFaces(int id, Kokkos::View<const int*,Kokkos::HostSpace>& ret) const {
113-
Kokkos::subview(value_2d_.entries.view_host(),
91+
return ret;
92+
} else if (MEM == host) {
93+
Kokkos::View<const Entity_ID*,Kokkos::HostSpace> ret = Kokkos::subview(value_2d_.entries.view_host(),
11494
Kokkos::make_pair(value_2d_.row_map.view_host()(id),
11595
value_2d_.row_map.view_host()(id + 1)));
96+
return ret;
97+
}
11698
}
11799

118-
// The following function cannot be overloaded with parameters
119-
// Default: only use Device function
120-
KOKKOS_INLINE_FUNCTION int getCellVolume(int i) const {
121-
return value_1d_.view_device()(i);
122-
}
123-
124-
// Duplicate function with host decoration
125-
int getCellVolume_host(int i) const {
126-
return value_1d_.view_host()(i);
100+
template<memory MEM = device>
101+
KOKKOS_INLINE_FUNCTION Entity_ID getCellFace(Entity_ID c, int i) const {
102+
if constexpr (MEM == device){
103+
return value_2d_.entries.view_device()(value_2d_.row_map.view_device()(c)+i);
104+
} else if (MEM == host){
105+
return value_2d_.entries.view_host()(value_2d_.row_map.view_host()(c)+i);
106+
}
127107
}
128108

129-
// Using C++ 17 with constexpr
130-
#if V2
131-
template<typename FExecutionSpace = Kokkos::HostSpace>
132-
int getCellVolume(int i) const {
133-
if constexpr(std::is_same<Kokkos::HostSpace,FExecutionSpace>::value) {
134-
return value_1d_.view_host()(i);
135-
} else if (std::is_same<Kokkos::CudaSpace,FExecutionSpace>::value) {
109+
// The following function cannot be overloaded with parameters
110+
// Default: only use Device function
111+
template<memory MEM = device>
112+
KOKKOS_INLINE_FUNCTION double getCellVolume(Entity_ID i) const {
113+
if constexpr (MEM == device){
136114
return value_1d_.view_device()(i);
115+
} else if (MEM == host) {
116+
return value_1d_.view_host()(i);
137117
}
138118
}
139-
#endif
140119

141120
private:
142-
Kokkos::DualView<int*,ExecutionSpace> value_1d_;
143-
DualCrs<int*,ExecutionSpace> value_2d_;
121+
Kokkos::DualView<double*,ExecutionSpace> value_1d_;
122+
DualCrs<Entity_ID*,ExecutionSpace> value_2d_;
144123
MeshFramework* framework_mesh_;
145124
int mesh_size_;
146125
};
147126

148-
149-
150-
151127
void test_mesh() {
128+
152129
using DeviceSpace = Kokkos::CudaSpace;
153130
const int ncells = 10;
154131
MeshFramework m(ncells);
@@ -157,38 +134,52 @@ void test_mesh() {
157134
// ------- Mesh Framework -------
158135
// Only accessible on Host
159136
for(int i = 0 ; i < ncells ; ++i){
160-
// 1d
161-
assert(m.getCellVolume(i) == i);
162-
// 2d
137+
if(m.getCellVolume(i) != i)
138+
printf("ERROR %.1f != %d \n",m.getCellVolume(i),i);
163139
Kokkos::View<const int*, Kokkos::HostSpace> v_h;
164-
m.getCellFaces(2, v_h);
140+
v_h = m.getCellFaces(2);
141+
for(int j = 0 ; j < 2 ; ++j){
142+
if(v_h(j) != j*10)
143+
printf("ERROR %d != %d \n",v_h(j),j*10);
144+
}
165145
for(int j = 0 ; j < 2 ; ++j){
166-
assert(v_h(j) == j*10);
146+
if(m.getCellFace(2,j) != j*10)
147+
printf("ERROR %d != %d \n",m.getCellFace(2,j),j*10);
167148
}
168149
}
169150

151+
170152
// ------- Mesh Cache -------
171153
// 1. Device Access (Default type of the mesh cache)
172154
Kokkos::parallel_for(
173-
"",
174-
ncells,
175-
KOKKOS_LAMBDA(const int i){
176-
// 1d
177-
assert(mc.getCellVolume(i) == i);
178-
// 2d
155+
ncells, KOKKOS_LAMBDA(const int i){
156+
if(mc.getCellVolume(i) != i)
157+
printf("ERROR %.1f != %d \n",mc.getCellVolume(i),i);
179158
Kokkos::View<const int*, DeviceSpace> v_d;
180-
mc.getCellFaces(2,v_d);
159+
v_d = mc.getCellFaces(2);
181160
for(int j = 0 ; j < 2 ; ++j){
182-
assert(v_d(j) == j*10);
161+
if(v_d(j) != j*10)
162+
printf("ERROR %d != %d \n",v_d(j),j*10);
163+
}
164+
for(int j = 0 ; j < 2 ; ++j){
165+
if(mc.getCellFace(2,j) != j*10)
166+
printf("ERROR %d != %d \n",mc.getCellFace(2,j),j*10);
183167
}
184168
});
185169
// 2. Host Access
186170
for(int i = 0 ; i < ncells ; ++i){
187-
// 1d
188-
assert(mc.getCellVolume_host(i) == i);
189-
// 2d
171+
if(mc.getCellVolume<memory::host>(i) != i)
172+
printf("ERROR %.1f != %d \n",mc.getCellVolume<memory::host>(i),i);
190173
Kokkos::View<const int*, Kokkos::HostSpace> v_h;
191-
mc.getCellFaces(2, v_h);
174+
v_h = mc.getCellFaces<memory::host>(2);
175+
for(int j = 0 ; j < 2 ; ++j){
176+
if(v_h(j) != j*10)
177+
printf("ERROR %d != %d \n",v_h(j),j*10);
178+
}
179+
for(int j = 0 ; j < 2 ; ++j){
180+
if(mc.getCellFace<memory::host>(2,j) != j*10)
181+
printf("ERROR %d != %d \n",mc.getCellFace<memory::host>(2,j),j*10);
182+
}
192183
}
193184
} // test_mesh
194185

0 commit comments

Comments
 (0)