Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_KokkosArrayKernelsUnitTestNew.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Stokhos Package
4 //
5 // Copyright 2009 NTESS and the Stokhos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 // Utilities
14 
15 #include "Stokhos_ConfigDefs.h"
16 
17 #include "Kokkos_Core.hpp"
18 
19 // Threads kernels
20 #ifdef KOKKOS_ENABLE_THREADS
22 #endif
23 
24 // OpenMP kernels
25 #if defined(KOKKOS_ENABLE_OPENMP) && defined(HAVE_STOKHOS_MKL)
27 #endif
28 
29 // Tests
30 #include "Stokhos_KokkosArrayKernelsUnitTestNew.hpp"
31 
32 using namespace KokkosKernelsUnitTest;
33 
35 
36 // Test declarations
37 #include "Stokhos_KokkosArrayKernelsUnitTestNewDecl.hpp"
38 
39 // Host-specific tests
40 
41 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( Kokkos_SG_SpMv, CrsProductTensorCijk, Scalar, Device ) {
42  success = true;
43 
44  typedef Scalar value_type;
45  typedef int size_type;
47 
48  tensor_type tensor =
49  Stokhos::create_product_tensor<Device>( *setup.basis, *setup.Cijk );
50 
51  for (int i=0; i<setup.stoch_length; ++i) {
52  const int iEntryBeg = tensor.entry_begin(i);
53  const int iEntryEnd = tensor.entry_end(i);
54  for (int iEntry = iEntryBeg ; iEntry < iEntryEnd ; ++iEntry ) {
55  const int kj = tensor.coord( iEntry );
56  const int j = kj & 0x0ffff;
57  const int k = kj >> 16;
58  // const int j = tensor.coord(iEntry,0);
59  // const int k = tensor.coord(iEntry,1);
60  value_type c2 = tensor.value(iEntry);
61  if (j == k) c2 *= 2.0;
62 
63  int ii = setup.inv_perm[i];
64  int jj = setup.inv_perm[j];
65  int kk = setup.inv_perm[k];
66  value_type c = setup.Cijk->getValue(ii,jj,kk);
67 
68  if (std::abs(c-c2) > std::abs(c)*setup.rel_tol + setup.abs_tol) {
69  out << "(" << ii << "," << jj << "," << kk << "): " << c
70  << " == " << c2 << " failed!" << std::endl;
71  success = false;
72  }
73  }
74  }
75 }
76 
77 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( Kokkos_SG_SpMv, TiledCrsProductTensorCijk, Scalar, Device ) {
78  success = true;
79 
80  typedef Scalar value_type;
82 
84  params.set("Tile Size",10);
85  params.set("Max Tiles",10000);
86 
87  tensor_type tensor =
88  Stokhos::create_tiled_product_tensor<Device>( *setup.basis, *setup.Cijk,
89  params );
90 
91  // This is a valid test only with no symmetry
92  // TEUCHOS_TEST_EQUALITY( tensor.entry_count(), setup.Cijk->num_entries(),
93  // out, success );
94 
95  const size_t n_tile = tensor.num_tiles();
96  for ( size_t tile = 0 ; tile < n_tile ; ++tile ) {
97  const size_t i_offset = tensor.offset(tile, 0);
98  const size_t j_offset = tensor.offset(tile, 1);
99  const size_t k_offset = tensor.offset(tile, 2);
100  const size_t n_row = tensor.num_rows(tile);
101 
102  for (size_t i=0; i<n_row; ++i) {
103  const size_t iEntryBeg = tensor.entry_begin(tile,i);
104  const size_t iEntryEnd = tensor.entry_end(tile,i);
105  for (size_t iEntry = iEntryBeg ; iEntry < iEntryEnd ; ++iEntry ) {
106  const size_t j = tensor.coord(iEntry,0);
107  const size_t k = tensor.coord(iEntry,1);
108  value_type c2 = tensor.value(iEntry);
109  int ii = i + i_offset;
110  int jj = j + j_offset;
111  int kk = k + k_offset;
112  if (jj == kk)
113  c2 *= 2.0;
114  value_type c = setup.Cijk->getValue(ii,jj,kk);
115 
116  if (std::abs(c-c2) > std::abs(c)*setup.rel_tol + setup.abs_tol) {
117  out << "(" << ii << "," << jj << "," << kk << "): " << c
118  << " == " << c2 << " failed!" << std::endl;
119  success = false;
120  }
121  }
122  }
123  }
124 }
125 
126 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( Kokkos_SG_SpMv, SimpleTiledCrsProductTensorCijk, Scalar, Device ) {
127  success = true;
128 
129  typedef Scalar value_type;
131 
132  Teuchos::ParameterList params;
133  params.set("Tile Size",10);
134 
135  tensor_type tensor =
136  Stokhos::create_simple_tiled_product_tensor<Device>(
137  *setup.basis, *setup.Cijk, params);
138 
139  int num_entry = 0;
140  const size_t n_i_tile = tensor.num_i_tiles();
141  for (size_t i_tile = 0; i_tile<n_i_tile; ++i_tile) {
142  const size_t i_begin = tensor.i_begin(i_tile);
143  const size_t i_size = tensor.i_size(i_tile);
144 
145  const size_t n_j_tile = tensor.num_j_tiles(i_tile);
146  for (size_t j_tile = 0; j_tile<n_j_tile; ++j_tile) {
147  const size_t j_begin = tensor.j_begin(i_tile, j_tile);
148  //const size_t j_size = tensor.j_size(i_tile, j_tile);
149 
150  const size_t n_k_tile = tensor.num_k_tiles(i_tile, j_tile);
151  for (size_t k_tile = 0; k_tile<n_k_tile; ++k_tile) {
152  const size_t k_begin = tensor.k_begin(i_tile, j_tile, k_tile);
153  //const size_t k_size = tensor.k_size(i_tile, j_tile, k_tile);
154 
155  for (size_t i=0; i<i_size; ++i) {
156  const size_t iEntryBeg = tensor.entry_begin(i_tile,j_tile,k_tile,i);
157  const size_t iEntryEnd = tensor.entry_end(i_tile,j_tile,k_tile,i);
158  for (size_t iEntry = iEntryBeg ; iEntry < iEntryEnd ; ++iEntry ) {
159  const size_t j = tensor.coord(iEntry,0);
160  const size_t k = tensor.coord(iEntry,1);
161  value_type c2 = tensor.value(iEntry);
162  int ii = i + i_begin;
163  int jj = j + j_begin;
164  int kk = k + k_begin;
165  ++num_entry;
166  if (jj == kk)
167  c2 *= 2.0;
168  else
169  ++num_entry;
170  value_type c = setup.Cijk->getValue(ii,jj,kk);
171 
172  if (std::abs(c-c2) > std::abs(c)*setup.rel_tol + setup.abs_tol) {
173  out << "(" << ii << "," << jj << "," << kk << "): " << c
174  << " == " << c2 << " failed!" << std::endl;
175  success = false;
176  }
177  }
178  }
179  }
180  }
181  }
182  TEUCHOS_TEST_EQUALITY( num_entry, setup.Cijk->num_entries(), out, success );
183 }
184 
185 template <typename Scalar, typename Device, bool Pack>
187  Teuchos::FancyOStream& out) {
188  bool success = true;
189 
190  typedef Scalar value_type;
192 
193  tensor_type tensor =
194  Stokhos::create_coo_product_tensor<Device, Pack>(
195  *setup.basis, *setup.Cijk );
196 
197  const size_t nEntry = tensor.entry_count();
198  size_t i, j, k;
199  for ( size_t entry = 0 ; entry < nEntry ; ++entry ) {
200  tensor.coord(entry, i, j, k);
201  value_type c2 = tensor.value(entry);
202  if (j == k) c2 *= 2.0;
203  value_type c = setup.Cijk->getValue(i,j,k);
204 
205  if (std::abs(c-c2) > std::abs(c)*setup.rel_tol + setup.abs_tol) {
206  out << "(" << i << "," << j << "," << k << "): " << c
207  << " == " << c2 << " failed!" << std::endl;
208  success = false;
209  }
210  }
211 
212  return success;
213 }
214 
215 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( Kokkos_SG_SpMv, CooProductTensorCijk_Packed, Scalar, Device ) {
216  success = test_coo_product_tensor_cijk<Scalar,Device,true>(setup, out);
217 }
218 
219 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( Kokkos_SG_SpMv, CooProductTensorCijk_Unpacked, Scalar, Device ) {
220  success = test_coo_product_tensor_cijk<Scalar,Device,false>(setup, out);
221 }
222 
223 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( Kokkos_SG_SpMv, FlatSparseCijk, Scalar, Device ) {
224  success = true;
225 
226  typedef Scalar value_type;
228  typedef size_t size_type;
229 
230  tensor_type tensor =
231  Stokhos::create_flat_sparse_3_tensor<Device>( *setup.basis, *setup.Cijk );
232 
233  for (int i=0; i<setup.stoch_length; ++i) {
234  const size_type nk = tensor.num_k(i);
235  const size_type kBeg = tensor.k_begin(i);
236  const size_type kEnd = kBeg + nk;
237  for (size_type kEntry = kBeg; kEntry < kEnd; ++kEntry) {
238  const size_type k = tensor.k_coord(kEntry);
239  const size_type nj = tensor.num_j(kEntry);
240  const size_type jBeg = tensor.j_begin(kEntry);
241  const size_type jEnd = jBeg + nj;
242  for (size_type jEntry = jBeg; jEntry < jEnd; ++jEntry) {
243  const size_type j = tensor.j_coord(jEntry);
244  value_type c2 = tensor.value(jEntry);
245  if (j == k) c2 *= 2.0;
246  value_type c = setup.Cijk->getValue(i,j,k);
247  if (std::abs(c-c2) > std::abs(c)*setup.rel_tol + setup.abs_tol) {
248  out << "(" << i << "," << j << "," << k << "): " << c
249  << " == " << c2 << " failed!" << std::endl;
250  success = false;
251  }
252  }
253  }
254  }
255 }
256 
257 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( Kokkos_SG_SpMv, FlatSparseCijk_kji, Scalar, Device ) {
258  success = true;
259 
260  typedef Scalar value_type;
262  typedef size_t size_type;
263 
264  tensor_type tensor =
265  Stokhos::create_flat_sparse_3_tensor_kji<Device>(*setup.basis, *setup.Cijk);
266  const size_type nk = tensor.num_k();
267 
268  for ( size_type k = 0; k < nk; ++k) {
269  const size_type nj = tensor.num_j(k);
270  const size_type jBeg = tensor.j_begin(k);
271  const size_type jEnd = jBeg + nj;
272  for (size_type jEntry = jBeg; jEntry < jEnd; ++jEntry) {
273  const size_type j = tensor.j_coord(jEntry);
274  const size_type ni = tensor.num_i(jEntry);
275  const size_type iBeg = tensor.i_begin(jEntry);
276  const size_type iEnd = iBeg + ni;
277  for (size_type iEntry = iBeg; iEntry < iEnd; ++iEntry) {
278  const size_type i = tensor.i_coord(iEntry);
279  value_type c2 = tensor.value(iEntry);
280  if (j == k) c2 *= 2.0;
281  value_type c = setup.Cijk->getValue(i,j,k);
282  if (std::abs(c-c2) > std::abs(c)*setup.rel_tol + setup.abs_tol) {
283  out << "(" << i << "," << j << "," << k << "): " << c
284  << " == " << c2 << " failed!" << std::endl;
285  success = false;
286  }
287  }
288  }
289  }
290 }
291 
292 #define UNIT_TEST_GROUP_SCALAR_HOST_DEVICE( SCALAR, DEVICE ) \
293  TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( Kokkos_SG_SpMv, CrsProductTensorCijk, SCALAR, DEVICE ) \
294  TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( Kokkos_SG_SpMv, TiledCrsProductTensorCijk, SCALAR, DEVICE ) \
295  TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( Kokkos_SG_SpMv, SimpleTiledCrsProductTensorCijk, SCALAR, DEVICE ) \
296  TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( Kokkos_SG_SpMv, CooProductTensorCijk_Packed, SCALAR, DEVICE ) \
297  TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( Kokkos_SG_SpMv, CooProductTensorCijk_Unpacked, SCALAR, DEVICE ) \
298  TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( Kokkos_SG_SpMv, FlatSparseCijk, SCALAR, DEVICE ) \
299  TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( Kokkos_SG_SpMv, FlatSparseCijk_kji, SCALAR, DEVICE )
300 
301 #ifdef KOKKOS_ENABLE_THREADS
302 using Kokkos::Threads;
303 UNIT_TEST_GROUP_SCALAR_DEVICE( double, Threads )
304 UNIT_TEST_GROUP_SCALAR_HOST_DEVICE( double, Threads )
305 #endif
306 
307 #ifdef KOKKOS_ENABLE_OPENMP
308 using Kokkos::OpenMP;
309 UNIT_TEST_GROUP_SCALAR_DEVICE( double, OpenMP )
310 UNIT_TEST_GROUP_SCALAR_HOST_DEVICE( double, OpenMP )
311 
312 #ifdef HAVE_STOKHOS_MKL
313 TEUCHOS_UNIT_TEST( Kokkos_SG_SpMv, double_OpenMP_CrsMatrixFree_MKL ) {
314  typedef double Scalar;
315  typedef Kokkos::OpenMP Device;
316  typedef Stokhos::MKLMultiply SparseMatOps;
317  success = test_crs_matrix_free<Scalar,Device,SparseMatOps>(
318  setup, out);
319 }
320 #endif
321 
322 #endif
323 
324 using Kokkos::Serial;
325 UNIT_TEST_GROUP_SCALAR_DEVICE( double, Serial )
326 UNIT_TEST_GROUP_SCALAR_HOST_DEVICE( double, Serial )
327 
328 int main( int argc, char* argv[] ) {
329  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
330 
331  const size_t team_count =
332  Kokkos::hwloc::get_available_numa_count() *
333  Kokkos::hwloc::get_available_cores_per_numa();
334  const size_t threads_per_team =
335  Kokkos::hwloc::get_available_threads_per_core();
336  // const size_t team_count = 1 ;
337  // const size_t threads_per_team = 1 ;
338 
339  Kokkos::InitializationSettings init_args;
340  init_args.set_num_threads(team_count*threads_per_team);
341  init_args.set_device_id(0);
342  Kokkos::initialize( init_args );
343  Kokkos::print_configuration( std::cout );
344 
345  // Setup (has to happen after initialization)
346  setup.setup();
347 
348  // Run tests
350 
351  // Finish up
352  Kokkos::finalize();
353 
354  return ret;
355 }
bool test_coo_product_tensor_cijk(const KokkosKernelsUnitTest::UnitTestSetup< Device > &setup, Teuchos::FancyOStream &out)
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Sparse product tensor with replicated entries to provide subsets with a given coordinate.
#define UNIT_TEST_GROUP_SCALAR_HOST_DEVICE(SCALAR, DEVICE)
Sparse product tensor with replicated entries to provide subsets with a given coordinate.
static int runUnitTestsFromMain(int argc, char *argv[])
TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL(Kokkos_SG_SpMv, CrsProductTensorCijk, Scalar, Device)
KOKKOS_INLINE_FUNCTION size_type num_k() const
Number of k entries.
KOKKOS_INLINE_FUNCTION size_type entry_begin(size_type i) const
Begin entries with a coordinate &#39;i&#39;.
KOKKOS_INLINE_FUNCTION PCE< Storage > abs(const PCE< Storage > &a)
KOKKOS_INLINE_FUNCTION size_type num_k(size_type i) const
Number of k entries with a coordinate &#39;i&#39;.
int main(int argc, char **argv)
#define TEUCHOS_TEST_EQUALITY(v1, v2, out, success)
#define UNIT_TEST_GROUP_SCALAR_DEVICE(SCALAR, DEVICE)
TEUCHOS_UNIT_TEST(tAdaptivityManager, test_interface)
Sparse product tensor with replicated entries to provide subsets with a given coordinate.
Sparse product tensor using &#39;COO&#39;-like storage format.