LCOV - code coverage report
Current view: top level - test - HDF5MatrixTest.cc (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 178 178 100.0 %
Date: 2016-06-29 12:30:40 Functions: 41 41 100.0 %

          Line data    Source code
       1             : #ifdef DASH_ENABLE_HDF5
       2             : 
       3             : #include "TestBase.h"
       4             : #include "TestLogHelpers.h"
       5             : #include "HDF5MatrixTest.h"
       6             : 
       7             : #include <libdash.h>
       8             : #include <gtest/gtest.h>
       9             : #include <limits.h>
      10             : 
      11             : 
      12             : typedef int value_t;
      13             : namespace dio = dash::io::hdf5;
      14             : 
      15             : /**
      16             :  * Cantors pairing function to map n-tuple to single number
      17             :  */
      18             : template <
      19             :   typename T,
      20             :   size_t ndim >
      21        2309 : T cantorpi(std::array<T, ndim> tuple)
      22             : {
      23        2309 :   int cantor = 0;
      24        4618 :   for (int i = 0; i < ndim - 1; i++) {
      25        2309 :     T x = tuple[i];
      26        2309 :     T y = tuple[i + 1];
      27        2309 :     cantor += y + 0.5 * (x + y) * (x + y + 1);
      28             :   }
      29        2309 :   return cantor;
      30             : }
      31             : 
      32             : /**
      33             :  * Fill a n-dimensional dash matrix with a signatures that contains
      34             :  * the global coordinates and a secret which can be the unit id
      35             :  * for example
      36             :  */
      37             : template <
      38             :   typename T,
      39             :   int ndim,
      40             :   typename IndexT,
      41             :   typename PatternT >
      42          32 : void fill_matrix(dash::Matrix<T, ndim, IndexT, PatternT> & matrix,
      43             :                  T secret = 0)
      44             : {
      45             :   std::function< void(const T &, IndexT)>
      46        4563 :   f = [&matrix, &secret](T el, IndexT i) {
      47        1521 :     auto coords = matrix.pattern().coords(i);
      48             :     // hack
      49        4563 :     *(matrix.begin() + i) = cantorpi(coords) + secret;
      50        1585 :   };
      51          32 :   dash::for_each_with_index(
      52             :     matrix.begin(),
      53             :     matrix.end(),
      54             :     f);
      55          32 : }
      56             : 
      57             : /**
      58             :  * Counterpart to fill_matrix which checks if the given matrix satisfies
      59             :  * the desired signature
      60             :  */
      61             : template <
      62             :   typename T,
      63             :   int ndim,
      64             :   typename IndexT,
      65             :   typename PatternT >
      66          24 : void verify_matrix(dash::Matrix<T, ndim, IndexT, PatternT> & matrix,
      67             :                    T secret = 0)
      68             : {
      69             :   std::function< void(const T &, IndexT)>
      70        1576 :   f = [&matrix, &secret](T el, IndexT i) {
      71         788 :     auto coords  = matrix.pattern().coords(i);
      72        1576 :     auto desired = cantorpi(coords) + secret;
      73         788 :     ASSERT_EQ_U(
      74             :       desired,
      75             :       el);
      76          48 :   };
      77          24 :   dash::for_each_with_index(
      78             :     matrix.begin(),
      79             :     matrix.end(),
      80             :     f);
      81          24 : }
      82             : 
      83             : 
      84          20 : TEST_F(HDF5MatrixTest, StoreMultiDimMatrix)
      85             : {
      86             :   typedef dash::TilePattern<2>  pattern_t;
      87             :   typedef dash::Matrix<
      88             :             value_t,
      89             :             2,
      90             :             long,
      91             :             pattern_t >         matrix_t;
      92             : 
      93           4 :   auto numunits =  dash::Team::All().size();
      94           4 :   dash::TeamSpec<2> team_spec(numunits, 1);
      95           4 :   team_spec.balance_extents();
      96             : 
      97           4 :   auto team_extent_x = team_spec.extent(0);
      98           4 :   auto team_extent_y = team_spec.extent(1);
      99             : 
     100           4 :   auto extend_x = 2 * 2 * team_extent_x;
     101           4 :   auto extend_y = 2 * 5 * team_extent_y;
     102             : 
     103             :   pattern_t pattern(
     104             :     dash::SizeSpec<2>(
     105             :       extend_x,
     106             :       extend_y),
     107             :     dash::DistributionSpec<2>(
     108           8 :       dash::TILE(2),
     109           8 :       dash::TILE(5)),
     110           4 :     team_spec);
     111             : 
     112             :   DASH_LOG_DEBUG("Pattern", pattern);
     113             : 
     114           4 :   int myid = dash::myid();
     115             :   {
     116           8 :     matrix_t mat1(pattern);
     117           4 :     dash::barrier();
     118             :     LOG_MESSAGE("Matrix created");
     119             : 
     120             :     // Fill Array
     121          20 :     for (int x = 0; x < pattern.local_extent(0); x++) {
     122         176 :       for (int y = 0; y < pattern.local_extent(1); y++) {
     123         160 :         mat1.local[x][y] = myid;
     124             :       }
     125             :     }
     126           4 :     dash::barrier();
     127             :     DASH_LOG_DEBUG("BEGIN STORE HDF");
     128             : 
     129           8 :                 dio::HDF5OutputStream os(_filename);
     130           4 :     os << dio::dataset(_dataset) << mat1;
     131             : 
     132             :     DASH_LOG_DEBUG("END STORE HDF");
     133           4 :     dash::barrier();
     134             :   }
     135           4 :   dash::barrier();
     136           4 : }
     137             : 
     138          20 : TEST_F(HDF5MatrixTest, StoreSUMMAMatrix)
     139             : {
     140             :   typedef double  value_t;
     141             :   typedef long    index_t;
     142             : 
     143           4 :   auto myid         = dash::myid();
     144           4 :   auto num_units   = dash::Team::All().size();
     145           4 :   auto extent_cols = num_units;
     146           4 :   auto extent_rows = num_units;
     147           4 :   auto team_size_x = num_units;
     148           4 :   auto team_size_y = 1;
     149             : 
     150             :   // Adopted from SUMMA test case
     151             :   // Automatically deduce pattern type satisfying constraints defined by
     152             :   // SUMMA implementation:
     153           4 :   dash::SizeSpec<2> size_spec(extent_cols, extent_rows);
     154           4 :   dash::TeamSpec<2> team_spec(team_size_x, team_size_y);
     155           4 :   team_spec.balance_extents();
     156             : 
     157             :   LOG_MESSAGE("Initialize matrix pattern ...");
     158             :   auto pattern = dash::make_pattern <
     159             :                  dash::summa_pattern_partitioning_constraints,
     160             :                  dash::summa_pattern_mapping_constraints,
     161             :                  dash::summa_pattern_layout_constraints > (
     162             :                    size_spec,
     163           4 :                    team_spec);
     164             :   DASH_LOG_DEBUG("Pattern", pattern);
     165             : 
     166             :   {
     167             :     // Instantiate Matrix
     168           8 :     dash::Matrix<value_t, 2, index_t, decltype(pattern)> matrix_a(pattern);
     169           4 :     dash::barrier();
     170             : 
     171           4 :     fill_matrix(matrix_a, static_cast<double>(myid));
     172           4 :     dash::barrier();
     173             : 
     174             :     // Store Matrix
     175           8 :                 dio::HDF5OutputStream os(_filename);
     176           4 :     os << dio::dataset(_dataset) << matrix_a;
     177             : 
     178           4 :     dash::barrier();
     179             :   }
     180             : 
     181           8 :   dash::Matrix<double, 2> matrix_b;
     182             : 
     183           8 :         dio::HDF5InputStream is(_filename);
     184           4 :         is >> dio::dataset(_dataset) >> matrix_b;
     185             : 
     186           4 :   dash::barrier();
     187           4 :   verify_matrix(matrix_b, static_cast<double>(myid));
     188           4 : }
     189             : 
     190          20 : TEST_F(HDF5MatrixTest, AutoGeneratePattern)
     191             : {
     192             :   {
     193             :     auto matrix_a = dash::Matrix<int, 2>(
     194             :                       dash::SizeSpec<2>(
     195             :                         dash::size(),
     196          12 :                         dash::size()));
     197             :     // Fill
     198           4 :     fill_matrix(matrix_a);
     199           4 :     dash::barrier();
     200             : 
     201           8 :                 dio::HDF5OutputStream os(_filename);
     202           8 :                 os << dio::store_pattern(false)
     203          12 :        << dio::dataset(_dataset)
     204           4 :                          << matrix_a;
     205             : 
     206           4 :     dash::barrier();
     207             :   }
     208           8 :   dash::Matrix<int, 2> matrix_b;
     209             : 
     210           8 :         dio::HDF5InputStream is(_filename);
     211           4 :         is >> dio::dataset(_dataset) >> matrix_b;
     212             : 
     213           4 :   dash::barrier();
     214             : 
     215             :   // Verify
     216           4 :   verify_matrix(matrix_b);
     217           4 : }
     218             : 
     219             : /**
     220             :  * Import data into a already allocated matrix
     221             :  * because matrix_a and matrix_b are allocated the same way
     222             :  * it is expected that each unit remains its local ranges
     223             :  */
     224          20 : TEST_F(HDF5MatrixTest, PreAllocation)
     225             : {
     226           4 :   int ext_x = dash::size();
     227           4 :   int ext_y = ext_x * 2 + 1;
     228             :   {
     229             :     auto matrix_a = dash::Matrix<int, 2>(
     230             :                       dash::SizeSpec<2>(
     231             :                         ext_x,
     232          12 :                         ext_y));
     233             :     // Fill
     234           4 :     fill_matrix(matrix_a, dash::myid());
     235           4 :     dash::barrier();
     236             : 
     237           8 :                 dio::HDF5OutputStream os(_filename);
     238           8 :                 os << dio::store_pattern(false)
     239          12 :        << dio::dataset(_dataset)
     240           4 :                          << matrix_a;
     241             : 
     242           4 :     dash::barrier();
     243             :   }
     244             :   dash::Matrix<int, 2> matrix_b(
     245             :     dash::SizeSpec<2>(
     246             :       ext_x,
     247          12 :       ext_y));
     248             : 
     249           8 :         dio::HDF5InputStream is(_filename);
     250           4 :         is >> dio::dataset(_dataset) >> matrix_b;
     251             : 
     252           4 :   dash::barrier();
     253             : 
     254             :   // Verify
     255           4 :   verify_matrix(matrix_b, dash::myid());
     256           4 : }
     257             : 
     258             : /**
     259             :  * Allocate a matrix with extents that cannot fit into full blocks
     260             :  */
     261          20 : TEST_F(HDF5MatrixTest, UnderfilledPattern)
     262             : {
     263             :   typedef dash::Pattern<2, dash::ROW_MAJOR> pattern_t;
     264             : 
     265           4 :   size_t team_size    = dash::Team::All().size();
     266             : 
     267           4 :   dash::TeamSpec<2> teamspec_2d(team_size, 1);
     268           4 :   teamspec_2d.balance_extents();
     269             : 
     270           4 :   auto block_size_x = 10;
     271           4 :   auto block_size_y = 15;
     272           4 :   auto ext_x        = (block_size_x * teamspec_2d.num_units(0)) - 3;
     273           4 :   auto ext_y        = (block_size_y * teamspec_2d.num_units(1)) - 1;
     274             : 
     275           4 :   auto size_spec = dash::SizeSpec<2>(ext_x, ext_y);
     276             : 
     277             :   // Check TilePattern
     278             :   const pattern_t pattern(
     279             :     size_spec,
     280             :     dash::DistributionSpec<2>(
     281           8 :       dash::TILE(block_size_x),
     282           8 :       dash::TILE(block_size_y)),
     283             :     teamspec_2d,
     284           8 :     dash::Team::All());
     285             : 
     286             :   {
     287           8 :     dash::Matrix<int, 2, long, pattern_t> matrix_a;
     288           4 :     matrix_a.allocate(pattern);
     289             : 
     290           4 :     fill_matrix(matrix_a);
     291             : 
     292           8 :                 dio::HDF5OutputStream os(_filename);
     293           8 :                 os << dio::dataset(_dataset)
     294           4 :        << matrix_a;
     295             :   }
     296           4 :   dash::barrier();
     297             : 
     298           8 :   dash::Matrix<int, 2, long, pattern_t> matrix_b;
     299           8 :         dio::HDF5InputStream is(_filename);
     300           8 :         is >> dio::dataset(_dataset)
     301           4 :      >> matrix_b;
     302           4 : }
     303             : 
     304          20 : TEST_F(HDF5MatrixTest, MultipleDatasets)
     305             : {
     306           4 :         int    ext_x    = dash::size() * 5;
     307           4 :         int    ext_y    = dash::size() * 3;
     308           4 :         int    secret_a = 10;
     309           4 :         double secret_b = 3;
     310             :         {
     311          12 :     auto matrix_a = dash::Matrix<int,2>(dash::SizeSpec<2>(ext_x,ext_y));
     312          12 :                 auto matrix_b = dash::Matrix<double,2>(dash::SizeSpec<2>(ext_x,ext_y));
     313             : 
     314             :     // Fill
     315           4 :     fill_matrix(matrix_a, secret_a);
     316           4 :                 fill_matrix(matrix_b, secret_b);
     317           4 :     dash::barrier();
     318             : 
     319           8 :                 dio::HDF5OutputStream os(_filename);
     320           8 :                 os << dio::dataset(_dataset)
     321           4 :        << matrix_a
     322          12 :                          << dio::dataset("datasettwo")
     323           4 :        << matrix_b;
     324           4 :     dash::barrier();
     325             :   }
     326           8 :   dash::Matrix<int,2>    matrix_c;
     327           8 :         dash::Matrix<double,2> matrix_d;
     328             : 
     329           8 :         dio::HDF5InputStream is(_filename);
     330           8 :         is >> dio::dataset(_dataset)
     331           4 :      >> matrix_c
     332          12 :                  >> dio::dataset("datasettwo")
     333           4 :                  >> matrix_d;
     334             : 
     335           4 :   dash::barrier();
     336             : 
     337             :   // Verify data
     338           4 :   verify_matrix(matrix_c, secret_a);
     339           4 :         verify_matrix(matrix_d, secret_b);
     340           4 : }
     341             : 
     342          20 : TEST_F(HDF5MatrixTest, ModifyDataset)
     343             : {
     344           4 :         int    ext_x    = dash::size() * 5;
     345           4 :         int    ext_y    = dash::size() * 3;
     346           4 :         double secret_a = 10;
     347           4 :         double secret_b = 3;
     348             :         {
     349          12 :     auto matrix_a = dash::Matrix<double,2>(dash::SizeSpec<2>(ext_x,ext_y));
     350          12 :                 auto matrix_b = dash::Matrix<double,2>(dash::SizeSpec<2>(ext_x,ext_y));
     351             : 
     352             :     // Fill
     353           4 :     fill_matrix(matrix_a, secret_a);
     354           4 :                 fill_matrix(matrix_b, secret_b);
     355           4 :     dash::barrier();
     356             : 
     357             :                 {
     358           8 :                         dio::HDF5OutputStream os(_filename);
     359           8 :                         os << dio::dataset(_dataset)
     360           4 :          << matrix_a;
     361             :                 }
     362             : 
     363           4 :                 dash::barrier();
     364             :                 // overwrite first data
     365           8 :                 dio::HDF5OutputStream os(_filename, dio::HDF5FileOptions::Append);
     366           8 :                 os << dio::dataset(_dataset)
     367          12 :        << dio::modify_dataset()
     368           4 :        << matrix_b;
     369           4 :     dash::barrier();
     370             :   }
     371           8 :   dash::Matrix<double,2>    matrix_c;
     372             : 
     373           8 :         dio::HDF5InputStream is(_filename);
     374           8 :         is >> dio::dataset(_dataset)
     375           4 :      >> matrix_c;
     376             : 
     377           4 :   dash::barrier();
     378             : 
     379             :   // Verify data
     380           4 :   verify_matrix(matrix_c, secret_b);
     381          16 : }
     382             : 
     383             : #if 0
     384             : // Test Conversion between dash::Array and dash::Matrix
     385             : // Currently not possible as matrix has to be at least
     386             : // two dimensional
     387             : TEST_F(HDF5MatrixTest, ArrayToMatrix)
     388             : {
     389             :   {
     390             :     auto array = dash::Array<int>(100, dash::CYCLIC);
     391             :     if (dash::myid() == 0) {
     392             :       for (int i = 0; i < array.size(); i++) {
     393             :         array[i] = i;
     394             :       }
     395             :     }
     396             : 
     397             :     // Do not store pattern
     398             :     auto fopts = dio::StoreHDF::get_default_options();
     399             :     fopts.store_pattern = false;
     400             : 
     401             :     dio::StoreHDF::write(array, _filename, _dataset);
     402             :     dash::barrier();
     403             :   }
     404             :   dash::Matrix<int, 1> matrix;
     405             :   dio::StoreHDF::read(matrix, _filename, _dataset);
     406             :   dash::barrier();
     407             : 
     408             :   // Verify
     409             :   if (dash::myid() == 0) {
     410             :     for (int i = 0; i < matrix.extent(0); i++) {
     411             :       ASSERT_EQ(i, matrix[i]);
     412             :     }
     413             :   }
     414             : }
     415             : #endif
     416             : 
     417             : #endif // DASH_ENABLE_HDF5

Generated by: LCOV version 1.12