From e5824d5efd4b370dce7568541b5b0ff46b866b9f Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 13 May 2020 14:28:23 +0000 Subject: [PATCH 01/58] Start working on batchgather --- src/tests/functionspace/CMakeLists.txt | 6 ++ src/tests/functionspace/test_batchgather.cc | 97 +++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/tests/functionspace/test_batchgather.cc diff --git a/src/tests/functionspace/CMakeLists.txt b/src/tests/functionspace/CMakeLists.txt index 9f3730375..9e14afbe1 100644 --- a/src/tests/functionspace/CMakeLists.txt +++ b/src/tests/functionspace/CMakeLists.txt @@ -23,6 +23,12 @@ if( HAVE_FCTEST ) endif() +ecbuild_add_test( TARGET test_batchgather + SOURCES test_batchgather.cc + LIBS atlas + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} +) + ecbuild_add_test( TARGET atlas_test_functionspace SOURCES test_functionspace.cc LIBS atlas diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc new file mode 100644 index 000000000..7fc78fc25 --- /dev/null +++ b/src/tests/functionspace/test_batchgather.cc @@ -0,0 +1,97 @@ +/* + * (C) Copyright 2013 ECMWF. + * + * This software is licensed under the terms of the Apache Licence Version 2.0 + * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. + * In applying this licence, ECMWF does not waive the privileges and immunities + * granted to it by virtue of its status as an intergovernmental organisation + * nor does it submit to any jurisdiction. + */ + +#include "eckit/log/Bytes.h" +#include "eckit/types/Types.h" + +#include "atlas/array/ArrayView.h" +#include "atlas/array/MakeView.h" +#include "atlas/field/Field.h" +#include "atlas/functionspace/StructuredColumns.h" +#include "atlas/grid/Partitioner.h" +#include "atlas/grid/StructuredGrid.h" +#include "atlas/meshgenerator.h" +#include "atlas/output/Gmsh.h" +#include "atlas/parallel/mpi/mpi.h" +#include "atlas/util/CoordinateEnums.h" +#include "atlas/util/MicroDeg.h" + +#include "tests/AtlasTestEnvironment.h" + +using namespace eckit; +using namespace atlas::functionspace; +using namespace atlas::util; + +namespace atlas { +namespace test { + +//----------------------------------------------------------------------------- + +CASE( "test_functionspace_StructuredColumns_batchgather" ) { + size_t root = 0; + std::string gridname = eckit::Resource ("--grid", "O8"); + int nfields = eckit::Resource ("--fields", 3); + int irank = mpi::comm ().rank (); + int nproc = mpi::comm ().size (); + + std::cout << " nfields = " << nfields << std::endl; + Grid grid (gridname); + + + Distribution dist (grid, grid::Partitioner ("equal_regions")); + functionspace::StructuredColumns fs (grid, dist, util::Config ("halo", 1) + | util::Config ("periodic_points", true)); + + std::vector partition (grid.size ()); + + for (int i = 0; i < grid.size (); i++) + partition[i] = dist.partition (i); + + FieldSet sloc; + FieldSet sglo; + + for (int i = 0; i < nfields; i++) + { + std::string name = std::string ("#") + std::to_string (i); + Field floc = fs.createField (option::name (name) | option::name ("owner", (i % nproc))); + auto v = array::make_view (floc); + for (int j = 0; j < fs.sizeOwned (); j++) + v[j] = irank + static_cast (j) / 1000.0; + sloc.add (floc); + Field fglo = Field (name, atlas::array::DataType::kind (), atlas::array::make_shape (grid.size ())); + sglo.add (fglo); + } + + fs.gather (sloc, sglo); + + for (int i = 0; i < nfields; i++) + { + const auto & fglo = sglo[i]; + const auto v = array::make_view (fglo); + int owner = -1; + EXPECT (f.metadata ().get ("owner", owner)); + if (owner == irank) + { + for (int j = 0; j < grid.size (); j++) + + } + } + +} + + +//----------------------------------------------------------------------------- + +} // namespace test +} // namespace atlas + +int main( int argc, char** argv ) { + return atlas::test::run( argc, argv ); +} From 8906c083bc4eae15c1aa0fc77660f16b657513e8 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 15 May 2020 14:07:26 +0000 Subject: [PATCH 02/58] First working test_batchgather.cc --- src/tests/functionspace/test_batchgather.cc | 84 ++++++++++++--------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index 7fc78fc25..62c91811b 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -8,21 +8,11 @@ * nor does it submit to any jurisdiction. */ -#include "eckit/log/Bytes.h" -#include "eckit/types/Types.h" - -#include "atlas/array/ArrayView.h" -#include "atlas/array/MakeView.h" -#include "atlas/field/Field.h" -#include "atlas/functionspace/StructuredColumns.h" -#include "atlas/grid/Partitioner.h" -#include "atlas/grid/StructuredGrid.h" -#include "atlas/meshgenerator.h" -#include "atlas/output/Gmsh.h" +#include "atlas/array.h" +#include "atlas/field.h" +#include "atlas/grid.h" +#include "atlas/functionspace.h" #include "atlas/parallel/mpi/mpi.h" -#include "atlas/util/CoordinateEnums.h" -#include "atlas/util/MicroDeg.h" - #include "tests/AtlasTestEnvironment.h" using namespace eckit; @@ -35,37 +25,55 @@ namespace test { //----------------------------------------------------------------------------- CASE( "test_functionspace_StructuredColumns_batchgather" ) { - size_t root = 0; - std::string gridname = eckit::Resource ("--grid", "O8"); int nfields = eckit::Resource ("--fields", 3); - int irank = mpi::comm ().rank (); - int nproc = mpi::comm ().size (); - - std::cout << " nfields = " << nfields << std::endl; - Grid grid (gridname); + atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); + auto & comm = mpi::comm (); + int irank = comm.rank (); + int nproc = comm.size (); - Distribution dist (grid, grid::Partitioner ("equal_regions")); - functionspace::StructuredColumns fs (grid, dist, util::Config ("halo", 1) - | util::Config ("periodic_points", true)); + atlas::grid::Distribution dist (grid, atlas::grid::Partitioner ("equal_regions")); + atlas::functionspace::StructuredColumns fs (grid, dist, atlas::util::Config ("halo", 1) + | atlas::util::Config ("periodic_points", true)); - std::vector partition (grid.size ()); + std::vector prc (grid.size ()); + std::vector ind (grid.size ()); for (int i = 0; i < grid.size (); i++) - partition[i] = dist.partition (i); - - FieldSet sloc; - FieldSet sglo; + prc[i] = dist.partition (i); + + { + atlas::Field indloc = fs.createField (atlas::util::Config ("name", "ind") | atlas::util::Config ("owner", 0)); + atlas::Field indglo ("ind", &ind[0], {grid.size ()}); + auto v = array::make_view (indloc); + for (int i = 0; i < fs.sizeOwned (); i++) + v (i) = i; + fs.gather (indloc, indglo); + comm.broadcast (ind, 0); + } + + + atlas::FieldSet sloc; + atlas::FieldSet sglo; + + auto func = [] (int fld, int prc, int ind) + { + double v = 1000.0 * static_cast (fld) + prc + static_cast (ind) / 1000.0; + return v; + }; for (int i = 0; i < nfields; i++) { + int owner = i % nproc; std::string name = std::string ("#") + std::to_string (i); - Field floc = fs.createField (option::name (name) | option::name ("owner", (i % nproc))); + atlas::Field floc = fs.createField (atlas::util::Config ("name", name) + | atlas::util::Config ("owner", owner)); auto v = array::make_view (floc); for (int j = 0; j < fs.sizeOwned (); j++) - v[j] = irank + static_cast (j) / 1000.0; + v[j] = func (i, irank, j); sloc.add (floc); - Field fglo = Field (name, atlas::array::DataType::kind (), atlas::array::make_shape (grid.size ())); + Field fglo = Field (name, atlas::array::DataType::kind (), {grid.size ()}); + fglo.metadata ().set ("owner", owner); sglo.add (fglo); } @@ -74,16 +82,20 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { for (int i = 0; i < nfields; i++) { const auto & fglo = sglo[i]; - const auto v = array::make_view (fglo); - int owner = -1; - EXPECT (f.metadata ().get ("owner", owner)); + int owner; + EXPECT (fglo.metadata ().get ("owner", owner)); if (owner == irank) { + const auto v = array::make_view (fglo); for (int j = 0; j < grid.size (); j++) - + { + double v1 = v[j], v2 = func (i, prc[j], ind[j]); + EXPECT_EQ (v1, v2); + } } } + } From 42ad7225e5691edaf6969187deaf0ef0e9ff488e Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Sat, 16 May 2020 10:21:48 +0000 Subject: [PATCH 03/58] Save --- src/tests/functionspace/test_batchgather.cc | 292 ++++++++++++++++++-- 1 file changed, 269 insertions(+), 23 deletions(-) diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index 62c91811b..5ffb37515 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -22,6 +22,240 @@ using namespace atlas::util; namespace atlas { namespace test { +namespace +{ + + +typedef char byte; + +void getprcind (const atlas::functionspace::StructuredColumns & fs, const atlas::grid::Distribution & dist, + std::vector & prc, std::vector & ind) +{ + auto & comm = mpi::comm (); + auto & grid = fs.grid (); + prc.resize (grid.size ()); + ind.resize (grid.size ()); + + for (int i = 0; i < grid.size (); i++) + prc[i] = dist.partition (i); + + { + atlas::Field indloc = fs.createField (atlas::util::Config ("name", "ind") + | atlas::util::Config ("owner", 0)); + atlas::Field indglo ("ind", &ind[0], {grid.size ()}); + auto v = array::make_view (indloc); + for (int i = 0; i < fs.sizeOwned (); i++) + v (i) = i; + fs.gather (indloc, indglo); + comm.broadcast (ind, 0); + } +} + +template +T reorder (const T & vec, const I & ord) +{ + T v (ord.size ()); + for (typename I::value_type i = 0; i < ord.size (); i++) + v[i] = vec[ord[i]]; + return v; +} + +template +void integrate (T & v) +{ + v[0].off = 0; + for (size_t i = 1; i < v.size (); i++) + v[i].off = v[i-1].off + v[i-1].len; +} + +void pack (const atlas::Field & f, size_t lsize, byte * buf) +{ + size_t dsize = f.datatype ().size (); + + switch (f.rank ()) + { + case 1: + case 2: + case 3: + } + + + +} + +void gather (const atlas::StructuredGrid & grid, const atlas::grid::Distribution & dist, + const atlas::FieldSet & sloc, atlas::FieldSet & sglo) +{ + ATLAS_ASSERT (sloc.size () == sglo.size ()); + size_t nfld = sloc.size (); + + auto & comm = mpi::comm (); + int nprc = comm.size (); + int lprc = comm.rank (); + + std::vector count (nprc); + std::vector ind (grid.size ()); + + for (int i = 0; i < grid.size (); i++) + ind[i] = count[dist.partition (i)]++; + + int max = *std::max_element (count.begin (), count.end ()); + + class locprc_t + { + public: + locprc_t () = default; + locprc_t (const std::initializer_list & l) + { + auto it = l.begin (); + loc = *it++; + prc = *it++; + } + int loc = std::numeric_limits::min (); + int prc = std::numeric_limits::min (); + }; + + class locprc2glo_t + { + public: + locprc2glo_t (int _max, int _nprc) : max (_max), nprc (_nprc) + { + data.resize (max * nprc, std::numeric_limits::min ()); + } + int & operator () (int iprc, int jloc) + { + return data[iprc * max + jloc]; + } + + class slice_t + { + public: + slice_t (int _iprc, locprc2glo_t * _locprc2glo) + : iprc (_iprc), locprc2glo (_locprc2glo) + { + } + int & operator [] (int jloc) + { + return (*locprc2glo) (iprc, jloc); + } + private: + locprc2glo_t * locprc2glo; + int iprc; + }; + + slice_t operator[] (int iprc) + { + return slice_t (iprc, this); + } + private: + int max, nprc; + std::vector data; + }; + + class glo2locprc_t : public std::vector + { + public: + glo2locprc_t () = default; + glo2locprc_t (size_t size) : std::vector (size) + { + } + }; + + class offlen_t + { + public: + size_t off = 0, len = 0; + }; + + class sizmul_t + { + public: + size_t siz = 0, mul = 1; + }; + + locprc2glo_t locprc2glo (max, nprc); + glo2locprc_t glo2locprc (grid.size ()); + + for (int i = 0; i < grid.size (); i++) + { + locprc2glo[dist.partition (i)][ind[i]] = i; + glo2locprc[i] = {ind[i], dist.partition (i)}; + } + + // Sort fields by owner + + std::vector floc (nfld); + std::vector fglo (nfld); + std::vector isort (nfld), owner (nfld); + + for (int jfld = 0; jfld < nfld; jfld++) + { + floc[jfld] = sloc[jfld]; + fglo[jfld] = sglo[jfld]; + fglo[jfld].metadata ().get ("owner", owner[jfld]); + } + + std::iota (std::begin (isort), std::end (isort), 0); + std::sort (std::begin (isort), std::end (isort), [&owner] (int a, int b) { return owner[a] < owner[b]; }); + + owner = reorder (owner, isort); + floc = reorder (floc, isort); + fglo = reorder (fglo, isort); + + // Collect field datatype size & number + + std::vector fld_info (nfld); + + for (int jfld = 0; jfld < nfld; jfld++) + { + auto & f = floc[jfld]; + const auto & ss = f.shape (); + for (int i = 1; i < ss.size (); i++) + fld_info[jfld].mul *= ss[i]; + fld_info[jfld].siz = f.datatype ().size (); + } + + // SEND + + std::vector fld_send (nfld + 1); + std::vector prc_send (nprc + 1); + + for (int jfld = 0; jfld < nfld; jfld++) + { + // datatype size x leading dimension x product of other dimension + fld_send[jfld].len = fld_info[jfld].siz * fld_info[jfld].mul; + prc_send[owner[jfld]].len += fld_send[jfld].len; + } + + integrate (fld_send); + integrate (prc_send); + + // Pack send buffer + + std::vector buf_send (fld_send.back ().off * dist.nb_pts ()[lprc]); + + for (int jfld = 0; jfld < nfld; jfld++) + pack (floc[jfld], dist.nb_pts ()[lprc], &buf_send[fld_send[jfld].off]); + + // RECV + + std::vector fld_recv (nfld + 1); + + for (int jfld = 0; jfld < nfld; jfld++) + if (lprc == owner[jfld]) + fld_recv[jfld].len = fld_info[jfld].siz * fld_info[jfld].mul; + + integrate (fld_recv); + + + + + +} + + +}; + //----------------------------------------------------------------------------- CASE( "test_functionspace_StructuredColumns_batchgather" ) { @@ -36,29 +270,34 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { atlas::functionspace::StructuredColumns fs (grid, dist, atlas::util::Config ("halo", 1) | atlas::util::Config ("periodic_points", true)); - std::vector prc (grid.size ()); - std::vector ind (grid.size ()); + std::vector prc, ind; + getprcind (fs, dist, prc, ind); + + atlas::FieldSet sloc; + atlas::FieldSet sglo, sglo2; + +#ifdef UNDEF for (int i = 0; i < grid.size (); i++) - prc[i] = dist.partition (i); - - { - atlas::Field indloc = fs.createField (atlas::util::Config ("name", "ind") | atlas::util::Config ("owner", 0)); - atlas::Field indglo ("ind", &ind[0], {grid.size ()}); - auto v = array::make_view (indloc); - for (int i = 0; i < fs.sizeOwned (); i++) - v (i) = i; - fs.gather (indloc, indglo); - comm.broadcast (ind, 0); - } + printf (" %8d > %8d, %8d\n", i, prc[i], ind[i]); +#endif - atlas::FieldSet sloc; - atlas::FieldSet sglo; + using T = long; + + const int ind_bit = 21, ind_off = 0; + const int prc_bit = 21, prc_off = ind_off + ind_bit; + const int fld_bit = 21, fld_off = prc_off + prc_bit; + + ATLAS_ASSERT (fs.sizeOwned () < (1 << ind_bit)); + ATLAS_ASSERT (nproc < (1 << prc_bit)); + ATLAS_ASSERT (nfields < (1 << fld_bit)); - auto func = [] (int fld, int prc, int ind) + auto func = [&ind_off,&prc_off,&fld_off] (int fld, int prc, int ind) { - double v = 1000.0 * static_cast (fld) + prc + static_cast (ind) / 1000.0; + long v = (static_cast (fld) << fld_off) + + (static_cast (prc) << prc_off) + + (static_cast (ind) << ind_off); return v; }; @@ -66,18 +305,25 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { { int owner = i % nproc; std::string name = std::string ("#") + std::to_string (i); - atlas::Field floc = fs.createField (atlas::util::Config ("name", name) - | atlas::util::Config ("owner", owner)); - auto v = array::make_view (floc); + atlas::Field floc = fs.createField (atlas::util::Config ("name", name) + | atlas::util::Config ("owner", owner)); + auto v = array::make_view (floc); for (int j = 0; j < fs.sizeOwned (); j++) v[j] = func (i, irank, j); sloc.add (floc); - Field fglo = Field (name, atlas::array::DataType::kind (), {grid.size ()}); + + Field fglo = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); fglo.metadata ().set ("owner", owner); sglo.add (fglo); + + Field fglo2 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); + fglo2.metadata ().set ("owner", owner); + sglo2.add (fglo); + } fs.gather (sloc, sglo); +// gather (grid, dist, sloc, sglo2); for (int i = 0; i < nfields; i++) { @@ -86,10 +332,10 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { EXPECT (fglo.metadata ().get ("owner", owner)); if (owner == irank) { - const auto v = array::make_view (fglo); + const auto v = array::make_view (fglo); for (int j = 0; j < grid.size (); j++) { - double v1 = v[j], v2 = func (i, prc[j], ind[j]); + T v1 = v[j], v2 = func (i, prc[j], ind[j]); EXPECT_EQ (v1, v2); } } From b32d684349428ed153a3a11cd02c3dfd74c24187 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Sun, 17 May 2020 08:48:38 +0000 Subject: [PATCH 04/58] Drop view last dimension, create view without check --- src/atlas/array/MakeView.h | 4 +++ src/atlas/array/native/NativeArrayView.h | 12 ++++++++ src/atlas/array/native/NativeMakeView.cc | 31 +++++++++++++++++-- src/atlas/array_fwd.h | 3 ++ src/tests/functionspace/CMakeLists.txt | 6 ++++ src/tests/functionspace/testphi.cc | 39 ++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 src/tests/functionspace/testphi.cc diff --git a/src/atlas/array/MakeView.h b/src/atlas/array/MakeView.h index d2892be9f..a5c4094e9 100644 --- a/src/atlas/array/MakeView.h +++ b/src/atlas/array/MakeView.h @@ -14,6 +14,7 @@ #include "atlas/array/IndexView.h" #include "atlas/array/LocalView.h" #include "atlas/array_fwd.h" +#include "atlas/util/Config.h" namespace atlas { namespace array { @@ -25,6 +26,9 @@ extern template IndexView make_indexview( Array& extern template IndexView make_indexview( const Array& ); extern template IndexView make_indexview( const Array& ); + +extern template ArrayView make_view_nocheck( Array& ); + #define EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( TYPE, RANK ) \ extern template ArrayView make_view( Array& ); \ extern template ArrayView make_view( Array& ); \ diff --git a/src/atlas/array/native/NativeArrayView.h b/src/atlas/array/native/NativeArrayView.h index 4d531b5d0..dc5228b23 100644 --- a/src/atlas/array/native/NativeArrayView.h +++ b/src/atlas/array/native/NativeArrayView.h @@ -144,6 +144,18 @@ class ArrayView { } } + ArrayView + drop (idx_t idx) + { + constexpr int rank = RANK-1; + idx_t _shape[rank], _strides[rank]; + ArrayShape shape; + ArrayStrides strides; + std::copy (std::begin (shape_), std::begin (shape_) + rank, std::back_inserter (shape)); + std::copy (std::begin (strides_), std::begin (strides_) + rank, std::back_inserter (strides)); + return ArrayView (data_ + strides_[rank] * idx, shape, strides); + } + #ifndef DOXYGEN_SHOULD_SKIP_THIS // This constructor should not be used directly, but only through a array::make_view() function. ArrayView( value_type* data, const ArrayShape& shape, const ArrayStrides& strides ) : data_( data ) { diff --git a/src/atlas/array/native/NativeMakeView.cc b/src/atlas/array/native/NativeMakeView.cc index b4c137e7b..ef24853af 100644 --- a/src/atlas/array/native/NativeMakeView.cc +++ b/src/atlas/array/native/NativeMakeView.cc @@ -15,23 +15,32 @@ #include "atlas/array/IndexView.h" #include "atlas/library/config.h" #include "atlas/runtime/Exception.h" +#include "atlas/util/Config.h" namespace atlas { namespace array { namespace { template -inline static void check_metadata( const Array& array ) { - if ( array.rank() != Rank ) { +inline static void check_metadata( const Array& array, + const bool check_rank = true, + const bool check_type = true, + const bool check_size = true ) { + if ( check_rank && (array.rank() != Rank) ) { std::stringstream err; err << "Number of dimensions do not match: template argument " << Rank << " expected to be " << array.rank(); throw_Exception( err.str(), Here() ); } - if ( array.datatype() != array::DataType::create() ) { + if ( check_type && (array.datatype() != array::DataType::create()) ) { std::stringstream err; err << "Data Type does not match: template argument expected to be " << array.datatype().str(); throw_Exception( err.str(), Here() ); } + if ( check_size && (array.datatype().size () != array::DataType::create().size ()) ) { + std::stringstream err; + err << "Data Type size does not match: template argument size expected to be " << array.datatype().size (); + throw_Exception( err.str(), Here() ); + } } } // namespace @@ -79,6 +88,20 @@ IndexView make_indexview( const Array& array ) { return make_host_indexview( array ); } +template +ArrayView make_view( Array& array, const util::Config & config ) { + bool check_type = true; + config.get ("check_type", check_type); + check_metadata( array ); + return make_host_view( array ); +} + +template +ArrayView make_view_nocheck( Array& array ) { + check_metadata( array, true, false ); + return make_host_view( array ); +} + template ArrayView make_view( Array& array ) { check_metadata( array ); @@ -102,6 +125,8 @@ namespace atlas { namespace array { #define EXPLICIT_TEMPLATE_INSTANTIATION_TYPE_RANK( TYPE, RANK ) \ + template ArrayView make_view_nocheck( Array& ); \ + template ArrayView make_view( Array&, const util::Config & ); \ template ArrayView make_view( Array& ); \ template ArrayView make_view( Array& ); \ template ArrayView make_view( const Array& ); \ diff --git a/src/atlas/array_fwd.h b/src/atlas/array_fwd.h index 4b20e2169..a9fdd69a6 100644 --- a/src/atlas/array_fwd.h +++ b/src/atlas/array_fwd.h @@ -52,6 +52,9 @@ class IndexView; template ArrayView make_view( Array& array ); +template +ArrayView make_view_nocheck( Array& array ); + template ArrayView make_view( const Array& array ); diff --git a/src/tests/functionspace/CMakeLists.txt b/src/tests/functionspace/CMakeLists.txt index 9e14afbe1..6f2521f31 100644 --- a/src/tests/functionspace/CMakeLists.txt +++ b/src/tests/functionspace/CMakeLists.txt @@ -29,6 +29,12 @@ ecbuild_add_test( TARGET test_batchgather ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} ) +ecbuild_add_test( TARGET testphi + SOURCES testphi.cc + LIBS atlas + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} +) + ecbuild_add_test( TARGET atlas_test_functionspace SOURCES test_functionspace.cc LIBS atlas diff --git a/src/tests/functionspace/testphi.cc b/src/tests/functionspace/testphi.cc new file mode 100644 index 000000000..6f6b67deb --- /dev/null +++ b/src/tests/functionspace/testphi.cc @@ -0,0 +1,39 @@ +#include "atlas/field.h" +#include "atlas/array.h" +#include + + + +int main (int argc, char * argv[]) +{ + atlas::Field f ("f", atlas::array::DataType::kind (), {5, 7}); + +//auto w = atlas::array::make_view (f, atlas::util::Config ("check_type", false)); + auto w = atlas::array::make_view_nocheck (f); + auto v = atlas::array::make_view (f); + + for (int i = 0; i < v.shape ()[0]; i++) + for (int j = 0; j < v.shape ()[1]; j++) + v (i, j) = i * 100 + j; + + + auto v1 = v.drop (0); + + std::cout << " v1.rank () = " << v1.rank () << std::endl; + + for (int i = 0; i < v1.shape (0); i++) + printf (" %8d > %12.2f\n", i, v1 (i)); + + + auto v2 = v.drop (1); + + std::cout << " v2.rank () = " << v2.rank () << std::endl; + + for (int i = 0; i < v2.shape (0); i++) + printf (" %8d > %12.2f\n", i, v2 (i)); + + + return 0; + +} + From 6c16d78184a44f99b3208fb70ca023282660d0fe Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Mon, 18 May 2020 09:41:20 +0000 Subject: [PATCH 05/58] dropDimension is an external template --- src/atlas/array/native/NativeArrayView.h | 12 ---- src/atlas/array/native/NativeMakeView.cc | 31 +-------- src/atlas/array_fwd.h | 3 - src/tests/functionspace/testphi.cc | 89 +++++++++++++++++++++++- 4 files changed, 90 insertions(+), 45 deletions(-) diff --git a/src/atlas/array/native/NativeArrayView.h b/src/atlas/array/native/NativeArrayView.h index dc5228b23..4d531b5d0 100644 --- a/src/atlas/array/native/NativeArrayView.h +++ b/src/atlas/array/native/NativeArrayView.h @@ -144,18 +144,6 @@ class ArrayView { } } - ArrayView - drop (idx_t idx) - { - constexpr int rank = RANK-1; - idx_t _shape[rank], _strides[rank]; - ArrayShape shape; - ArrayStrides strides; - std::copy (std::begin (shape_), std::begin (shape_) + rank, std::back_inserter (shape)); - std::copy (std::begin (strides_), std::begin (strides_) + rank, std::back_inserter (strides)); - return ArrayView (data_ + strides_[rank] * idx, shape, strides); - } - #ifndef DOXYGEN_SHOULD_SKIP_THIS // This constructor should not be used directly, but only through a array::make_view() function. ArrayView( value_type* data, const ArrayShape& shape, const ArrayStrides& strides ) : data_( data ) { diff --git a/src/atlas/array/native/NativeMakeView.cc b/src/atlas/array/native/NativeMakeView.cc index ef24853af..b4c137e7b 100644 --- a/src/atlas/array/native/NativeMakeView.cc +++ b/src/atlas/array/native/NativeMakeView.cc @@ -15,32 +15,23 @@ #include "atlas/array/IndexView.h" #include "atlas/library/config.h" #include "atlas/runtime/Exception.h" -#include "atlas/util/Config.h" namespace atlas { namespace array { namespace { template -inline static void check_metadata( const Array& array, - const bool check_rank = true, - const bool check_type = true, - const bool check_size = true ) { - if ( check_rank && (array.rank() != Rank) ) { +inline static void check_metadata( const Array& array ) { + if ( array.rank() != Rank ) { std::stringstream err; err << "Number of dimensions do not match: template argument " << Rank << " expected to be " << array.rank(); throw_Exception( err.str(), Here() ); } - if ( check_type && (array.datatype() != array::DataType::create()) ) { + if ( array.datatype() != array::DataType::create() ) { std::stringstream err; err << "Data Type does not match: template argument expected to be " << array.datatype().str(); throw_Exception( err.str(), Here() ); } - if ( check_size && (array.datatype().size () != array::DataType::create().size ()) ) { - std::stringstream err; - err << "Data Type size does not match: template argument size expected to be " << array.datatype().size (); - throw_Exception( err.str(), Here() ); - } } } // namespace @@ -88,20 +79,6 @@ IndexView make_indexview( const Array& array ) { return make_host_indexview( array ); } -template -ArrayView make_view( Array& array, const util::Config & config ) { - bool check_type = true; - config.get ("check_type", check_type); - check_metadata( array ); - return make_host_view( array ); -} - -template -ArrayView make_view_nocheck( Array& array ) { - check_metadata( array, true, false ); - return make_host_view( array ); -} - template ArrayView make_view( Array& array ) { check_metadata( array ); @@ -125,8 +102,6 @@ namespace atlas { namespace array { #define EXPLICIT_TEMPLATE_INSTANTIATION_TYPE_RANK( TYPE, RANK ) \ - template ArrayView make_view_nocheck( Array& ); \ - template ArrayView make_view( Array&, const util::Config & ); \ template ArrayView make_view( Array& ); \ template ArrayView make_view( Array& ); \ template ArrayView make_view( const Array& ); \ diff --git a/src/atlas/array_fwd.h b/src/atlas/array_fwd.h index a9fdd69a6..4b20e2169 100644 --- a/src/atlas/array_fwd.h +++ b/src/atlas/array_fwd.h @@ -52,9 +52,6 @@ class IndexView; template ArrayView make_view( Array& array ); -template -ArrayView make_view_nocheck( Array& array ); - template ArrayView make_view( const Array& array ); diff --git a/src/tests/functionspace/testphi.cc b/src/tests/functionspace/testphi.cc index 6f6b67deb..169bd210d 100644 --- a/src/tests/functionspace/testphi.cc +++ b/src/tests/functionspace/testphi.cc @@ -2,6 +2,59 @@ #include "atlas/array.h" #include +template +atlas::array::ArrayView +dropDimension (const atlas::array::ArrayView & view, int dim, atlas::idx_t idx) +{ + constexpr int rank = Rank-1; + atlas::idx_t _shape[rank], _strides[rank]; + atlas::array::ArrayShape shape; + atlas::array::ArrayStrides strides; + + if (dim < 0) + dim = dim + Rank; + + for (int i = 0; i < dim; i++) + { + shape.push_back (view.shape (i)); + strides.push_back (view.stride (i)); + } + atlas::idx_t stride_dim = view.stride (dim); + for (int i = dim + 1; i < Rank; i++) + { + shape.push_back (view.shape (i)); + strides.push_back (view.stride (i)); + } + + + using nonConstValue = typename std::remove_const::type; + + Value * data = (nonConstValue *) (view.data ()); + + return atlas::array::ArrayView (data + stride_dim * idx, shape, strides); +} + +using byte = unsigned char; + +#ifdef UNDEF +template +atlas::array::ArrayView +byteView (const atlas::array::ArrayView & view) +{ + +} +#endif + + + +template +void prss (const std::string & t, const V & v) +{ + printf ("--------- %s ---------\n", t.data ()); + for (int i = 0; i < v.rank (); i++) + printf (" %8d > %8d, %8d\n", i, v.shape (i), v.stride (i)); + printf ("\n"); +} int main (int argc, char * argv[]) @@ -12,12 +65,35 @@ int main (int argc, char * argv[]) auto w = atlas::array::make_view_nocheck (f); auto v = atlas::array::make_view (f); + prss ("v", v); + for (int i = 0; i < v.shape ()[0]; i++) for (int j = 0; j < v.shape ()[1]; j++) v (i, j) = i * 100 + j; + + + printf (" &v(0,0) = 0x%llx\n", &v(0,0)); + printf (" &v(1,0) = 0x%llx\n", &v(1,0)); + printf (" &v(0,1) = 0x%llx\n", &v(0,1)); + + printf (" %8s |", ""); + for (int j = 0; j < v.shape ()[1]; j++) + printf (" %12d", j); + printf ("\n"); - auto v1 = v.drop (0); + for (int i = 0; i < v.shape ()[0]; i++) + { + printf (" %8d |", i); + for (int j = 0; j < v.shape ()[1]; j++) + printf (" %12.0f", v (i, j)); + printf ("\n"); + } + + + auto v1 = dropDimension (v, -1, 0); + + prss ("v1", v1); std::cout << " v1.rank () = " << v1.rank () << std::endl; @@ -25,13 +101,22 @@ int main (int argc, char * argv[]) printf (" %8d > %12.2f\n", i, v1 (i)); - auto v2 = v.drop (1); + auto v2 = dropDimension (v, -1, 1); std::cout << " v2.rank () = " << v2.rank () << std::endl; for (int i = 0; i < v2.shape (0); i++) printf (" %8d > %12.2f\n", i, v2 (i)); + auto v3 = dropDimension (v, 0, 2); + + std::cout << " v3.rank () = " << v3.rank () << std::endl; + + prss ("v3", v3); + + for (int i = 0; i < v3.shape (0); i++) + printf (" %8d > %12.2f\n", i, v3 (i)); + return 0; From 726e613e8c95b3dbd6f25bcb4b04adbde1c12717 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Mon, 18 May 2020 16:13:40 +0000 Subject: [PATCH 06/58] Convert a view to a list of ArrayView --- src/atlas/array/ArrayView.h | 1 + src/atlas/array/DataType.h | 26 +++++- src/atlas/array/MakeView.h | 3 +- src/atlas/array/native/NativeArray.cc | 2 + src/atlas/array/native/NativeArrayView.cc | 4 + src/atlas/array/native/NativeMakeView.cc | 1 + src/tests/functionspace/testphi.cc | 107 +++++++++++++++++++--- 7 files changed, 127 insertions(+), 17 deletions(-) diff --git a/src/atlas/array/ArrayView.h b/src/atlas/array/ArrayView.h index 51ecfecf2..f94551b15 100644 --- a/src/atlas/array/ArrayView.h +++ b/src/atlas/array/ArrayView.h @@ -26,6 +26,7 @@ namespace array { extern template class ArrayView; #define EXPLICIT_TEMPLATE_DECLARATION( RANK ) \ + EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( char, RANK ); \ EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( int, RANK ); \ EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( long, RANK ); \ EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( float, RANK ); \ diff --git a/src/atlas/array/DataType.h b/src/atlas/array/DataType.h index 5666aa7d8..efa945897 100644 --- a/src/atlas/array/DataType.h +++ b/src/atlas/array/DataType.h @@ -21,6 +21,7 @@ namespace array { class DataType { public: typedef long kind_t; + static const kind_t KIND_INT8 = -1; static const kind_t KIND_INT32 = -4; static const kind_t KIND_INT64 = -8; static const kind_t KIND_REAL32 = 4; @@ -30,6 +31,7 @@ class DataType { template static DataType create(); + static DataType int8() { return DataType( KIND_INT8 ); } static DataType int32() { return DataType( KIND_INT32 ); } static DataType int64() { return DataType( KIND_INT64 ); } static DataType real32() { return DataType( KIND_REAL32 ); } @@ -51,6 +53,7 @@ class DataType { static bool kind_valid( kind_t ); private: + static std::string int8_str() { return "int8"; } static std::string int32_str() { return "int32"; } static std::string int64_str() { return "int64"; } static std::string real32_str() { return "real32"; } @@ -79,6 +82,14 @@ class DataType { kind_t kind_; }; +template <> +inline std::string DataType::str() { + return int8_str(); +} +template <> +inline std::string DataType::str() { + return int8_str(); +} template <> inline std::string DataType::str() { return int32_str(); @@ -140,6 +151,14 @@ inline std::string DataType::str( const double& ) { return real64_str(); } template <> +inline DataType::kind_t DataType::kind() { + return KIND_INT8; +} +template <> +inline DataType::kind_t DataType::kind() { + return KIND_INT8; +} +template <> inline DataType::kind_t DataType::kind() { return KIND_INT32; } @@ -201,7 +220,9 @@ inline DataType::kind_t DataType::kind( const double& ) { } inline DataType::kind_t DataType::str_to_kind( const std::string& datatype ) { - if ( datatype == "int32" ) + if ( datatype == "int8" ) + return KIND_INT8; + else if ( datatype == "int32" ) return KIND_INT32; else if ( datatype == "int64" ) return KIND_INT64; @@ -217,6 +238,8 @@ inline DataType::kind_t DataType::str_to_kind( const std::string& datatype ) { } inline std::string DataType::kind_to_str( kind_t kind ) { switch ( kind ) { + case KIND_INT8: + return int8_str(); case KIND_INT32: return int32_str(); case KIND_INT64: @@ -233,6 +256,7 @@ inline std::string DataType::kind_to_str( kind_t kind ) { } inline bool DataType::kind_valid( kind_t kind ) { switch ( kind ) { + case KIND_INT8: case KIND_INT32: case KIND_INT64: case KIND_UINT64: diff --git a/src/atlas/array/MakeView.h b/src/atlas/array/MakeView.h index a5c4094e9..7fc3ff1ee 100644 --- a/src/atlas/array/MakeView.h +++ b/src/atlas/array/MakeView.h @@ -27,8 +27,6 @@ extern template IndexView make_indexview( const Array& extern template IndexView make_indexview( const Array& ); -extern template ArrayView make_view_nocheck( Array& ); - #define EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( TYPE, RANK ) \ extern template ArrayView make_view( Array& ); \ extern template ArrayView make_view( Array& ); \ @@ -50,6 +48,7 @@ extern template ArrayView make_view_nocheck( Array& ); #define EXPLICIT_TEMPLATE_DECLARATION( RANK ) \ + EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( char, RANK ) \ EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( int, RANK ) \ EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( long, RANK ) \ EXPLICIT_TEMPLATE_DECLARATION_TYPE_RANK( float, RANK ) \ diff --git a/src/atlas/array/native/NativeArray.cc b/src/atlas/array/native/NativeArray.cc index bd4b6f117..9ae1b6417 100644 --- a/src/atlas/array/native/NativeArray.cc +++ b/src/atlas/array/native/NativeArray.cc @@ -68,6 +68,8 @@ Array* Array::create( DataType datatype, const ArrayShape& shape ) { return new ArrayT( shape ); case DataType::KIND_REAL32: return new ArrayT( shape ); + case DataType::KIND_INT8: + return new ArrayT( shape ); case DataType::KIND_INT32: return new ArrayT( shape ); case DataType::KIND_INT64: diff --git a/src/atlas/array/native/NativeArrayView.cc b/src/atlas/array/native/NativeArrayView.cc index 8c7d0e9f1..de024cf44 100644 --- a/src/atlas/array/native/NativeArrayView.cc +++ b/src/atlas/array/native/NativeArrayView.cc @@ -59,6 +59,8 @@ void ArrayView::dump( std::ostream& os ) const { namespace atlas { namespace array { #define EXPLICIT_TEMPLATE_INSTANTIATION( Rank ) \ + template class ArrayView; \ + template class ArrayView; \ template class ArrayView; \ template class ArrayView; \ template class ArrayView; \ @@ -69,10 +71,12 @@ namespace array { template class ArrayView; \ template class ArrayView; \ template class ArrayView; \ + template void ArrayView::assign( char const& ); \ template void ArrayView::assign( int const& ); \ template void ArrayView::assign( long const& ); \ template void ArrayView::assign( float const& ); \ template void ArrayView::assign( double const& ); \ + template void ArrayView::assign( std::initializer_list const& ); \ template void ArrayView::assign( std::initializer_list const& ); \ template void ArrayView::assign( std::initializer_list const& ); \ template void ArrayView::assign( std::initializer_list const& ); \ diff --git a/src/atlas/array/native/NativeMakeView.cc b/src/atlas/array/native/NativeMakeView.cc index b4c137e7b..2aac613f9 100644 --- a/src/atlas/array/native/NativeMakeView.cc +++ b/src/atlas/array/native/NativeMakeView.cc @@ -118,6 +118,7 @@ namespace array { template ArrayView make_device_view( const Array& ); #define EXPLICIT_TEMPLATE_INSTATIATION( RANK ) \ + EXPLICIT_TEMPLATE_INSTANTIATION_TYPE_RANK( char, RANK ) \ EXPLICIT_TEMPLATE_INSTANTIATION_TYPE_RANK( int, RANK ) \ EXPLICIT_TEMPLATE_INSTANTIATION_TYPE_RANK( long, RANK ) \ EXPLICIT_TEMPLATE_INSTANTIATION_TYPE_RANK( float, RANK ) \ diff --git a/src/tests/functionspace/testphi.cc b/src/tests/functionspace/testphi.cc index 169bd210d..19fcefadd 100644 --- a/src/tests/functionspace/testphi.cc +++ b/src/tests/functionspace/testphi.cc @@ -2,12 +2,14 @@ #include "atlas/array.h" #include + +// Drop a dimension of a view (set it to a fixed value); we get a view of rank=Rank-1 + template atlas::array::ArrayView dropDimension (const atlas::array::ArrayView & view, int dim, atlas::idx_t idx) { constexpr int rank = Rank-1; - atlas::idx_t _shape[rank], _strides[rank]; atlas::array::ArrayShape shape; atlas::array::ArrayStrides strides; @@ -26,7 +28,6 @@ dropDimension (const atlas::array::ArrayView & view, int dim, atlas: strides.push_back (view.stride (i)); } - using nonConstValue = typename std::remove_const::type; Value * data = (nonConstValue *) (view.data ()); @@ -34,18 +35,65 @@ dropDimension (const atlas::array::ArrayView & view, int dim, atlas: return atlas::array::ArrayView (data + stride_dim * idx, shape, strides); } + +// Convert a view to a view of bytes (add an extra inner dimension) + using byte = unsigned char; -#ifdef UNDEF template atlas::array::ArrayView byteView (const atlas::array::ArrayView & view) { - + constexpr int rank = Rank+1; + atlas::array::ArrayShape shape; + atlas::array::ArrayStrides strides; + + size_t dlen = atlas::array::DataType::create ().size (); + + for (int i = 0; i < Rank; i++) + { + shape.push_back (view.shape (i)); + strides.push_back (view.stride (i) * dlen); + } + + shape.push_back (dlen); + strides.push_back (1); + + byte * data = (byte *) (view.data ()); + + return atlas::array::ArrayView (data, shape, strides); } -#endif +// The following templates create a list of byte views of rank 2 from a view of any rank, any type + +template +void listOf1DByteView (atlas::array::ArrayView & view, + std::vector> & list) +{ + static_assert (Rank > 2, "listOf1DByteView should be called with views having a Rank > 2"); + for (int i = 0; i < view.shape (0); i++) + { + auto v = dropDimension (view, 0, i); + listOf1DByteView (v, list); + } +} + +template <> +void listOf1DByteView (atlas::array::ArrayView & view, + std::vector> & list) +{ + list.push_back (view); +} + +template +void createListOf1DByteView (atlas::array::ArrayView & view, + std::vector> & list) +{ + auto v = byteView (view); + listOf1DByteView (v, list); +} + template void prss (const std::string & t, const V & v) @@ -56,14 +104,11 @@ void prss (const std::string & t, const V & v) printf ("\n"); } - int main (int argc, char * argv[]) { - atlas::Field f ("f", atlas::array::DataType::kind (), {5, 7}); + atlas::Field f ("f", atlas::array::DataType::kind (), {5, 7}); -//auto w = atlas::array::make_view (f, atlas::util::Config ("check_type", false)); - auto w = atlas::array::make_view_nocheck (f); - auto v = atlas::array::make_view (f); + auto v = atlas::array::make_view (f); prss ("v", v); @@ -76,6 +121,40 @@ int main (int argc, char * argv[]) printf (" &v(1,0) = 0x%llx\n", &v(1,0)); printf (" &v(0,1) = 0x%llx\n", &v(0,1)); + auto c = byteView (v); + + std::vector> list; + + createListOf1DByteView (v, list); + + std::cout << " list.size () = " << list.size () << std::endl; + + prss ("c", c); + + printf (" sizeof (c (0,0)) = %d\n", sizeof (c (0,0))); + + for (int i = 0; i < 4; i++) + printf (" &c(0,0,%d) = 0x%llx\n", i, &c(0,0,i)); + + for (int i = 0; i < 4; i++) + printf (" &c(0,%d,0) = 0x%llx\n", i, &c(0,i,0)); + + for (int i = 0; i < 4; i++) + printf (" &c(%d,0,0) = 0x%llx\n", i, &c(i,0,0)); + + +if(1) + for (int i = 0; i < 3; i++) + { + c (i, i, 0) = 0xff; + c (i, i, 1) = 0xff; + c (i, i, 2) = 0xff; + c (i, i, 3) = 0xff; + c (i, i, 4) = 0xff; + c (i, i, 5) = 0xff; + c (i, i, 6) = 0xff; + c (i, i, 7) = 0xff; + } printf (" %8s |", ""); for (int j = 0; j < v.shape ()[1]; j++) @@ -86,7 +165,7 @@ int main (int argc, char * argv[]) { printf (" %8d |", i); for (int j = 0; j < v.shape ()[1]; j++) - printf (" %12.0f", v (i, j)); + printf (" %12d", v (i, j)); printf ("\n"); } @@ -98,7 +177,7 @@ int main (int argc, char * argv[]) std::cout << " v1.rank () = " << v1.rank () << std::endl; for (int i = 0; i < v1.shape (0); i++) - printf (" %8d > %12.2f\n", i, v1 (i)); + printf (" %8d > %12d\n", i, v1 (i)); auto v2 = dropDimension (v, -1, 1); @@ -106,7 +185,7 @@ int main (int argc, char * argv[]) std::cout << " v2.rank () = " << v2.rank () << std::endl; for (int i = 0; i < v2.shape (0); i++) - printf (" %8d > %12.2f\n", i, v2 (i)); + printf (" %8d > %12d\n", i, v2 (i)); auto v3 = dropDimension (v, 0, 2); @@ -115,7 +194,7 @@ int main (int argc, char * argv[]) prss ("v3", v3); for (int i = 0; i < v3.shape (0); i++) - printf (" %8d > %12.2f\n", i, v3 (i)); + printf (" %8d > %12d\n", i, v3 (i)); return 0; From 56ffc8a52db805583bc55369efc9d9343095e08d Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Tue, 19 May 2020 07:36:45 +0000 Subject: [PATCH 07/58] Use ioFieldDesc --- src/tests/functionspace/testphi.cc | 78 +++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/src/tests/functionspace/testphi.cc b/src/tests/functionspace/testphi.cc index 19fcefadd..00f5e3629 100644 --- a/src/tests/functionspace/testphi.cc +++ b/src/tests/functionspace/testphi.cc @@ -66,32 +66,94 @@ byteView (const atlas::array::ArrayView & view) // The following templates create a list of byte views of rank 2 from a view of any rank, any type +// + +class ioFieldDesc +{ +public: + ioFieldDesc (atlas::array::ArrayView & _v, + const std::vector & _ind, + const atlas::Field & _f) : v (_v), ind (_ind), f (_f) {} + const std::vector & indices () const + { + return ind; + } + const atlas::Field & field () const + { + return f; + } +private: + atlas::array::ArrayView v; + const std::vector ind; + const atlas::Field & f; +}; template void listOf1DByteView (atlas::array::ArrayView & view, - std::vector> & list) + const std::vector & _ind, + const atlas::Field & f, + std::vector & list) { static_assert (Rank > 2, "listOf1DByteView should be called with views having a Rank > 2"); + + std::vector ind = _ind; + ind.push_back (0); + for (int i = 0; i < view.shape (0); i++) { auto v = dropDimension (view, 0, i); - listOf1DByteView (v, list); + ind.back () = i; + listOf1DByteView (v, ind, f, list); } } template <> void listOf1DByteView (atlas::array::ArrayView & view, - std::vector> & list) + const std::vector & ind, + const atlas::Field & f, + std::vector & list) { - list.push_back (view); + list.push_back (ioFieldDesc (view, ind, f)); } template void createListOf1DByteView (atlas::array::ArrayView & view, - std::vector> & list) + const atlas::Field & f, + std::vector & list) { auto v = byteView (view); - listOf1DByteView (v, list); + listOf1DByteView (v, std::vector (), f, list); +} + +void createIoFieldDescriptors (atlas::Field & f, std::vector & list) +{ + int rank = f.rank (); + auto type = f.datatype (); + +#define HANDLE_TYPE_RANK(__type,__rank) \ + if (rank == __rank) \ + { \ + auto v = atlas::array::make_view<__type,__rank> (f); \ + createListOf1DByteView (v, f, list); \ + goto done; \ + } + +#define HANDLE_TYPE(__type) \ + if (type.kind () == atlas::array::DataType::create<__type> ().kind ()) \ + { \ + HANDLE_TYPE_RANK (__type, 1); HANDLE_TYPE_RANK (__type, 2); HANDLE_TYPE_RANK (__type, 3); \ + HANDLE_TYPE_RANK (__type, 4); HANDLE_TYPE_RANK (__type, 5); HANDLE_TYPE_RANK (__type, 6); \ + HANDLE_TYPE_RANK (__type, 7); HANDLE_TYPE_RANK (__type, 8); HANDLE_TYPE_RANK (__type, 9); \ + } + + HANDLE_TYPE (long); + HANDLE_TYPE (double); + HANDLE_TYPE (int); + HANDLE_TYPE (float); + +done: + + return; } @@ -123,9 +185,9 @@ int main (int argc, char * argv[]) auto c = byteView (v); - std::vector> list; + std::vector list; - createListOf1DByteView (v, list); + createIoFieldDescriptors (f, list); std::cout << " list.size () = " << list.size () << std::endl; From f9a929e93d12f43d3deedf59736d3c76a641077e Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Tue, 19 May 2020 20:36:46 +0000 Subject: [PATCH 08/58] Split into several files; first working gather --- src/tests/functionspace/CMakeLists.txt | 4 +- src/tests/functionspace/arrayViewHelpers.h | 62 +++++ src/tests/functionspace/ioFieldDesc.cc | 84 ++++++ src/tests/functionspace/ioFieldDesc.h | 83 ++++++ src/tests/functionspace/test_batchgather.cc | 289 +++++++++++--------- src/tests/functionspace/testphi.cc | 157 +---------- 6 files changed, 388 insertions(+), 291 deletions(-) create mode 100644 src/tests/functionspace/arrayViewHelpers.h create mode 100644 src/tests/functionspace/ioFieldDesc.cc create mode 100644 src/tests/functionspace/ioFieldDesc.h diff --git a/src/tests/functionspace/CMakeLists.txt b/src/tests/functionspace/CMakeLists.txt index 6f2521f31..7e8347e49 100644 --- a/src/tests/functionspace/CMakeLists.txt +++ b/src/tests/functionspace/CMakeLists.txt @@ -24,13 +24,13 @@ if( HAVE_FCTEST ) endif() ecbuild_add_test( TARGET test_batchgather - SOURCES test_batchgather.cc + SOURCES test_batchgather.cc ioFieldDesc.cc LIBS atlas ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} ) ecbuild_add_test( TARGET testphi - SOURCES testphi.cc + SOURCES testphi.cc ioFieldDesc.cc LIBS atlas ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} ) diff --git a/src/tests/functionspace/arrayViewHelpers.h b/src/tests/functionspace/arrayViewHelpers.h new file mode 100644 index 000000000..a5659f990 --- /dev/null +++ b/src/tests/functionspace/arrayViewHelpers.h @@ -0,0 +1,62 @@ + +#pragma once + + +// Drop a dimension of a view (set it to a fixed value); we get a view of rank=Rank-1 + +template +atlas::array::ArrayView +dropDimension (const atlas::array::ArrayView & view, int dim, atlas::idx_t idx) +{ + constexpr int rank = Rank-1; + atlas::array::ArrayShape shape; + atlas::array::ArrayStrides strides; + + if (dim < 0) + dim = dim + Rank; + + for (int i = 0; i < dim; i++) + { + shape.push_back (view.shape (i)); + strides.push_back (view.stride (i)); + } + atlas::idx_t stride_dim = view.stride (dim); + for (int i = dim + 1; i < Rank; i++) + { + shape.push_back (view.shape (i)); + strides.push_back (view.stride (i)); + } + + using nonConstValue = typename std::remove_const::type; + + Value * data = (nonConstValue *) (view.data ()); + + return atlas::array::ArrayView (data + stride_dim * idx, shape, strides); +} + +// Convert a view to a view of bytes (add an extra inner dimension) + +template +atlas::array::ArrayView +byteView (const atlas::array::ArrayView & view) +{ + constexpr int rank = Rank+1; + atlas::array::ArrayShape shape; + atlas::array::ArrayStrides strides; + + size_t dlen = atlas::array::DataType::create ().size (); + + for (int i = 0; i < Rank; i++) + { + shape.push_back (view.shape (i)); + strides.push_back (view.stride (i) * dlen); + } + + shape.push_back (dlen); + strides.push_back (1); + + byte * data = (byte *) (view.data ()); + + return atlas::array::ArrayView (data, shape, strides); +} + diff --git a/src/tests/functionspace/ioFieldDesc.cc b/src/tests/functionspace/ioFieldDesc.cc new file mode 100644 index 000000000..fb30f197b --- /dev/null +++ b/src/tests/functionspace/ioFieldDesc.cc @@ -0,0 +1,84 @@ +#include "ioFieldDesc.h" +#include "arrayViewHelpers.h" + + + +// The following templates create a list of byte views of rank 2 from a view of any rank, any type +// + +template +void listOf1DByteView (atlas::array::ArrayView & view, + const std::vector & _ind, + const atlas::Field & f, size_t ldim, + std::vector & list) +{ + static_assert (Rank > 2, "listOf1DByteView should be called with views having a Rank > 2"); + + std::vector ind = _ind; + ind.push_back (0); + + for (int i = 0; i < view.shape (0); i++) + { + auto v = dropDimension (view, 0, i); + ind.back () = i; + listOf1DByteView (v, ind, f, ldim, list); + } +} + +template <> +void listOf1DByteView (atlas::array::ArrayView & view, + const std::vector & ind, + const atlas::Field & f, size_t ldim, + std::vector & list) +{ + list.push_back (ioFieldDesc (view, ind, f, ldim)); +} + +template +void createListOf1DByteView (atlas::array::ArrayView & view, + const atlas::Field & f, size_t ldim, + std::vector & list) +{ + auto v = byteView (view); + listOf1DByteView (v, std::vector (), f, ldim, list); +} + +void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim) +{ + int rank = f.rank (); + auto type = f.datatype (); + +#define HANDLE_TYPE_RANK(__type,__rank) \ + if (rank == __rank) \ + { \ + auto v = atlas::array::make_view<__type,__rank> (f); \ + createListOf1DByteView (v, f, ldim, list); \ + goto done; \ + } + +#define HANDLE_TYPE(__type) \ + if (type.kind () == atlas::array::DataType::create<__type> ().kind ()) \ + { \ + HANDLE_TYPE_RANK (__type, 1); HANDLE_TYPE_RANK (__type, 2); HANDLE_TYPE_RANK (__type, 3); \ + HANDLE_TYPE_RANK (__type, 4); HANDLE_TYPE_RANK (__type, 5); HANDLE_TYPE_RANK (__type, 6); \ + HANDLE_TYPE_RANK (__type, 7); HANDLE_TYPE_RANK (__type, 8); HANDLE_TYPE_RANK (__type, 9); \ + } + + HANDLE_TYPE (long); + HANDLE_TYPE (double); + HANDLE_TYPE (int); + HANDLE_TYPE (float); + +done: + + return; +} + +void createIoFieldDescriptors (atlas::FieldSet & s, std::vector & list, size_t ldim) +{ + for (auto & f : s) + createIoFieldDescriptors (f, list, ldim); +} + + + diff --git a/src/tests/functionspace/ioFieldDesc.h b/src/tests/functionspace/ioFieldDesc.h new file mode 100644 index 000000000..b7f46a06a --- /dev/null +++ b/src/tests/functionspace/ioFieldDesc.h @@ -0,0 +1,83 @@ + +#pragma once + +#include "atlas/field.h" +#include "atlas/array.h" +#include + + +typedef char byte; + +class ioFieldDesc +{ +public: + ioFieldDesc (atlas::array::ArrayView & v, + const std::vector & ind, + const atlas::Field & f, size_t ldim) + : _v (v), _ind (ind), _f (f), _ldim (ldim) + { + _dlen = _v.shape (1); + if (_ldim == 0) + _ldim = _v.shape (0); + _size = _ldim * _v.shape (1); + } + + atlas::array::ArrayView & view () + { + return _v; + } + + const std::vector & indices () const + { + return _ind; + } + + const atlas::Field & field () const + { + return _f; + } + + int & owner () + { + return _owner; + } + + int owner () const + { + return _owner; + } + + size_t size () const + { + return _size; + } + + size_t dlen () const + { + return _dlen; + } + + void pack (byte * buffer) const + { + for (int i = 0; i < _ldim; i++) + for (int j = 0; j < _dlen; j++) + buffer[i*_dlen+j] = _v (i, j); + } + + byte & operator () (int i, int j) + { + return _v (i, j); + } + +private: + atlas::array::ArrayView _v; + const std::vector _ind; + const atlas::Field & _f; + int _owner = 0; + size_t _ldim; + size_t _size; + size_t _dlen; +}; + +void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim = 0); +void createIoFieldDescriptors (atlas::FieldSet & s, std::vector & list, size_t ldim = 0); diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index 5ffb37515..94d4d3899 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -14,6 +14,7 @@ #include "atlas/functionspace.h" #include "atlas/parallel/mpi/mpi.h" #include "tests/AtlasTestEnvironment.h" +#include "ioFieldDesc.h" using namespace eckit; using namespace atlas::functionspace; @@ -25,9 +26,6 @@ namespace test { namespace { - -typedef char byte; - void getprcind (const atlas::functionspace::StructuredColumns & fs, const atlas::grid::Distribution & dist, std::vector & prc, std::vector & ind) { @@ -54,9 +52,10 @@ void getprcind (const atlas::functionspace::StructuredColumns & fs, const atlas: template T reorder (const T & vec, const I & ord) { - T v (ord.size ()); + T v; + v.reserve (ord.size ()); for (typename I::value_type i = 0; i < ord.size (); i++) - v[i] = vec[ord[i]]; + v.push_back (vec[ord[i]]); return v; } @@ -68,98 +67,67 @@ void integrate (T & v) v[i].off = v[i-1].off + v[i-1].len; } -void pack (const atlas::Field & f, size_t lsize, byte * buf) +class mapping_t { - size_t dsize = f.datatype ().size (); - - switch (f.rank ()) - { - case 1: - case 2: - case 3: - } - - - -} - -void gather (const atlas::StructuredGrid & grid, const atlas::grid::Distribution & dist, - const atlas::FieldSet & sloc, atlas::FieldSet & sglo) -{ - ATLAS_ASSERT (sloc.size () == sglo.size ()); - size_t nfld = sloc.size (); - - auto & comm = mpi::comm (); - int nprc = comm.size (); - int lprc = comm.rank (); - - std::vector count (nprc); - std::vector ind (grid.size ()); - - for (int i = 0; i < grid.size (); i++) - ind[i] = count[dist.partition (i)]++; - - int max = *std::max_element (count.begin (), count.end ()); +private: class locprc_t { public: - locprc_t () = default; - locprc_t (const std::initializer_list & l) - { - auto it = l.begin (); - loc = *it++; - prc = *it++; - } int loc = std::numeric_limits::min (); int prc = std::numeric_limits::min (); }; - class locprc2glo_t + int max, nprc; + + std::vector prcloc2glo; + std::vector glo2prcloc; +public: + mapping_t (const atlas::StructuredGrid & grid, const atlas::grid::Distribution & dist) { - public: - locprc2glo_t (int _max, int _nprc) : max (_max), nprc (_nprc) - { - data.resize (max * nprc, std::numeric_limits::min ()); - } - int & operator () (int iprc, int jloc) - { - return data[iprc * max + jloc]; - } - - class slice_t - { - public: - slice_t (int _iprc, locprc2glo_t * _locprc2glo) - : iprc (_iprc), locprc2glo (_locprc2glo) - { - } - int & operator [] (int jloc) + nprc = dist.nb_partitions (); + + std::vector count (nprc); + std::vector ind (grid.size ()); + + for (int i = 0; i < grid.size (); i++) + ind[i] = count[dist.partition (i)]++; + + max = *std::max_element (count.begin (), count.end ()); + + prcloc2glo.resize (max * nprc, std::numeric_limits::min ()); + glo2prcloc.resize (grid.size ()); + + for (int i = 0; i < grid.size (); i++) { - return (*locprc2glo) (iprc, jloc); + prcloc2glo[max * dist.partition (i) + ind[i]] = i; + glo2prcloc[i].loc = ind[i]; + glo2prcloc[i].prc = dist.partition (i); } - private: - locprc2glo_t * locprc2glo; - int iprc; - }; - slice_t operator[] (int iprc) - { - return slice_t (iprc, this); - } - private: - int max, nprc; - std::vector data; - }; + } - class glo2locprc_t : public std::vector + int operator () (int iprc, int jloc) const { - public: - glo2locprc_t () = default; - glo2locprc_t (size_t size) : std::vector (size) - { - } - }; + return prcloc2glo[iprc * max + jloc]; + } + + const locprc_t & operator () (int jglo) const + { + return glo2prcloc[jglo]; + } + +}; + +void gather (const atlas::StructuredGrid & grid, const atlas::grid::Distribution & dist, + std::vector & floc, std::vector & fglo) +{ + ATLAS_ASSERT (floc.size () == fglo.size ()); + size_t nfld = floc.size (); + + auto & comm = mpi::comm (); + int nprc = comm.size (); + int lprc = comm.rank (); class offlen_t { @@ -167,54 +135,21 @@ void gather (const atlas::StructuredGrid & grid, const atlas::grid::Distribution size_t off = 0, len = 0; }; - class sizmul_t - { - public: - size_t siz = 0, mul = 1; - }; + mapping_t mapping (grid, dist); + + size_t ldim = dist.nb_pts ()[lprc]; - locprc2glo_t locprc2glo (max, nprc); - glo2locprc_t glo2locprc (grid.size ()); - - for (int i = 0; i < grid.size (); i++) - { - locprc2glo[dist.partition (i)][ind[i]] = i; - glo2locprc[i] = {ind[i], dist.partition (i)}; - } - // Sort fields by owner - std::vector floc (nfld); - std::vector fglo (nfld); - std::vector isort (nfld), owner (nfld); - - for (int jfld = 0; jfld < nfld; jfld++) - { - floc[jfld] = sloc[jfld]; - fglo[jfld] = sglo[jfld]; - fglo[jfld].metadata ().get ("owner", owner[jfld]); - } + std::vector isort (nfld); std::iota (std::begin (isort), std::end (isort), 0); - std::sort (std::begin (isort), std::end (isort), [&owner] (int a, int b) { return owner[a] < owner[b]; }); + std::sort (std::begin (isort), std::end (isort), + [&fglo] (int a, int b) { return fglo[a].owner () < fglo[b].owner (); }); - owner = reorder (owner, isort); floc = reorder (floc, isort); fglo = reorder (fglo, isort); - // Collect field datatype size & number - - std::vector fld_info (nfld); - - for (int jfld = 0; jfld < nfld; jfld++) - { - auto & f = floc[jfld]; - const auto & ss = f.shape (); - for (int i = 1; i < ss.size (); i++) - fld_info[jfld].mul *= ss[i]; - fld_info[jfld].siz = f.datatype ().size (); - } - // SEND std::vector fld_send (nfld + 1); @@ -222,35 +157,80 @@ void gather (const atlas::StructuredGrid & grid, const atlas::grid::Distribution for (int jfld = 0; jfld < nfld; jfld++) { - // datatype size x leading dimension x product of other dimension - fld_send[jfld].len = fld_info[jfld].siz * fld_info[jfld].mul; - prc_send[owner[jfld]].len += fld_send[jfld].len; + int owner = fglo[jfld].owner (); + fld_send[jfld].len = floc[jfld].size (); + prc_send[owner].len += floc[jfld].size (); } +printf (" dist.nb_pts ()[lprc] = %8d\n", dist.nb_pts ()[lprc]); + integrate (fld_send); integrate (prc_send); // Pack send buffer - std::vector buf_send (fld_send.back ().off * dist.nb_pts ()[lprc]); + std::vector buf_send (fld_send.back ().off); for (int jfld = 0; jfld < nfld; jfld++) - pack (floc[jfld], dist.nb_pts ()[lprc], &buf_send[fld_send[jfld].off]); + floc[jfld].pack (&buf_send[fld_send[jfld].off]); // RECV + std::vector prc_recv (nprc + 1); std::vector fld_recv (nfld + 1); for (int jfld = 0; jfld < nfld; jfld++) - if (lprc == owner[jfld]) - fld_recv[jfld].len = fld_info[jfld].siz * fld_info[jfld].mul; + if (lprc == fglo[jfld].owner ()) + fld_recv[jfld].len = fglo[jfld].dlen (); integrate (fld_recv); - + for (int iprc = 0; iprc < nprc; iprc++) + prc_recv[iprc].len = dist.nb_pts ()[iprc] * fld_recv.back ().off; + + integrate (prc_recv); + + std::vector buf_recv (prc_recv.back ().off); + + std::vector rqr; + + for (int iprc = 0; iprc < nprc; iprc++) + if (prc_recv[iprc].len > 0) + rqr.push_back (comm.iReceive (&buf_recv[prc_recv[iprc].off], + prc_recv[iprc].len, iprc, 100)); + comm.barrier (); + std::vector rqs; + for (int iprc = 0; iprc < nprc; iprc++) + if (prc_send[iprc].len > 0) + rqs.push_back (comm.iSend (&buf_send[prc_send[iprc].off], + prc_send[iprc].len, iprc, 100)); + + for (auto & r : rqr) + comm.wait (r); + + for (auto & r : rqs) + comm.wait (r); + + // Unpack RECV buffer + + for (int iprc = 0; iprc < nprc; iprc++) + if (prc_recv[iprc].len > 0) + { + int off = prc_recv[iprc].off; + for (int jfld = 0; jfld < nfld; jfld++) + { + if (fld_recv[jfld].len > 0) + { + for (int jloc = 0, k = 0; jloc < dist.nb_pts ()[iprc]; jloc++) + for (int j = 0; j < fld_recv[jfld].len; j++, k++) + fglo[jfld](mapping (iprc, jloc), j) = buf_recv[off+k]; + off += dist.nb_pts ()[iprc] * fglo[jfld].dlen (); + } + } + } } @@ -277,11 +257,14 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { atlas::FieldSet sloc; atlas::FieldSet sglo, sglo2; -#ifdef UNDEF + { + char tmp[128]; + sprintf (tmp, "prcind.%8.8d.txt", irank); + FILE * fp = fopen (tmp, "w"); for (int i = 0; i < grid.size (); i++) - printf (" %8d > %8d, %8d\n", i, prc[i], ind[i]); -#endif - + fprintf (fp, " %8d > %8d, %8d\n", i, prc[i], ind[i]); + fclose (fp); + } using T = long; @@ -295,6 +278,8 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { auto func = [&ind_off,&prc_off,&fld_off] (int fld, int prc, int ind) { + long x = prc; + return x; long v = (static_cast (fld) << fld_off) + (static_cast (prc) << prc_off) + (static_cast (ind) << ind_off); @@ -304,6 +289,7 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { for (int i = 0; i < nfields; i++) { int owner = i % nproc; + std::string name = std::string ("#") + std::to_string (i); atlas::Field floc = fs.createField (atlas::util::Config ("name", name) | atlas::util::Config ("owner", owner)); @@ -318,13 +304,46 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { Field fglo2 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); fglo2.metadata ().set ("owner", owner); - sglo2.add (fglo); + sglo2.add (fglo2); } + fs.gather (sloc, sglo); -// gather (grid, dist, sloc, sglo2); + { + + std::vector dloc; + std::vector dglo; + + createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); + createIoFieldDescriptors (sglo2, dglo, grid.size ()); + + for (auto & d : dglo) + d.field ().metadata ().get ("owner", d.owner ()); + + printf (" dloc.size () = %8d\n", dloc.size ()); + printf (" dglo.size () = %8d\n", dglo.size ()); + + gather (grid, dist, dloc, dglo); + + + for (int i = 0; i < sglo2.size (); i++) + { + auto v = array::make_view (sglo2[i]); + if (v.size () == 0) + continue; + + char tmp[128]; + sprintf (tmp, "out.%8.8d.%8.8d.txt", irank, i); + FILE * fp = fopen (tmp, "w"); + for (int i = 0; i < v.size (); i++) + fprintf (fp, "%8d > %8d\n", i, v (i)); + } + + } + +if(1) for (int i = 0; i < nfields; i++) { const auto & fglo = sglo[i]; diff --git a/src/tests/functionspace/testphi.cc b/src/tests/functionspace/testphi.cc index 00f5e3629..1ad704ba1 100644 --- a/src/tests/functionspace/testphi.cc +++ b/src/tests/functionspace/testphi.cc @@ -1,162 +1,11 @@ +#include "ioFieldDesc.h" +#include "arrayViewHelpers.h" + #include "atlas/field.h" #include "atlas/array.h" #include -// Drop a dimension of a view (set it to a fixed value); we get a view of rank=Rank-1 - -template -atlas::array::ArrayView -dropDimension (const atlas::array::ArrayView & view, int dim, atlas::idx_t idx) -{ - constexpr int rank = Rank-1; - atlas::array::ArrayShape shape; - atlas::array::ArrayStrides strides; - - if (dim < 0) - dim = dim + Rank; - - for (int i = 0; i < dim; i++) - { - shape.push_back (view.shape (i)); - strides.push_back (view.stride (i)); - } - atlas::idx_t stride_dim = view.stride (dim); - for (int i = dim + 1; i < Rank; i++) - { - shape.push_back (view.shape (i)); - strides.push_back (view.stride (i)); - } - - using nonConstValue = typename std::remove_const::type; - - Value * data = (nonConstValue *) (view.data ()); - - return atlas::array::ArrayView (data + stride_dim * idx, shape, strides); -} - - -// Convert a view to a view of bytes (add an extra inner dimension) - -using byte = unsigned char; - -template -atlas::array::ArrayView -byteView (const atlas::array::ArrayView & view) -{ - constexpr int rank = Rank+1; - atlas::array::ArrayShape shape; - atlas::array::ArrayStrides strides; - - size_t dlen = atlas::array::DataType::create ().size (); - - for (int i = 0; i < Rank; i++) - { - shape.push_back (view.shape (i)); - strides.push_back (view.stride (i) * dlen); - } - - shape.push_back (dlen); - strides.push_back (1); - - byte * data = (byte *) (view.data ()); - - return atlas::array::ArrayView (data, shape, strides); -} - - -// The following templates create a list of byte views of rank 2 from a view of any rank, any type -// - -class ioFieldDesc -{ -public: - ioFieldDesc (atlas::array::ArrayView & _v, - const std::vector & _ind, - const atlas::Field & _f) : v (_v), ind (_ind), f (_f) {} - const std::vector & indices () const - { - return ind; - } - const atlas::Field & field () const - { - return f; - } -private: - atlas::array::ArrayView v; - const std::vector ind; - const atlas::Field & f; -}; - -template -void listOf1DByteView (atlas::array::ArrayView & view, - const std::vector & _ind, - const atlas::Field & f, - std::vector & list) -{ - static_assert (Rank > 2, "listOf1DByteView should be called with views having a Rank > 2"); - - std::vector ind = _ind; - ind.push_back (0); - - for (int i = 0; i < view.shape (0); i++) - { - auto v = dropDimension (view, 0, i); - ind.back () = i; - listOf1DByteView (v, ind, f, list); - } -} - -template <> -void listOf1DByteView (atlas::array::ArrayView & view, - const std::vector & ind, - const atlas::Field & f, - std::vector & list) -{ - list.push_back (ioFieldDesc (view, ind, f)); -} - -template -void createListOf1DByteView (atlas::array::ArrayView & view, - const atlas::Field & f, - std::vector & list) -{ - auto v = byteView (view); - listOf1DByteView (v, std::vector (), f, list); -} - -void createIoFieldDescriptors (atlas::Field & f, std::vector & list) -{ - int rank = f.rank (); - auto type = f.datatype (); - -#define HANDLE_TYPE_RANK(__type,__rank) \ - if (rank == __rank) \ - { \ - auto v = atlas::array::make_view<__type,__rank> (f); \ - createListOf1DByteView (v, f, list); \ - goto done; \ - } - -#define HANDLE_TYPE(__type) \ - if (type.kind () == atlas::array::DataType::create<__type> ().kind ()) \ - { \ - HANDLE_TYPE_RANK (__type, 1); HANDLE_TYPE_RANK (__type, 2); HANDLE_TYPE_RANK (__type, 3); \ - HANDLE_TYPE_RANK (__type, 4); HANDLE_TYPE_RANK (__type, 5); HANDLE_TYPE_RANK (__type, 6); \ - HANDLE_TYPE_RANK (__type, 7); HANDLE_TYPE_RANK (__type, 8); HANDLE_TYPE_RANK (__type, 9); \ - } - - HANDLE_TYPE (long); - HANDLE_TYPE (double); - HANDLE_TYPE (int); - HANDLE_TYPE (float); - -done: - - return; -} - - template void prss (const std::string & t, const V & v) { From 6ffc7cadfa66de8b61f37118e949ba96da42fd99 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 20 May 2020 07:37:35 +0000 Subject: [PATCH 09/58] Refactor --- src/tests/functionspace/test_batchgather.cc | 172 +++++++++++--------- 1 file changed, 97 insertions(+), 75 deletions(-) diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index 94d4d3899..aea988280 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -80,45 +80,53 @@ class mapping_t int max, nprc; - std::vector prcloc2glo; - std::vector glo2prcloc; -public: - mapping_t (const atlas::StructuredGrid & grid, const atlas::grid::Distribution & dist) - { - nprc = dist.nb_partitions (); - - std::vector count (nprc); - std::vector ind (grid.size ()); - - for (int i = 0; i < grid.size (); i++) - ind[i] = count[dist.partition (i)]++; - - max = *std::max_element (count.begin (), count.end ()); - - prcloc2glo.resize (max * nprc, std::numeric_limits::min ()); - glo2prcloc.resize (grid.size ()); + std::vector _prcloc2glo; + std::vector _glo2prcloc; - for (int i = 0; i < grid.size (); i++) - { - prcloc2glo[max * dist.partition (i) + ind[i]] = i; - glo2prcloc[i].loc = ind[i]; - glo2prcloc[i].prc = dist.partition (i); - } + const atlas::StructuredGrid & grid; + const atlas::grid::Distribution & dist; - } +public: + mapping_t (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist); - int operator () (int iprc, int jloc) const + int prcloc2glo (int iprc, int jloc) const { - return prcloc2glo[iprc * max + jloc]; + return _prcloc2glo[iprc * max + jloc]; } - const locprc_t & operator () (int jglo) const + const locprc_t & glo2prcloc (int jglo) const { - return glo2prcloc[jglo]; + return _glo2prcloc[jglo]; } + }; +mapping_t::mapping_t (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist) + : grid (_grid), dist (_dist) +{ + nprc = dist.nb_partitions (); + + std::vector count (nprc); + std::vector ind (grid.size ()); + + for (int i = 0; i < grid.size (); i++) + ind[i] = count[dist.partition (i)]++; + + max = *std::max_element (count.begin (), count.end ()); + + _prcloc2glo.resize (max * nprc, std::numeric_limits::min ()); + _glo2prcloc.resize (grid.size ()); + + for (int i = 0; i < grid.size (); i++) + { + _prcloc2glo[max * dist.partition (i) + ind[i]] = i; + _glo2prcloc[i].loc = ind[i]; + _glo2prcloc[i].prc = dist.partition (i); + } + +} + void gather (const atlas::StructuredGrid & grid, const atlas::grid::Distribution & dist, std::vector & floc, std::vector & fglo) { @@ -226,7 +234,7 @@ printf (" dist.nb_pts ()[lprc] = %8d\n", dist.nb_pts ()[lprc]); { for (int jloc = 0, k = 0; jloc < dist.nb_pts ()[iprc]; jloc++) for (int j = 0; j < fld_recv[jfld].len; j++, k++) - fglo[jfld](mapping (iprc, jloc), j) = buf_recv[off+k]; + fglo[jfld](mapping.prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; off += dist.nb_pts ()[iprc] * fglo[jfld].dlen (); } } @@ -234,6 +242,28 @@ printf (" dist.nb_pts ()[lprc] = %8d\n", dist.nb_pts ()[lprc]); } +template +void prff (const std::string & name, const atlas::FieldSet & sglo) +{ + auto & comm = mpi::comm (); + int irank = comm.rank (); + for (int i = 0; i < sglo.size (); i++) + { + auto v = array::make_view (sglo[i]); + if (v.size () == 0) + continue; + + char tmp[128]; + sprintf (tmp, "%s.%8.8d.%8.8d.txt", name.c_str (), irank, i); + FILE * fp = fopen (tmp, "w"); + for (int i = 0; i < v.size (); i++) + fprintf (fp, "%8d > %8d\n", i, v (i)); + fclose (fp); + } +} + + + }; //----------------------------------------------------------------------------- @@ -255,7 +285,7 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { getprcind (fs, dist, prc, ind); atlas::FieldSet sloc; - atlas::FieldSet sglo, sglo2; + atlas::FieldSet sglo1, sglo2; { char tmp[128]; @@ -278,8 +308,6 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { auto func = [&ind_off,&prc_off,&fld_off] (int fld, int prc, int ind) { - long x = prc; - return x; long v = (static_cast (fld) << fld_off) + (static_cast (prc) << prc_off) + (static_cast (ind) << ind_off); @@ -300,7 +328,7 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { Field fglo = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); fglo.metadata ().set ("owner", owner); - sglo.add (fglo); + sglo1.add (fglo); Field fglo2 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); fglo2.metadata ().set ("owner", owner); @@ -309,62 +337,56 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { } - fs.gather (sloc, sglo); + fs.gather (sloc, sglo1); { + std::vector dloc; + std::vector dglo; - std::vector dloc; - std::vector dglo; + createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); + createIoFieldDescriptors (sglo2, dglo, grid.size ()); + + for (auto & d : dglo) + d.field ().metadata ().get ("owner", d.owner ()); - createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); - createIoFieldDescriptors (sglo2, dglo, grid.size ()); - - for (auto & d : dglo) - d.field ().metadata ().get ("owner", d.owner ()); + printf (" dloc.size () = %8d\n", dloc.size ()); + printf (" dglo.size () = %8d\n", dglo.size ()); - printf (" dloc.size () = %8d\n", dloc.size ()); - printf (" dglo.size () = %8d\n", dglo.size ()); + gather (grid, dist, dloc, dglo); - gather (grid, dist, dloc, dglo); - - for (int i = 0; i < sglo2.size (); i++) - { - auto v = array::make_view (sglo2[i]); - if (v.size () == 0) - continue; - - char tmp[128]; - sprintf (tmp, "out.%8.8d.%8.8d.txt", irank, i); - FILE * fp = fopen (tmp, "w"); - for (int i = 0; i < v.size (); i++) - fprintf (fp, "%8d > %8d\n", i, v (i)); - } + prff ("sglo2", sglo2); } -if(1) - for (int i = 0; i < nfields; i++) - { - const auto & fglo = sglo[i]; - int owner; - EXPECT (fglo.metadata ().get ("owner", owner)); - if (owner == irank) - { - const auto v = array::make_view (fglo); - for (int j = 0; j < grid.size (); j++) - { - T v1 = v[j], v2 = func (i, prc[j], ind[j]); - EXPECT_EQ (v1, v2); - } - } - } + prff ("sglo1", sglo1); -} + auto cmp = [ind, prc, grid, func, irank] (const atlas::FieldSet & sglo) + { + for (int i = 0; i < sglo.size (); i++) + { + const auto & fglo = sglo[i]; + int owner; + EXPECT (fglo.metadata ().get ("owner", owner)); + if (owner == irank) + { + const auto v = array::make_view (fglo); + for (int j = 0; j < grid.size (); j++) + { + T v1 = v[j], v2 = func (i, prc[j], ind[j]); + EXPECT_EQ (v1, v2); + } + } + } + }; + + cmp (sglo1); + cmp (sglo2); + +} -//----------------------------------------------------------------------------- } // namespace test } // namespace atlas From 8a38618182248b80ffb04cb9c07465adc9786958 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 20 May 2020 07:48:00 +0000 Subject: [PATCH 10/58] Split into several files --- src/tests/functionspace/CMakeLists.txt | 2 +- src/tests/functionspace/GatherScatter.cc | 166 ++++++++++++++++ src/tests/functionspace/GatherScatter.h | 43 +++++ src/tests/functionspace/test_batchgather.cc | 201 +------------------- 4 files changed, 215 insertions(+), 197 deletions(-) create mode 100644 src/tests/functionspace/GatherScatter.cc create mode 100644 src/tests/functionspace/GatherScatter.h diff --git a/src/tests/functionspace/CMakeLists.txt b/src/tests/functionspace/CMakeLists.txt index 7e8347e49..1c12428b2 100644 --- a/src/tests/functionspace/CMakeLists.txt +++ b/src/tests/functionspace/CMakeLists.txt @@ -24,7 +24,7 @@ if( HAVE_FCTEST ) endif() ecbuild_add_test( TARGET test_batchgather - SOURCES test_batchgather.cc ioFieldDesc.cc + SOURCES test_batchgather.cc ioFieldDesc.cc GatherScatter.cc LIBS atlas ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} ) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc new file mode 100644 index 000000000..162b34bf2 --- /dev/null +++ b/src/tests/functionspace/GatherScatter.cc @@ -0,0 +1,166 @@ +#include "GatherScatter.h" + +#include "atlas/array.h" +#include "atlas/field.h" +#include "atlas/grid.h" +#include "atlas/parallel/mpi/mpi.h" + +namespace +{ + +template +T reorder (const T & vec, const I & ord) +{ + T v; + v.reserve (ord.size ()); + for (typename I::value_type i = 0; i < ord.size (); i++) + v.push_back (vec[ord[i]]); + return v; +} + +template +void integrate (T & v) +{ + v[0].off = 0; + for (size_t i = 1; i < v.size (); i++) + v[i].off = v[i-1].off + v[i-1].len; +} + +}; + +GatherScatter::GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist) + : grid (_grid), dist (_dist) +{ + nprc = dist.nb_partitions (); + + std::vector count (nprc); + std::vector ind (grid.size ()); + + for (int i = 0; i < grid.size (); i++) + ind[i] = count[dist.partition (i)]++; + + max = *std::max_element (count.begin (), count.end ()); + + _prcloc2glo.resize (max * nprc, std::numeric_limits::min ()); + _glo2prcloc.resize (grid.size ()); + + for (int i = 0; i < grid.size (); i++) + { + _prcloc2glo[max * dist.partition (i) + ind[i]] = i; + _glo2prcloc[i].loc = ind[i]; + _glo2prcloc[i].prc = dist.partition (i); + } + +} + +void GatherScatter::gather (std::vector & floc, std::vector & fglo) const +{ + ATLAS_ASSERT (floc.size () == fglo.size ()); + size_t nfld = floc.size (); + + auto & comm = eckit::mpi::comm (); + int nprc = comm.size (); + int lprc = comm.rank (); + + class offlen_t + { + public: + size_t off = 0, len = 0; + }; + + size_t ldim = dist.nb_pts ()[lprc]; + + // Sort fields by owner + + std::vector isort (nfld); + + std::iota (std::begin (isort), std::end (isort), 0); + std::sort (std::begin (isort), std::end (isort), + [&fglo] (int a, int b) { return fglo[a].owner () < fglo[b].owner (); }); + + floc = reorder (floc, isort); + fglo = reorder (fglo, isort); + + // SEND + + std::vector fld_send (nfld + 1); + std::vector prc_send (nprc + 1); + + for (int jfld = 0; jfld < nfld; jfld++) + { + int owner = fglo[jfld].owner (); + fld_send[jfld].len = floc[jfld].size (); + prc_send[owner].len += floc[jfld].size (); + } + +printf (" dist.nb_pts ()[lprc] = %8d\n", dist.nb_pts ()[lprc]); + + integrate (fld_send); + integrate (prc_send); + + // Pack send buffer + + std::vector buf_send (fld_send.back ().off); + + for (int jfld = 0; jfld < nfld; jfld++) + floc[jfld].pack (&buf_send[fld_send[jfld].off]); + + // RECV + + std::vector prc_recv (nprc + 1); + std::vector fld_recv (nfld + 1); + + for (int jfld = 0; jfld < nfld; jfld++) + if (lprc == fglo[jfld].owner ()) + fld_recv[jfld].len = fglo[jfld].dlen (); + + integrate (fld_recv); + + for (int iprc = 0; iprc < nprc; iprc++) + prc_recv[iprc].len = dist.nb_pts ()[iprc] * fld_recv.back ().off; + + integrate (prc_recv); + + std::vector buf_recv (prc_recv.back ().off); + + std::vector rqr; + + for (int iprc = 0; iprc < nprc; iprc++) + if (prc_recv[iprc].len > 0) + rqr.push_back (comm.iReceive (&buf_recv[prc_recv[iprc].off], + prc_recv[iprc].len, iprc, 100)); + + comm.barrier (); + + std::vector rqs; + + for (int iprc = 0; iprc < nprc; iprc++) + if (prc_send[iprc].len > 0) + rqs.push_back (comm.iSend (&buf_send[prc_send[iprc].off], + prc_send[iprc].len, iprc, 100)); + + for (auto & r : rqr) + comm.wait (r); + + for (auto & r : rqs) + comm.wait (r); + + // Unpack RECV buffer + + for (int iprc = 0; iprc < nprc; iprc++) + if (prc_recv[iprc].len > 0) + { + int off = prc_recv[iprc].off; + for (int jfld = 0; jfld < nfld; jfld++) + { + if (fld_recv[jfld].len > 0) + { + for (int jloc = 0, k = 0; jloc < dist.nb_pts ()[iprc]; jloc++) + for (int j = 0; j < fld_recv[jfld].len; j++, k++) + fglo[jfld](prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; + off += dist.nb_pts ()[iprc] * fglo[jfld].dlen (); + } + } + } +} + diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h new file mode 100644 index 000000000..24ff52fe8 --- /dev/null +++ b/src/tests/functionspace/GatherScatter.h @@ -0,0 +1,43 @@ +#pragma once + + +#include "ioFieldDesc.h" +#include "atlas/grid.h" + +class GatherScatter +{ +private: + + class locprc_t + { + public: + int loc = std::numeric_limits::min (); + int prc = std::numeric_limits::min (); + }; + + int max, nprc; + + std::vector _prcloc2glo; + std::vector _glo2prcloc; + + const atlas::StructuredGrid & grid; + const atlas::grid::Distribution & dist; + +public: + GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist); + + int prcloc2glo (int iprc, int jloc) const + { + return _prcloc2glo[iprc * max + jloc]; + } + + const locprc_t & glo2prcloc (int jglo) const + { + return _glo2prcloc[jglo]; + } + + void gather (std::vector & floc, std::vector & fglo) const; + + +}; + diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index aea988280..f63724df6 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -14,6 +14,8 @@ #include "atlas/functionspace.h" #include "atlas/parallel/mpi/mpi.h" #include "tests/AtlasTestEnvironment.h" + +#include "GatherScatter.h" #include "ioFieldDesc.h" using namespace eckit; @@ -49,199 +51,6 @@ void getprcind (const atlas::functionspace::StructuredColumns & fs, const atlas: } } -template -T reorder (const T & vec, const I & ord) -{ - T v; - v.reserve (ord.size ()); - for (typename I::value_type i = 0; i < ord.size (); i++) - v.push_back (vec[ord[i]]); - return v; -} - -template -void integrate (T & v) -{ - v[0].off = 0; - for (size_t i = 1; i < v.size (); i++) - v[i].off = v[i-1].off + v[i-1].len; -} - -class mapping_t -{ -private: - - class locprc_t - { - public: - int loc = std::numeric_limits::min (); - int prc = std::numeric_limits::min (); - }; - - int max, nprc; - - std::vector _prcloc2glo; - std::vector _glo2prcloc; - - const atlas::StructuredGrid & grid; - const atlas::grid::Distribution & dist; - -public: - mapping_t (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist); - - int prcloc2glo (int iprc, int jloc) const - { - return _prcloc2glo[iprc * max + jloc]; - } - - const locprc_t & glo2prcloc (int jglo) const - { - return _glo2prcloc[jglo]; - } - - -}; - -mapping_t::mapping_t (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist) - : grid (_grid), dist (_dist) -{ - nprc = dist.nb_partitions (); - - std::vector count (nprc); - std::vector ind (grid.size ()); - - for (int i = 0; i < grid.size (); i++) - ind[i] = count[dist.partition (i)]++; - - max = *std::max_element (count.begin (), count.end ()); - - _prcloc2glo.resize (max * nprc, std::numeric_limits::min ()); - _glo2prcloc.resize (grid.size ()); - - for (int i = 0; i < grid.size (); i++) - { - _prcloc2glo[max * dist.partition (i) + ind[i]] = i; - _glo2prcloc[i].loc = ind[i]; - _glo2prcloc[i].prc = dist.partition (i); - } - -} - -void gather (const atlas::StructuredGrid & grid, const atlas::grid::Distribution & dist, - std::vector & floc, std::vector & fglo) -{ - ATLAS_ASSERT (floc.size () == fglo.size ()); - size_t nfld = floc.size (); - - auto & comm = mpi::comm (); - int nprc = comm.size (); - int lprc = comm.rank (); - - class offlen_t - { - public: - size_t off = 0, len = 0; - }; - - mapping_t mapping (grid, dist); - - size_t ldim = dist.nb_pts ()[lprc]; - - // Sort fields by owner - - std::vector isort (nfld); - - std::iota (std::begin (isort), std::end (isort), 0); - std::sort (std::begin (isort), std::end (isort), - [&fglo] (int a, int b) { return fglo[a].owner () < fglo[b].owner (); }); - - floc = reorder (floc, isort); - fglo = reorder (fglo, isort); - - // SEND - - std::vector fld_send (nfld + 1); - std::vector prc_send (nprc + 1); - - for (int jfld = 0; jfld < nfld; jfld++) - { - int owner = fglo[jfld].owner (); - fld_send[jfld].len = floc[jfld].size (); - prc_send[owner].len += floc[jfld].size (); - } - -printf (" dist.nb_pts ()[lprc] = %8d\n", dist.nb_pts ()[lprc]); - - integrate (fld_send); - integrate (prc_send); - - // Pack send buffer - - std::vector buf_send (fld_send.back ().off); - - for (int jfld = 0; jfld < nfld; jfld++) - floc[jfld].pack (&buf_send[fld_send[jfld].off]); - - // RECV - - std::vector prc_recv (nprc + 1); - std::vector fld_recv (nfld + 1); - - for (int jfld = 0; jfld < nfld; jfld++) - if (lprc == fglo[jfld].owner ()) - fld_recv[jfld].len = fglo[jfld].dlen (); - - integrate (fld_recv); - - for (int iprc = 0; iprc < nprc; iprc++) - prc_recv[iprc].len = dist.nb_pts ()[iprc] * fld_recv.back ().off; - - integrate (prc_recv); - - std::vector buf_recv (prc_recv.back ().off); - - std::vector rqr; - - for (int iprc = 0; iprc < nprc; iprc++) - if (prc_recv[iprc].len > 0) - rqr.push_back (comm.iReceive (&buf_recv[prc_recv[iprc].off], - prc_recv[iprc].len, iprc, 100)); - - comm.barrier (); - - std::vector rqs; - - for (int iprc = 0; iprc < nprc; iprc++) - if (prc_send[iprc].len > 0) - rqs.push_back (comm.iSend (&buf_send[prc_send[iprc].off], - prc_send[iprc].len, iprc, 100)); - - for (auto & r : rqr) - comm.wait (r); - - for (auto & r : rqs) - comm.wait (r); - - // Unpack RECV buffer - - for (int iprc = 0; iprc < nprc; iprc++) - if (prc_recv[iprc].len > 0) - { - int off = prc_recv[iprc].off; - for (int jfld = 0; jfld < nfld; jfld++) - { - if (fld_recv[jfld].len > 0) - { - for (int jloc = 0, k = 0; jloc < dist.nb_pts ()[iprc]; jloc++) - for (int j = 0; j < fld_recv[jfld].len; j++, k++) - fglo[jfld](mapping.prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; - off += dist.nb_pts ()[iprc] * fglo[jfld].dlen (); - } - } - } -} - - template void prff (const std::string & name, const atlas::FieldSet & sglo) { @@ -262,8 +71,6 @@ void prff (const std::string & name, const atlas::FieldSet & sglo) } } - - }; //----------------------------------------------------------------------------- @@ -352,7 +159,9 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { printf (" dloc.size () = %8d\n", dloc.size ()); printf (" dglo.size () = %8d\n", dglo.size ()); - gather (grid, dist, dloc, dglo); + GatherScatter gs (grid, dist); + + gs.gather (dloc, dglo); prff ("sglo2", sglo2); From f869fd20d1c06395bbc9a6e5e3bdf48d88c8b113 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 20 May 2020 08:43:50 +0000 Subject: [PATCH 11/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 15 ++++++++++----- src/tests/functionspace/ioFieldDesc.h | 5 +++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 162b34bf2..9cecfbdfb 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -93,8 +93,6 @@ void GatherScatter::gather (std::vector & floc, std::vector buf_send (fld_send.back ().off); for (int jfld = 0; jfld < nfld; jfld++) - floc[jfld].pack (&buf_send[fld_send[jfld].off]); + { + auto & f = floc[jfld]; + byte * buffer = &buf_send[fld_send[jfld].off]; + for (int i = 0; i < f.ldim (); i++) + for (int j = 0; j < f.dlen (); j++) + buffer[i*f.dlen ()+j] = f (i, j); + } // RECV @@ -153,12 +157,13 @@ printf (" dist.nb_pts ()[lprc] = %8d\n", dist.nb_pts ()[lprc]); int off = prc_recv[iprc].off; for (int jfld = 0; jfld < nfld; jfld++) { + auto & f = fglo[jfld]; if (fld_recv[jfld].len > 0) { for (int jloc = 0, k = 0; jloc < dist.nb_pts ()[iprc]; jloc++) for (int j = 0; j < fld_recv[jfld].len; j++, k++) - fglo[jfld](prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; - off += dist.nb_pts ()[iprc] * fglo[jfld].dlen (); + f (prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; + off += dist.nb_pts ()[iprc] * f.dlen (); } } } diff --git a/src/tests/functionspace/ioFieldDesc.h b/src/tests/functionspace/ioFieldDesc.h index b7f46a06a..2cdb804ab 100644 --- a/src/tests/functionspace/ioFieldDesc.h +++ b/src/tests/functionspace/ioFieldDesc.h @@ -52,6 +52,11 @@ class ioFieldDesc return _size; } + size_t ldim () const + { + return _ldim; + } + size_t dlen () const { return _dlen; From 1acc57d0068413cb5a5c7d45bff426cc6747ab28 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 20 May 2020 08:57:34 +0000 Subject: [PATCH 12/58] Cleaning --- src/tests/functionspace/test_batchgather.cc | 68 +++++++++------------ 1 file changed, 29 insertions(+), 39 deletions(-) diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index f63724df6..275a7e4e0 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -78,6 +78,8 @@ void prff (const std::string & name, const atlas::FieldSet & sglo) CASE( "test_functionspace_StructuredColumns_batchgather" ) { int nfields = eckit::Resource ("--fields", 3); atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); + bool gather1 (eckit::Resource ("--gather1", false)); + bool gather2 (eckit::Resource ("--gather2", false)); auto & comm = mpi::comm (); int irank = comm.rank (); @@ -92,16 +94,8 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { getprcind (fs, dist, prc, ind); atlas::FieldSet sloc; - atlas::FieldSet sglo1, sglo2; - - { - char tmp[128]; - sprintf (tmp, "prcind.%8.8d.txt", irank); - FILE * fp = fopen (tmp, "w"); - for (int i = 0; i < grid.size (); i++) - fprintf (fp, " %8d > %8d, %8d\n", i, prc[i], ind[i]); - fclose (fp); - } + atlas::FieldSet sglo1; + atlas::FieldSet sglo2; using T = long; @@ -121,6 +115,25 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { return v; }; + auto check = [ind, prc, grid, func, irank] (const atlas::FieldSet & sglo) + { + for (int i = 0; i < sglo.size (); i++) + { + const auto & fglo = sglo[i]; + int owner; + EXPECT (fglo.metadata ().get ("owner", owner)); + if (owner == irank) + { + const auto v = array::make_view (fglo); + for (int j = 0; j < grid.size (); j++) + { + T v1 = v[j], v2 = func (i, prc[j], ind[j]); + EXPECT_EQ (v1, v2); + } + } + } + }; + for (int i = 0; i < nfields; i++) { int owner = i % nproc; @@ -133,9 +146,9 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { v[j] = func (i, irank, j); sloc.add (floc); - Field fglo = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); - fglo.metadata ().set ("owner", owner); - sglo1.add (fglo); + Field fglo1 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); + fglo1.metadata ().set ("owner", owner); + sglo1.add (fglo1); Field fglo2 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); fglo2.metadata ().set ("owner", owner); @@ -143,8 +156,9 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { } - fs.gather (sloc, sglo1); + check (sglo1); + prff ("sglo1", sglo1); { std::vector dloc; @@ -156,43 +170,19 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { for (auto & d : dglo) d.field ().metadata ().get ("owner", d.owner ()); - printf (" dloc.size () = %8d\n", dloc.size ()); - printf (" dglo.size () = %8d\n", dglo.size ()); - GatherScatter gs (grid, dist); gs.gather (dloc, dglo); prff ("sglo2", sglo2); + check (sglo2); } - prff ("sglo1", sglo1); - - auto cmp = [ind, prc, grid, func, irank] (const atlas::FieldSet & sglo) - { - for (int i = 0; i < sglo.size (); i++) - { - const auto & fglo = sglo[i]; - int owner; - EXPECT (fglo.metadata ().get ("owner", owner)); - if (owner == irank) - { - const auto v = array::make_view (fglo); - for (int j = 0; j < grid.size (); j++) - { - T v1 = v[j], v2 = func (i, prc[j], ind[j]); - EXPECT_EQ (v1, v2); - } - } - } - }; - cmp (sglo1); - cmp (sglo2); } From 1f31855ca00881b82df1e873aed5b9f38cf5cf13 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 20 May 2020 09:52:39 +0000 Subject: [PATCH 13/58] Add trace --- src/tests/functionspace/GatherScatter.cc | 115 ++++++++++++-------- src/tests/functionspace/test_batchgather.cc | 74 ++++++++----- 2 files changed, 111 insertions(+), 78 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 9cecfbdfb..a4f9229e1 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -4,6 +4,7 @@ #include "atlas/field.h" #include "atlas/grid.h" #include "atlas/parallel/mpi/mpi.h" +#include "atlas/runtime/Trace.h" namespace { @@ -31,6 +32,9 @@ void integrate (T & v) GatherScatter::GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist) : grid (_grid), dist (_dist) { +ATLAS_TRACE_SCOPE ("GatherScatter::GatherScatter") +{ + nprc = dist.nb_partitions (); std::vector count (nprc); @@ -52,9 +56,13 @@ GatherScatter::GatherScatter (const atlas::StructuredGrid & _grid, const atlas:: } } +} void GatherScatter::gather (std::vector & floc, std::vector & fglo) const { +ATLAS_TRACE_SCOPE ("GatherScatter::gather") +{ + ATLAS_ASSERT (floc.size () == fglo.size ()); size_t nfld = floc.size (); @@ -100,14 +108,18 @@ void GatherScatter::gather (std::vector & floc, std::vector buf_send (fld_send.back ().off); - for (int jfld = 0; jfld < nfld; jfld++) - { - auto & f = floc[jfld]; - byte * buffer = &buf_send[fld_send[jfld].off]; - for (int i = 0; i < f.ldim (); i++) - for (int j = 0; j < f.dlen (); j++) - buffer[i*f.dlen ()+j] = f (i, j); - } + ATLAS_TRACE_SCOPE ("Pack") + { +#pragma omp parallel for + for (int jfld = 0; jfld < nfld; jfld++) + { + auto & f = floc[jfld]; + byte * buffer = &buf_send[fld_send[jfld].off]; + for (int i = 0; i < f.ldim (); i++) + for (int j = 0; j < f.dlen (); j++) + buffer[i*f.dlen ()+j] = f (i, j); + } + } // RECV @@ -127,45 +139,52 @@ void GatherScatter::gather (std::vector & floc, std::vector buf_recv (prc_recv.back ().off); - std::vector rqr; - - for (int iprc = 0; iprc < nprc; iprc++) - if (prc_recv[iprc].len > 0) - rqr.push_back (comm.iReceive (&buf_recv[prc_recv[iprc].off], - prc_recv[iprc].len, iprc, 100)); - - comm.barrier (); - - std::vector rqs; - - for (int iprc = 0; iprc < nprc; iprc++) - if (prc_send[iprc].len > 0) - rqs.push_back (comm.iSend (&buf_send[prc_send[iprc].off], - prc_send[iprc].len, iprc, 100)); - - for (auto & r : rqr) - comm.wait (r); - - for (auto & r : rqs) - comm.wait (r); - - // Unpack RECV buffer - - for (int iprc = 0; iprc < nprc; iprc++) - if (prc_recv[iprc].len > 0) - { - int off = prc_recv[iprc].off; - for (int jfld = 0; jfld < nfld; jfld++) - { - auto & f = fglo[jfld]; - if (fld_recv[jfld].len > 0) - { - for (int jloc = 0, k = 0; jloc < dist.nb_pts ()[iprc]; jloc++) - for (int j = 0; j < fld_recv[jfld].len; j++, k++) - f (prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; - off += dist.nb_pts ()[iprc] * f.dlen (); - } - } - } + ATLAS_TRACE_SCOPE ("SEND/RECV") + { + std::vector rqr; + + for (int iprc = 0; iprc < nprc; iprc++) + if (prc_recv[iprc].len > 0) + rqr.push_back (comm.iReceive (&buf_recv[prc_recv[iprc].off], + prc_recv[iprc].len, iprc, 100)); + + comm.barrier (); + + std::vector rqs; + + for (int iprc = 0; iprc < nprc; iprc++) + if (prc_send[iprc].len > 0) + rqs.push_back (comm.iSend (&buf_send[prc_send[iprc].off], + prc_send[iprc].len, iprc, 100)); + + for (auto & r : rqr) + comm.wait (r); + + for (auto & r : rqs) + comm.wait (r); + } + + ATLAS_TRACE_SCOPE ("Unpack") + { + + for (int iprc = 0; iprc < nprc; iprc++) + if (prc_recv[iprc].len > 0) + { + int off = prc_recv[iprc].off; + for (int jfld = 0; jfld < nfld; jfld++) + { + auto & f = fglo[jfld]; + if (fld_recv[jfld].len > 0) + { + for (int jloc = 0, k = 0; jloc < dist.nb_pts ()[iprc]; jloc++) + for (int j = 0; j < fld_recv[jfld].len; j++, k++) + f (prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; + off += dist.nb_pts ()[iprc] * f.dlen (); + } + } + } + + } +} } diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index 275a7e4e0..70cb48127 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -14,6 +14,7 @@ #include "atlas/functionspace.h" #include "atlas/parallel/mpi/mpi.h" #include "tests/AtlasTestEnvironment.h" +#include "atlas/runtime/Trace.h" #include "GatherScatter.h" #include "ioFieldDesc.h" @@ -75,11 +76,14 @@ void prff (const std::string & name, const atlas::FieldSet & sglo) //----------------------------------------------------------------------------- -CASE( "test_functionspace_StructuredColumns_batchgather" ) { +CASE( "test_gatherscatter" ) +{ int nfields = eckit::Resource ("--fields", 3); atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); bool gather1 (eckit::Resource ("--gather1", false)); bool gather2 (eckit::Resource ("--gather2", false)); + bool debug (eckit::Resource ("--debug", false)); + bool check (eckit::Resource ("--check", false)); auto & comm = mpi::comm (); int irank = comm.rank (); @@ -115,7 +119,7 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { return v; }; - auto check = [ind, prc, grid, func, irank] (const atlas::FieldSet & sglo) + auto checkgather = [ind, prc, grid, func, irank] (const atlas::FieldSet & sglo) { for (int i = 0; i < sglo.size (); i++) { @@ -146,43 +150,53 @@ CASE( "test_functionspace_StructuredColumns_batchgather" ) { v[j] = func (i, irank, j); sloc.add (floc); - Field fglo1 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); - fglo1.metadata ().set ("owner", owner); - sglo1.add (fglo1); + if (gather1) + { + Field fglo1 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); + fglo1.metadata ().set ("owner", owner); + sglo1.add (fglo1); + } - Field fglo2 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); - fglo2.metadata ().set ("owner", owner); - sglo2.add (fglo2); + if (gather2) + { + Field fglo2 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); + fglo2.metadata ().set ("owner", owner); + sglo2.add (fglo2); + } } - fs.gather (sloc, sglo1); - check (sglo1); - prff ("sglo1", sglo1); - - { - std::vector dloc; - std::vector dglo; - - createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); - createIoFieldDescriptors (sglo2, dglo, grid.size ()); - - for (auto & d : dglo) - d.field ().metadata ().get ("owner", d.owner ()); - - GatherScatter gs (grid, dist); - - gs.gather (dloc, dglo); - - - prff ("sglo2", sglo2); - check (sglo2); + if (gather1) + { + ATLAS_TRACE_SCOPE ("test_gather1") + { + fs.gather (sloc, sglo1); + if (check) checkgather (sglo1); + if (debug) prff ("sglo1", sglo1); + } + } - } + if (gather2) + { + ATLAS_TRACE_SCOPE ("test_gather2") + { + std::vector dloc; + std::vector dglo; + createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); + createIoFieldDescriptors (sglo2, dglo, grid.size ()); + + for (auto & d : dglo) + d.field ().metadata ().get ("owner", d.owner ()); + GatherScatter gs (grid, dist); + gs.gather (dloc, dglo); + if (debug) prff ("sglo2", sglo2); + if (check) checkgather (sglo2); + } + } } From d38948f3b2f8592373d637d30be5f7fe2e78529f Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 20 May 2020 14:09:40 +0000 Subject: [PATCH 14/58] Add trace --- .../functionspace/detail/StructuredColumns.cc | 4 ++- src/atlas/parallel/GatherScatter.h | 8 ++++- src/tests/functionspace/GatherScatter.cc | 17 +++++---- src/tests/functionspace/ioFieldDesc.h | 8 +++++ src/tests/functionspace/test_batchgather.cc | 35 +++++++++++++------ 5 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/atlas/functionspace/detail/StructuredColumns.cc b/src/atlas/functionspace/detail/StructuredColumns.cc index 12d037b23..ace85b4d7 100644 --- a/src/atlas/functionspace/detail/StructuredColumns.cc +++ b/src/atlas/functionspace/detail/StructuredColumns.cc @@ -492,7 +492,8 @@ Field StructuredColumns::createField( const Field& other, const eckit::Configura // ---------------------------------------------------------------------------- void StructuredColumns::gather( const FieldSet& local_fieldset, FieldSet& global_fieldset ) const { ATLAS_ASSERT( local_fieldset.size() == global_fieldset.size() ); - + ATLAS_TRACE_SCOPE ("StructuredColumns::gather") + { for ( idx_t f = 0; f < local_fieldset.size(); ++f ) { const Field& loc = local_fieldset[f]; Field& glb = global_fieldset[f]; @@ -524,6 +525,7 @@ void StructuredColumns::gather( const FieldSet& local_fieldset, FieldSet& global throw_Exception( "datatype not supported", Here() ); } } + } } // ---------------------------------------------------------------------------- diff --git a/src/atlas/parallel/GatherScatter.h b/src/atlas/parallel/GatherScatter.h index d39519a91..2084fcebd 100644 --- a/src/atlas/parallel/GatherScatter.h +++ b/src/atlas/parallel/GatherScatter.h @@ -227,15 +227,21 @@ void GatherScatter::gather( parallel::Field lfields[], parallel /// Pack - pack_send_buffer( lfields[jfield], locmap_, loc_buffer.data() ); + ATLAS_TRACE_SCOPE ("Pack") + { + pack_send_buffer( lfields[jfield], locmap_, loc_buffer.data() ); + }; /// Gather ATLAS_TRACE_MPI( GATHER ) { mpi::comm().gatherv( loc_buffer, glb_buffer, glb_counts, glb_displs, root ); } + ATLAS_TRACE_SCOPE ("Unpack") + { /// Unpack if ( myproc == root ) unpack_recv_buffer( glbmap_, glb_buffer.data(), gfields[jfield] ); + } } } diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index a4f9229e1..1618cc9d2 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -170,16 +170,21 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") for (int iprc = 0; iprc < nprc; iprc++) if (prc_recv[iprc].len > 0) { - int off = prc_recv[iprc].off; for (int jfld = 0; jfld < nfld; jfld++) { - auto & f = fglo[jfld]; if (fld_recv[jfld].len > 0) { - for (int jloc = 0, k = 0; jloc < dist.nb_pts ()[iprc]; jloc++) - for (int j = 0; j < fld_recv[jfld].len; j++, k++) - f (prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; - off += dist.nb_pts ()[iprc] * f.dlen (); + const int ngptot = dist.nb_pts ()[iprc]; + const int off = prc_recv[iprc].off + ngptot * fld_recv[jfld].off; + auto & f = fglo[jfld]; +#pragma omp parallel for + for (int jloc = 0; jloc < ngptot; jloc++) + for (int j = 0; j < fld_recv[jfld].len; j++) + { + int k = jloc * fld_recv[jfld].len + j; + f (prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; + } + } } } diff --git a/src/tests/functionspace/ioFieldDesc.h b/src/tests/functionspace/ioFieldDesc.h index 2cdb804ab..02a338695 100644 --- a/src/tests/functionspace/ioFieldDesc.h +++ b/src/tests/functionspace/ioFieldDesc.h @@ -20,6 +20,13 @@ class ioFieldDesc if (_ldim == 0) _ldim = _v.shape (0); _size = _ldim * _v.shape (1); + _contiguous = (_dlen == _v.stride (0)); + } + + + bool contiguous () const + { + return _contiguous; } atlas::array::ArrayView & view () @@ -82,6 +89,7 @@ class ioFieldDesc size_t _ldim; size_t _size; size_t _dlen; + bool _contiguous; }; void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim = 0); diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index 70cb48127..ffccc9430 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -107,20 +107,29 @@ CASE( "test_gatherscatter" ) const int prc_bit = 21, prc_off = ind_off + ind_bit; const int fld_bit = 21, fld_off = prc_off + prc_bit; - ATLAS_ASSERT (fs.sizeOwned () < (1 << ind_bit)); - ATLAS_ASSERT (nproc < (1 << prc_bit)); - ATLAS_ASSERT (nfields < (1 << fld_bit)); + if (check) + { + ATLAS_ASSERT (fs.sizeOwned () < (1 << ind_bit)); + ATLAS_ASSERT (nproc < (1 << prc_bit)); + ATLAS_ASSERT (nfields < (1 << fld_bit)); + } - auto func = [&ind_off,&prc_off,&fld_off] (int fld, int prc, int ind) + auto func = [check,ind_off,prc_off,fld_off] (int fld, int prc, int ind) { - long v = (static_cast (fld) << fld_off) - + (static_cast (prc) << prc_off) - + (static_cast (ind) << ind_off); + long v = 0; + if (check) + { + v = (static_cast (fld) << fld_off) + + (static_cast (prc) << prc_off) + + (static_cast (ind) << ind_off); + } return v; }; auto checkgather = [ind, prc, grid, func, irank] (const atlas::FieldSet & sglo) { + ATLAS_TRACE_SCOPE ("check") + { for (int i = 0; i < sglo.size (); i++) { const auto & fglo = sglo[i]; @@ -136,6 +145,7 @@ CASE( "test_gatherscatter" ) } } } + } }; for (int i = 0; i < nfields; i++) @@ -168,6 +178,10 @@ CASE( "test_gatherscatter" ) if (gather1) { + { + atlas::FieldSet loc, glo; + fs.gather (loc, glo); + } ATLAS_TRACE_SCOPE ("test_gather1") { fs.gather (sloc, sglo1); @@ -178,18 +192,19 @@ CASE( "test_gatherscatter" ) if (gather2) { + GatherScatter gs (grid, dist); ATLAS_TRACE_SCOPE ("test_gather2") { std::vector dloc; std::vector dglo; + ATLAS_TRACE_SCOPE ("create io descriptors") + { createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); createIoFieldDescriptors (sglo2, dglo, grid.size ()); - for (auto & d : dglo) d.field ().metadata ().get ("owner", d.owner ()); - - GatherScatter gs (grid, dist); + } gs.gather (dloc, dglo); From ac624791fe052fd0925e4ad1dc54878eb188d922 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 20 May 2020 20:52:17 +0000 Subject: [PATCH 15/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 79 +++++++++++++++--------- src/tests/functionspace/GatherScatter.h | 12 ++-- 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 1618cc9d2..f93411503 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -27,6 +27,15 @@ void integrate (T & v) v[i].off = v[i-1].off + v[i-1].len; } +template +std::vector grep (I n, F f) +{ + std::vector r (n), g; + std::iota (r.begin (), r.end (), 0); + std::copy_if (r.begin (), r.end (), std::back_inserter (g), f); + return g; +} + }; GatherScatter::GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist) @@ -37,18 +46,18 @@ ATLAS_TRACE_SCOPE ("GatherScatter::GatherScatter") nprc = dist.nb_partitions (); - std::vector count (nprc); - std::vector ind (grid.size ()); + std::vector count (nprc); + std::vector ind (grid.size ()); - for (int i = 0; i < grid.size (); i++) + for (atlas::gidx_t i = 0; i < grid.size (); i++) ind[i] = count[dist.partition (i)]++; max = *std::max_element (count.begin (), count.end ()); - _prcloc2glo.resize (max * nprc, std::numeric_limits::min ()); + _prcloc2glo.resize (max * nprc, std::numeric_limits::min ()); _glo2prcloc.resize (grid.size ()); - for (int i = 0; i < grid.size (); i++) + for (atlas::gidx_t i = 0; i < grid.size (); i++) { _prcloc2glo[max * dist.partition (i) + ind[i]] = i; _glo2prcloc[i].loc = ind[i]; @@ -64,27 +73,28 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") { ATLAS_ASSERT (floc.size () == fglo.size ()); - size_t nfld = floc.size (); + atlas::idx_t nfld = floc.size (); auto & comm = eckit::mpi::comm (); - int nprc = comm.size (); - int lprc = comm.rank (); + atlas::idx_t nprc = comm.size (); + atlas::idx_t lprc = comm.rank (); class offlen_t { public: - size_t off = 0, len = 0; + atlas::gidx_t off = 0, len = 0; }; - size_t ldim = dist.nb_pts ()[lprc]; + atlas::idx_t ldim = dist.nb_pts ()[lprc]; // Sort fields by owner - std::vector isort (nfld); + std::vector isort (nfld); std::iota (std::begin (isort), std::end (isort), 0); std::sort (std::begin (isort), std::end (isort), - [&fglo] (int a, int b) { return fglo[a].owner () < fglo[b].owner (); }); + [&fglo] (atlas::idx_t a, atlas::idx_t b) + { return fglo[a].owner () < fglo[b].owner (); }); floc = reorder (floc, isort); fglo = reorder (fglo, isort); @@ -94,9 +104,9 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") std::vector fld_send (nfld + 1); std::vector prc_send (nprc + 1); - for (int jfld = 0; jfld < nfld; jfld++) + for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { - int owner = fglo[jfld].owner (); + atlas::idx_t owner = fglo[jfld].owner (); fld_send[jfld].len = floc[jfld].size (); prc_send[owner].len += floc[jfld].size (); } @@ -111,11 +121,11 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") ATLAS_TRACE_SCOPE ("Pack") { #pragma omp parallel for - for (int jfld = 0; jfld < nfld; jfld++) + for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { auto & f = floc[jfld]; byte * buffer = &buf_send[fld_send[jfld].off]; - for (int i = 0; i < f.ldim (); i++) + for (atlas::idx_t i = 0; i < f.ldim (); i++) for (int j = 0; j < f.dlen (); j++) buffer[i*f.dlen ()+j] = f (i, j); } @@ -126,13 +136,13 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") std::vector prc_recv (nprc + 1); std::vector fld_recv (nfld + 1); - for (int jfld = 0; jfld < nfld; jfld++) + for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) if (lprc == fglo[jfld].owner ()) fld_recv[jfld].len = fglo[jfld].dlen (); integrate (fld_recv); - for (int iprc = 0; iprc < nprc; iprc++) + for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) prc_recv[iprc].len = dist.nb_pts ()[iprc] * fld_recv.back ().off; integrate (prc_recv); @@ -143,7 +153,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") { std::vector rqr; - for (int iprc = 0; iprc < nprc; iprc++) + for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) if (prc_recv[iprc].len > 0) rqr.push_back (comm.iReceive (&buf_recv[prc_recv[iprc].off], prc_recv[iprc].len, iprc, 100)); @@ -152,7 +162,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") std::vector rqs; - for (int iprc = 0; iprc < nprc; iprc++) + for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) if (prc_send[iprc].len > 0) rqs.push_back (comm.iSend (&buf_send[prc_send[iprc].off], prc_send[iprc].len, iprc, 100)); @@ -166,22 +176,31 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") ATLAS_TRACE_SCOPE ("Unpack") { - - for (int iprc = 0; iprc < nprc; iprc++) - if (prc_recv[iprc].len > 0) + std::vector prcs = grep (nprc, + [&prc_recv] (atlas::idx_t i) { return prc_recv[i].len > 0; }); + std::vector flds = grep (nfld, + [&fld_recv] (atlas::idx_t i) { return fld_recv[i].len > 0; }); + +// for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) +// if (prc_recv[iprc].len > 0) +// + for (auto iprc : prcs) { - for (int jfld = 0; jfld < nfld; jfld++) + for (auto jfld : flds) { - if (fld_recv[jfld].len > 0) +// for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) +// { +// if (fld_recv[jfld].len > 0) { - const int ngptot = dist.nb_pts ()[iprc]; - const int off = prc_recv[iprc].off + ngptot * fld_recv[jfld].off; + const atlas::idx_t ngptot = dist.nb_pts ()[iprc]; + const size_t off = prc_recv[iprc].off + ngptot * fld_recv[jfld].off; auto & f = fglo[jfld]; + const size_t len = fld_recv[jfld].len; #pragma omp parallel for - for (int jloc = 0; jloc < ngptot; jloc++) - for (int j = 0; j < fld_recv[jfld].len; j++) + for (atlas::idx_t jloc = 0; jloc < ngptot; jloc++) + for (int j = 0; j < len; j++) { - int k = jloc * fld_recv[jfld].len + j; + size_t k = jloc * fld_recv[jfld].len + j; f (prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; } diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index 24ff52fe8..fe0c54ca7 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -11,13 +11,13 @@ class GatherScatter class locprc_t { public: - int loc = std::numeric_limits::min (); - int prc = std::numeric_limits::min (); + atlas::idx_t loc = std::numeric_limits::min (); + atlas::idx_t prc = std::numeric_limits::min (); }; - int max, nprc; + atlas::idx_t max, nprc; - std::vector _prcloc2glo; + std::vector _prcloc2glo; std::vector _glo2prcloc; const atlas::StructuredGrid & grid; @@ -26,12 +26,12 @@ class GatherScatter public: GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist); - int prcloc2glo (int iprc, int jloc) const + atlas::gidx_t prcloc2glo (atlas::idx_t iprc, atlas::idx_t jloc) const { return _prcloc2glo[iprc * max + jloc]; } - const locprc_t & glo2prcloc (int jglo) const + const locprc_t & glo2prcloc (atlas::gidx_t jglo) const { return _glo2prcloc[jglo]; } From 192cf21489400a4cd78d49b404db4411215e72ec Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 20 May 2020 21:23:54 +0000 Subject: [PATCH 16/58] Try grep function --- src/tests/functionspace/GatherScatter.cc | 23 ++++++++++++--------- src/tests/functionspace/test_batchgather.cc | 3 +++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index f93411503..3007c50de 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -181,17 +181,20 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") std::vector flds = grep (nfld, [&fld_recv] (atlas::idx_t i) { return fld_recv[i].len > 0; }); -// for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) -// if (prc_recv[iprc].len > 0) -// - for (auto iprc : prcs) +#ifdef UNDEF + for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) + if (prc_recv[iprc].len > 0) { - for (auto jfld : flds) + for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { -// for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) -// { -// if (fld_recv[jfld].len > 0) + if (fld_recv[jfld].len > 0) +#endif + + for (int ii = 0; ii < prcs.size (); ii++) + for (int jj = 0; jj < flds.size (); jj++) { + const atlas::idx_t iprc = prcs[ii]; + const atlas::idx_t jfld = flds[jj]; const atlas::idx_t ngptot = dist.nb_pts ()[iprc]; const size_t off = prc_recv[iprc].off + ngptot * fld_recv[jfld].off; auto & f = fglo[jfld]; @@ -205,10 +208,10 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") } } - } - } } + + } } diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index ffccc9430..326fce706 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -213,6 +213,9 @@ CASE( "test_gatherscatter" ) } } + // Avoid Atlas barrier + comm.barrier (); + } From fbb469928e9b720cb0f4e3617b1aa0a50f640d84 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 06:20:38 +0000 Subject: [PATCH 17/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 78 ++++++++++----------- src/tests/functionspace/test_batchgather.cc | 3 +- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 3007c50de..f8c324f46 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -101,22 +101,38 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") // SEND - std::vector fld_send (nfld + 1); - std::vector prc_send (nprc + 1); + std::vector fld_loc (nfld + 1); + std::vector prc_loc (nprc + 1); for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { atlas::idx_t owner = fglo[jfld].owner (); - fld_send[jfld].len = floc[jfld].size (); - prc_send[owner].len += floc[jfld].size (); + fld_loc[jfld].len = floc[jfld].size (); + prc_loc[owner].len += floc[jfld].size (); } - integrate (fld_send); - integrate (prc_send); + integrate (fld_loc); + integrate (prc_loc); + + // RECV + + std::vector prc_glo (nprc + 1); + std::vector fld_glo (nfld + 1); + + for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) + if (lprc == fglo[jfld].owner ()) + fld_glo[jfld].len = fglo[jfld].dlen (); + + integrate (fld_glo); + + for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) + prc_glo[iprc].len = dist.nb_pts ()[iprc] * fld_glo.back ().off; + + integrate (prc_glo); // Pack send buffer - std::vector buf_send (fld_send.back ().off); + std::vector buf_loc (fld_loc.back ().off); ATLAS_TRACE_SCOPE ("Pack") { @@ -124,48 +140,32 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { auto & f = floc[jfld]; - byte * buffer = &buf_send[fld_send[jfld].off]; + byte * buffer = &buf_loc[fld_loc[jfld].off]; for (atlas::idx_t i = 0; i < f.ldim (); i++) for (int j = 0; j < f.dlen (); j++) buffer[i*f.dlen ()+j] = f (i, j); } } - // RECV - - std::vector prc_recv (nprc + 1); - std::vector fld_recv (nfld + 1); - - for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) - if (lprc == fglo[jfld].owner ()) - fld_recv[jfld].len = fglo[jfld].dlen (); - - integrate (fld_recv); - - for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - prc_recv[iprc].len = dist.nb_pts ()[iprc] * fld_recv.back ().off; - - integrate (prc_recv); - - std::vector buf_recv (prc_recv.back ().off); + std::vector buf_glo (prc_glo.back ().off); ATLAS_TRACE_SCOPE ("SEND/RECV") { std::vector rqr; for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (prc_recv[iprc].len > 0) - rqr.push_back (comm.iReceive (&buf_recv[prc_recv[iprc].off], - prc_recv[iprc].len, iprc, 100)); + if (prc_glo[iprc].len > 0) + rqr.push_back (comm.iReceive (&buf_glo[prc_glo[iprc].off], + prc_glo[iprc].len, iprc, 100)); comm.barrier (); std::vector rqs; for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (prc_send[iprc].len > 0) - rqs.push_back (comm.iSend (&buf_send[prc_send[iprc].off], - prc_send[iprc].len, iprc, 100)); + if (prc_loc[iprc].len > 0) + rqs.push_back (comm.iSend (&buf_loc[prc_loc[iprc].off], + prc_loc[iprc].len, iprc, 100)); for (auto & r : rqr) comm.wait (r); @@ -177,17 +177,17 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") ATLAS_TRACE_SCOPE ("Unpack") { std::vector prcs = grep (nprc, - [&prc_recv] (atlas::idx_t i) { return prc_recv[i].len > 0; }); + [&prc_glo] (atlas::idx_t i) { return prc_glo[i].len > 0; }); std::vector flds = grep (nfld, - [&fld_recv] (atlas::idx_t i) { return fld_recv[i].len > 0; }); + [&fld_glo] (atlas::idx_t i) { return fld_glo[i].len > 0; }); #ifdef UNDEF for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (prc_recv[iprc].len > 0) + if (prc_glo[iprc].len > 0) { for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { - if (fld_recv[jfld].len > 0) + if (fld_glo[jfld].len > 0) #endif for (int ii = 0; ii < prcs.size (); ii++) @@ -196,15 +196,15 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") const atlas::idx_t iprc = prcs[ii]; const atlas::idx_t jfld = flds[jj]; const atlas::idx_t ngptot = dist.nb_pts ()[iprc]; - const size_t off = prc_recv[iprc].off + ngptot * fld_recv[jfld].off; + const size_t off = prc_glo[iprc].off + ngptot * fld_glo[jfld].off; auto & f = fglo[jfld]; - const size_t len = fld_recv[jfld].len; + const size_t len = fld_glo[jfld].len; #pragma omp parallel for for (atlas::idx_t jloc = 0; jloc < ngptot; jloc++) for (int j = 0; j < len; j++) { - size_t k = jloc * fld_recv[jfld].len + j; - f (prcloc2glo (iprc, jloc), j) = buf_recv[off+k]; + size_t k = jloc * fld_glo[jfld].len + j; + f (prcloc2glo (iprc, jloc), j) = buf_glo[off+k]; } } diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index 326fce706..2ca2ece8b 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -95,7 +95,8 @@ CASE( "test_gatherscatter" ) std::vector prc, ind; - getprcind (fs, dist, prc, ind); + if (check) + getprcind (fs, dist, prc, ind); atlas::FieldSet sloc; atlas::FieldSet sglo1; From 8e3671f375ebed1843e32b2dbab07578ecf3b414 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 07:02:03 +0000 Subject: [PATCH 18/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 16 +++++----------- src/tests/functionspace/GatherScatter.h | 13 ++++++++++++- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index f8c324f46..4ae4ff0c5 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -67,7 +67,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::GatherScatter") } } -void GatherScatter::gather (std::vector & floc, std::vector & fglo) const +void GatherScatter::gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const { ATLAS_TRACE_SCOPE ("GatherScatter::gather") { @@ -79,12 +79,6 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") atlas::idx_t nprc = comm.size (); atlas::idx_t lprc = comm.rank (); - class offlen_t - { - public: - atlas::gidx_t off = 0, len = 0; - }; - atlas::idx_t ldim = dist.nb_pts ()[lprc]; // Sort fields by owner @@ -101,8 +95,8 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") // SEND - std::vector fld_loc (nfld + 1); - std::vector prc_loc (nprc + 1); + offlen_v fld_loc (nfld + 1); + offlen_v prc_loc (nprc + 1); for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { @@ -116,8 +110,8 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") // RECV - std::vector prc_glo (nprc + 1); - std::vector fld_glo (nfld + 1); + offlen_v prc_glo (nprc + 1); + offlen_v fld_glo (nfld + 1); for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) if (lprc == fglo[jfld].owner ()) diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index fe0c54ca7..004a177fe 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -15,6 +15,15 @@ class GatherScatter atlas::idx_t prc = std::numeric_limits::min (); }; + class offlen_t + { + public: + atlas::gidx_t off = 0, len = 0; + }; + + using offlen_v = std::vector; + using ioFieldDesc_v = std::vector; + atlas::idx_t max, nprc; std::vector _prcloc2glo; @@ -26,6 +35,9 @@ class GatherScatter public: GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist); + void gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const; + +private: atlas::gidx_t prcloc2glo (atlas::idx_t iprc, atlas::idx_t jloc) const { return _prcloc2glo[iprc * max + jloc]; @@ -36,7 +48,6 @@ class GatherScatter return _glo2prcloc[jglo]; } - void gather (std::vector & floc, std::vector & fglo) const; }; From b7d59aa1522dfe63e7c8e516255c7e988c3d49d9 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 07:05:51 +0000 Subject: [PATCH 19/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 4ae4ff0c5..32dde92d7 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -93,6 +93,9 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") floc = reorder (floc, isort); fglo = reorder (fglo, isort); + for (int jfld = 0; jfld < nfld; jfld++) + floc[jfld].owner () = fglo[jfld].owner (); + // SEND offlen_v fld_loc (nfld + 1); From 01790454668673dc7adaf7967146832a62ac8d50 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 07:06:48 +0000 Subject: [PATCH 20/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 32dde92d7..daf0c415e 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -103,7 +103,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { - atlas::idx_t owner = fglo[jfld].owner (); + atlas::idx_t owner = floc[jfld].owner (); fld_loc[jfld].len = floc[jfld].size (); prc_loc[owner].len += floc[jfld].size (); } From e894b5a07563b5c27df6c41b8af4e1f0a936a094 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 07:12:45 +0000 Subject: [PATCH 21/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 30 +++++++++++++++--------- src/tests/functionspace/GatherScatter.h | 3 ++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index daf0c415e..99cc54575 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -67,19 +67,10 @@ ATLAS_TRACE_SCOPE ("GatherScatter::GatherScatter") } } -void GatherScatter::gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const -{ -ATLAS_TRACE_SCOPE ("GatherScatter::gather") +void GatherScatter::reOrderFields (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const { - ATLAS_ASSERT (floc.size () == fglo.size ()); - atlas::idx_t nfld = floc.size (); - - auto & comm = eckit::mpi::comm (); - atlas::idx_t nprc = comm.size (); - atlas::idx_t lprc = comm.rank (); - - atlas::idx_t ldim = dist.nb_pts ()[lprc]; + atlas::idx_t nfld = fglo.size (); // Sort fields by owner @@ -96,6 +87,23 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") for (int jfld = 0; jfld < nfld; jfld++) floc[jfld].owner () = fglo[jfld].owner (); +} + +void GatherScatter::gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const +{ +ATLAS_TRACE_SCOPE ("GatherScatter::gather") +{ + + ATLAS_ASSERT (floc.size () == fglo.size ()); + atlas::idx_t nfld = floc.size (); + + auto & comm = eckit::mpi::comm (); + atlas::idx_t nprc = comm.size (); + atlas::idx_t lprc = comm.rank (); + atlas::idx_t ldim = dist.nb_pts ()[lprc]; + + reOrderFields (floc, fglo); + // SEND offlen_v fld_loc (nfld + 1); diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index 004a177fe..ac70b3137 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -48,7 +48,8 @@ class GatherScatter return _glo2prcloc[jglo]; } - + void reOrderFields (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const; + }; From 5fd517284c446ddb7d941c04736e683c230666ec Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 07:17:51 +0000 Subject: [PATCH 22/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 24 +++++++++++++----------- src/tests/functionspace/GatherScatter.h | 8 ++++++++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 99cc54575..9ef208e7c 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -106,18 +106,20 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") // SEND - offlen_v fld_loc (nfld + 1); - offlen_v prc_loc (nprc + 1); + fldprc_t loc; + + loc.fld.resize (nfld + 1); + loc.prc.resize (nprc + 1); for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { atlas::idx_t owner = floc[jfld].owner (); - fld_loc[jfld].len = floc[jfld].size (); - prc_loc[owner].len += floc[jfld].size (); + loc.fld[jfld].len = floc[jfld].size (); + loc.prc[owner].len += floc[jfld].size (); } - integrate (fld_loc); - integrate (prc_loc); + integrate (loc.fld); + integrate (loc.prc); // RECV @@ -137,7 +139,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") // Pack send buffer - std::vector buf_loc (fld_loc.back ().off); + std::vector buf_loc (loc.fld.back ().off); ATLAS_TRACE_SCOPE ("Pack") { @@ -145,7 +147,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { auto & f = floc[jfld]; - byte * buffer = &buf_loc[fld_loc[jfld].off]; + byte * buffer = &buf_loc[loc.fld[jfld].off]; for (atlas::idx_t i = 0; i < f.ldim (); i++) for (int j = 0; j < f.dlen (); j++) buffer[i*f.dlen ()+j] = f (i, j); @@ -168,9 +170,9 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") std::vector rqs; for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (prc_loc[iprc].len > 0) - rqs.push_back (comm.iSend (&buf_loc[prc_loc[iprc].off], - prc_loc[iprc].len, iprc, 100)); + if (loc.prc[iprc].len > 0) + rqs.push_back (comm.iSend (&buf_loc[loc.prc[iprc].off], + loc.prc[iprc].len, iprc, 100)); for (auto & r : rqr) comm.wait (r); diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index ac70b3137..565c93aee 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -22,6 +22,14 @@ class GatherScatter }; using offlen_v = std::vector; + + class fldprc_t + { + public: + offlen_v prc; + offlen_v fld; + }; + using ioFieldDesc_v = std::vector; atlas::idx_t max, nprc; From eb2980d9aec7b37a566f95baf856004e030b5c16 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 07:20:39 +0000 Subject: [PATCH 23/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 36 +++++++++++++----------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 9ef208e7c..160edfeac 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -123,19 +123,21 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") // RECV - offlen_v prc_glo (nprc + 1); - offlen_v fld_glo (nfld + 1); + fldprc_t glo; + + glo.prc.resize (nprc + 1); + glo.fld.resize (nfld + 1); for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) if (lprc == fglo[jfld].owner ()) - fld_glo[jfld].len = fglo[jfld].dlen (); + glo.fld[jfld].len = fglo[jfld].dlen (); - integrate (fld_glo); + integrate (glo.fld); for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - prc_glo[iprc].len = dist.nb_pts ()[iprc] * fld_glo.back ().off; + glo.prc[iprc].len = dist.nb_pts ()[iprc] * glo.fld.back ().off; - integrate (prc_glo); + integrate (glo.prc); // Pack send buffer @@ -154,16 +156,16 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") } } - std::vector buf_glo (prc_glo.back ().off); + std::vector buf_glo (glo.prc.back ().off); ATLAS_TRACE_SCOPE ("SEND/RECV") { std::vector rqr; for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (prc_glo[iprc].len > 0) - rqr.push_back (comm.iReceive (&buf_glo[prc_glo[iprc].off], - prc_glo[iprc].len, iprc, 100)); + if (glo.prc[iprc].len > 0) + rqr.push_back (comm.iReceive (&buf_glo[glo.prc[iprc].off], + glo.prc[iprc].len, iprc, 100)); comm.barrier (); @@ -184,17 +186,17 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") ATLAS_TRACE_SCOPE ("Unpack") { std::vector prcs = grep (nprc, - [&prc_glo] (atlas::idx_t i) { return prc_glo[i].len > 0; }); + [&glo] (atlas::idx_t i) { return glo.prc[i].len > 0; }); std::vector flds = grep (nfld, - [&fld_glo] (atlas::idx_t i) { return fld_glo[i].len > 0; }); + [&glo] (atlas::idx_t i) { return glo.fld[i].len > 0; }); #ifdef UNDEF for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (prc_glo[iprc].len > 0) + if (glo.prc[iprc].len > 0) { for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { - if (fld_glo[jfld].len > 0) + if (glo.fld[jfld].len > 0) #endif for (int ii = 0; ii < prcs.size (); ii++) @@ -203,14 +205,14 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") const atlas::idx_t iprc = prcs[ii]; const atlas::idx_t jfld = flds[jj]; const atlas::idx_t ngptot = dist.nb_pts ()[iprc]; - const size_t off = prc_glo[iprc].off + ngptot * fld_glo[jfld].off; + const size_t off = glo.prc[iprc].off + ngptot * glo.fld[jfld].off; auto & f = fglo[jfld]; - const size_t len = fld_glo[jfld].len; + const size_t len = glo.fld[jfld].len; #pragma omp parallel for for (atlas::idx_t jloc = 0; jloc < ngptot; jloc++) for (int j = 0; j < len; j++) { - size_t k = jloc * fld_glo[jfld].len + j; + size_t k = jloc * glo.fld[jfld].len + j; f (prcloc2glo (iprc, jloc), j) = buf_glo[off+k]; } From d319595a6f2c9f3e2d5b8437f222a9665be9043a Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 08:02:59 +0000 Subject: [PATCH 24/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 60 ++++++++++++------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 160edfeac..d413ff7db 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -106,42 +106,42 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") // SEND - fldprc_t loc; + fldprc_t tloc; - loc.fld.resize (nfld + 1); - loc.prc.resize (nprc + 1); + tloc.fld.resize (nfld + 1); + tloc.prc.resize (nprc + 1); for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { atlas::idx_t owner = floc[jfld].owner (); - loc.fld[jfld].len = floc[jfld].size (); - loc.prc[owner].len += floc[jfld].size (); + tloc.fld[jfld].len = floc[jfld].size (); + tloc.prc[owner].len += floc[jfld].size (); } - integrate (loc.fld); - integrate (loc.prc); + integrate (tloc.fld); + integrate (tloc.prc); // RECV - fldprc_t glo; + fldprc_t tglo; - glo.prc.resize (nprc + 1); - glo.fld.resize (nfld + 1); + tglo.prc.resize (nprc + 1); + tglo.fld.resize (nfld + 1); for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) if (lprc == fglo[jfld].owner ()) - glo.fld[jfld].len = fglo[jfld].dlen (); + tglo.fld[jfld].len = fglo[jfld].dlen (); - integrate (glo.fld); + integrate (tglo.fld); for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - glo.prc[iprc].len = dist.nb_pts ()[iprc] * glo.fld.back ().off; + tglo.prc[iprc].len = dist.nb_pts ()[iprc] * tglo.fld.back ().off; - integrate (glo.prc); + integrate (tglo.prc); // Pack send buffer - std::vector buf_loc (loc.fld.back ().off); + std::vector buf_loc (tloc.fld.back ().off); ATLAS_TRACE_SCOPE ("Pack") { @@ -149,32 +149,32 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { auto & f = floc[jfld]; - byte * buffer = &buf_loc[loc.fld[jfld].off]; + byte * buffer = &buf_loc[tloc.fld[jfld].off]; for (atlas::idx_t i = 0; i < f.ldim (); i++) for (int j = 0; j < f.dlen (); j++) buffer[i*f.dlen ()+j] = f (i, j); } } - std::vector buf_glo (glo.prc.back ().off); + std::vector buf_glo (tglo.prc.back ().off); ATLAS_TRACE_SCOPE ("SEND/RECV") { std::vector rqr; for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (glo.prc[iprc].len > 0) - rqr.push_back (comm.iReceive (&buf_glo[glo.prc[iprc].off], - glo.prc[iprc].len, iprc, 100)); + if (tglo.prc[iprc].len > 0) + rqr.push_back (comm.iReceive (&buf_glo[tglo.prc[iprc].off], + tglo.prc[iprc].len, iprc, 100)); comm.barrier (); std::vector rqs; for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (loc.prc[iprc].len > 0) - rqs.push_back (comm.iSend (&buf_loc[loc.prc[iprc].off], - loc.prc[iprc].len, iprc, 100)); + if (tloc.prc[iprc].len > 0) + rqs.push_back (comm.iSend (&buf_loc[tloc.prc[iprc].off], + tloc.prc[iprc].len, iprc, 100)); for (auto & r : rqr) comm.wait (r); @@ -186,17 +186,17 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") ATLAS_TRACE_SCOPE ("Unpack") { std::vector prcs = grep (nprc, - [&glo] (atlas::idx_t i) { return glo.prc[i].len > 0; }); + [&tglo] (atlas::idx_t i) { return tglo.prc[i].len > 0; }); std::vector flds = grep (nfld, - [&glo] (atlas::idx_t i) { return glo.fld[i].len > 0; }); + [&tglo] (atlas::idx_t i) { return tglo.fld[i].len > 0; }); #ifdef UNDEF for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (glo.prc[iprc].len > 0) + if (tglo.prc[iprc].len > 0) { for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { - if (glo.fld[jfld].len > 0) + if (tglo.fld[jfld].len > 0) #endif for (int ii = 0; ii < prcs.size (); ii++) @@ -205,14 +205,14 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") const atlas::idx_t iprc = prcs[ii]; const atlas::idx_t jfld = flds[jj]; const atlas::idx_t ngptot = dist.nb_pts ()[iprc]; - const size_t off = glo.prc[iprc].off + ngptot * glo.fld[jfld].off; + const size_t off = tglo.prc[iprc].off + ngptot * tglo.fld[jfld].off; auto & f = fglo[jfld]; - const size_t len = glo.fld[jfld].len; + const size_t len = tglo.fld[jfld].len; #pragma omp parallel for for (atlas::idx_t jloc = 0; jloc < ngptot; jloc++) for (int j = 0; j < len; j++) { - size_t k = jloc * glo.fld[jfld].len + j; + size_t k = jloc * tglo.fld[jfld].len + j; f (prcloc2glo (iprc, jloc), j) = buf_glo[off+k]; } From af519047648b93de07f5b21749aedc75e6ce8694 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 08:06:56 +0000 Subject: [PATCH 25/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 33 +++++++++++++++--------- src/tests/functionspace/GatherScatter.h | 1 + 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index d413ff7db..7986a6e10 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -89,6 +89,26 @@ void GatherScatter::reOrderFields (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) c } +void GatherScatter::computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) const +{ + auto & comm = eckit::mpi::comm (); + atlas::idx_t nprc = comm.size (); + atlas::idx_t nfld = floc.size (); + + tloc.fld.resize (nfld + 1); + tloc.prc.resize (nprc + 1); + + for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) + { + atlas::idx_t owner = floc[jfld].owner (); + tloc.fld[jfld].len = floc[jfld].size (); + tloc.prc[owner].len += floc[jfld].size (); + } + + integrate (tloc.fld); + integrate (tloc.prc); +} + void GatherScatter::gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const { ATLAS_TRACE_SCOPE ("GatherScatter::gather") @@ -108,18 +128,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") fldprc_t tloc; - tloc.fld.resize (nfld + 1); - tloc.prc.resize (nprc + 1); - - for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) - { - atlas::idx_t owner = floc[jfld].owner (); - tloc.fld[jfld].len = floc[jfld].size (); - tloc.prc[owner].len += floc[jfld].size (); - } - - integrate (tloc.fld); - integrate (tloc.prc); + computeTLoc (floc, tloc); // RECV diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index 565c93aee..615d06d58 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -57,6 +57,7 @@ class GatherScatter } void reOrderFields (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const; + void computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) const; }; From 457d40331132c83b7d23ee638175b25cc8e6c60a Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 08:09:47 +0000 Subject: [PATCH 26/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 36 +++++++++++++++--------- src/tests/functionspace/GatherScatter.h | 1 + 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 7986a6e10..c27a43cdd 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -109,6 +109,28 @@ void GatherScatter::computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) co integrate (tloc.prc); } +void GatherScatter::computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) const +{ + auto & comm = eckit::mpi::comm (); + atlas::idx_t nprc = comm.size (); + atlas::idx_t lprc = comm.rank (); + atlas::idx_t nfld = fglo.size (); + + tglo.prc.resize (nprc + 1); + tglo.fld.resize (nfld + 1); + + for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) + if (lprc == fglo[jfld].owner ()) + tglo.fld[jfld].len = fglo[jfld].dlen (); + + integrate (tglo.fld); + + for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) + tglo.prc[iprc].len = dist.nb_pts ()[iprc] * tglo.fld.back ().off; + + integrate (tglo.prc); +} + void GatherScatter::gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const { ATLAS_TRACE_SCOPE ("GatherScatter::gather") @@ -134,19 +156,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") fldprc_t tglo; - tglo.prc.resize (nprc + 1); - tglo.fld.resize (nfld + 1); - - for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) - if (lprc == fglo[jfld].owner ()) - tglo.fld[jfld].len = fglo[jfld].dlen (); - - integrate (tglo.fld); - - for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - tglo.prc[iprc].len = dist.nb_pts ()[iprc] * tglo.fld.back ().off; - - integrate (tglo.prc); + computeTGlo (fglo, tglo); // Pack send buffer diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index 615d06d58..5b593e839 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -58,6 +58,7 @@ class GatherScatter void reOrderFields (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const; void computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) const; + void computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) const; }; From bb184adbcdfaa697371f0ffb18f72911c2951ca4 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 08:13:10 +0000 Subject: [PATCH 27/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index c27a43cdd..dbfad5e6d 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -135,8 +135,6 @@ void GatherScatter::gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const { ATLAS_TRACE_SCOPE ("GatherScatter::gather") { - - ATLAS_ASSERT (floc.size () == fglo.size ()); atlas::idx_t nfld = floc.size (); auto & comm = eckit::mpi::comm (); @@ -146,16 +144,9 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") reOrderFields (floc, fglo); - // SEND - - fldprc_t tloc; + fldprc_t tloc, tglo; computeTLoc (floc, tloc); - - // RECV - - fldprc_t tglo; - computeTGlo (fglo, tglo); // Pack send buffer From 0efd0d853573f3f9bf1fbfe3efcac817cd0782ba Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 08:19:24 +0000 Subject: [PATCH 28/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 36 +++++++++++++++--------- src/tests/functionspace/GatherScatter.h | 2 ++ src/tests/functionspace/ioFieldDesc.h | 5 ++++ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index dbfad5e6d..9fe43fda7 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -131,13 +131,32 @@ void GatherScatter::computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) co integrate (tglo.prc); } +void GatherScatter::processLocBuffer (const ioFieldDesc_v & floc, const fldprc_t & tloc, + std::vector & buf_loc) const +{ + atlas::idx_t nfld = floc.size (); + + ATLAS_TRACE_SCOPE ("GatherScatter::processLocBuffer") + { +#pragma omp parallel for + for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) + { + auto & f = floc[jfld]; + byte * buffer = &buf_loc[tloc.fld[jfld].off]; + for (atlas::idx_t i = 0; i < f.ldim (); i++) + for (int j = 0; j < f.dlen (); j++) + buffer[i*f.dlen ()+j] = f (i, j); + } + } + +} + void GatherScatter::gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const { ATLAS_TRACE_SCOPE ("GatherScatter::gather") { - atlas::idx_t nfld = floc.size (); - auto & comm = eckit::mpi::comm (); + atlas::idx_t nfld = floc.size (); atlas::idx_t nprc = comm.size (); atlas::idx_t lprc = comm.rank (); atlas::idx_t ldim = dist.nb_pts ()[lprc]; @@ -153,18 +172,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") std::vector buf_loc (tloc.fld.back ().off); - ATLAS_TRACE_SCOPE ("Pack") - { -#pragma omp parallel for - for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) - { - auto & f = floc[jfld]; - byte * buffer = &buf_loc[tloc.fld[jfld].off]; - for (atlas::idx_t i = 0; i < f.ldim (); i++) - for (int j = 0; j < f.dlen (); j++) - buffer[i*f.dlen ()+j] = f (i, j); - } - } + processLocBuffer (floc, tloc, buf_loc); std::vector buf_glo (tglo.prc.back ().off); diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index 5b593e839..5496a26cb 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -59,6 +59,8 @@ class GatherScatter void reOrderFields (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const; void computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) const; void computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) const; + void processLocBuffer (const ioFieldDesc_v & floc, const fldprc_t & tloc, + std::vector & buf_loc) const; }; diff --git a/src/tests/functionspace/ioFieldDesc.h b/src/tests/functionspace/ioFieldDesc.h index 02a338695..1348ec0bc 100644 --- a/src/tests/functionspace/ioFieldDesc.h +++ b/src/tests/functionspace/ioFieldDesc.h @@ -81,6 +81,11 @@ class ioFieldDesc return _v (i, j); } + byte operator () (int i, int j) const + { + return _v (i, j); + } + private: atlas::array::ArrayView _v; const std::vector _ind; From 61b1dc0e8ea01fb1ac2be5bead3fd7a3149f3967 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 09:56:48 +0000 Subject: [PATCH 29/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 89 +++++++++++++----------- src/tests/functionspace/GatherScatter.h | 6 +- 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 9fe43fda7..2633356da 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -132,7 +132,7 @@ void GatherScatter::computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) co } void GatherScatter::processLocBuffer (const ioFieldDesc_v & floc, const fldprc_t & tloc, - std::vector & buf_loc) const + byte_v & buf_loc) const { atlas::idx_t nfld = floc.size (); @@ -151,6 +151,51 @@ void GatherScatter::processLocBuffer (const ioFieldDesc_v & floc, const fldprc_t } +void GatherScatter::processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tglo, + const byte_v & buf_glo) const +{ + auto & comm = eckit::mpi::comm (); + atlas::idx_t nfld = fglo.size (); + atlas::idx_t nprc = comm.size (); + + ATLAS_TRACE_SCOPE ("GatherScatter::processGloBuffer") + { + std::vector prcs = grep (nprc, + [&tglo] (atlas::idx_t i) { return tglo.prc[i].len > 0; }); + std::vector flds = grep (nfld, + [&tglo] (atlas::idx_t i) { return tglo.fld[i].len > 0; }); + +#ifdef UNDEF + for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) + if (tglo.prc[iprc].len > 0) + { + for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) + { + if (tglo.fld[jfld].len > 0) +#endif + + for (int ii = 0; ii < prcs.size (); ii++) + for (int jj = 0; jj < flds.size (); jj++) + { + const atlas::idx_t iprc = prcs[ii]; + const atlas::idx_t jfld = flds[jj]; + const atlas::idx_t ngptot = dist.nb_pts ()[iprc]; + const size_t off = tglo.prc[iprc].off + ngptot * tglo.fld[jfld].off; + auto & f = fglo[jfld]; + const size_t len = tglo.fld[jfld].len; +#pragma omp parallel for + for (atlas::idx_t jloc = 0; jloc < ngptot; jloc++) + for (int j = 0; j < len; j++) + { + size_t k = jloc * tglo.fld[jfld].len + j; + f (prcloc2glo (iprc, jloc), j) = buf_glo[off+k]; + } + + } + + } +} + void GatherScatter::gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const { ATLAS_TRACE_SCOPE ("GatherScatter::gather") @@ -170,11 +215,11 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") // Pack send buffer - std::vector buf_loc (tloc.fld.back ().off); + byte_v buf_loc (tloc.fld.back ().off); processLocBuffer (floc, tloc, buf_loc); - std::vector buf_glo (tglo.prc.back ().off); + byte_v buf_glo (tglo.prc.back ().off); ATLAS_TRACE_SCOPE ("SEND/RECV") { @@ -201,43 +246,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") comm.wait (r); } - ATLAS_TRACE_SCOPE ("Unpack") - { - std::vector prcs = grep (nprc, - [&tglo] (atlas::idx_t i) { return tglo.prc[i].len > 0; }); - std::vector flds = grep (nfld, - [&tglo] (atlas::idx_t i) { return tglo.fld[i].len > 0; }); - -#ifdef UNDEF - for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (tglo.prc[iprc].len > 0) - { - for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) - { - if (tglo.fld[jfld].len > 0) -#endif - - for (int ii = 0; ii < prcs.size (); ii++) - for (int jj = 0; jj < flds.size (); jj++) - { - const atlas::idx_t iprc = prcs[ii]; - const atlas::idx_t jfld = flds[jj]; - const atlas::idx_t ngptot = dist.nb_pts ()[iprc]; - const size_t off = tglo.prc[iprc].off + ngptot * tglo.fld[jfld].off; - auto & f = fglo[jfld]; - const size_t len = tglo.fld[jfld].len; -#pragma omp parallel for - for (atlas::idx_t jloc = 0; jloc < ngptot; jloc++) - for (int j = 0; j < len; j++) - { - size_t k = jloc * tglo.fld[jfld].len + j; - f (prcloc2glo (iprc, jloc), j) = buf_glo[off+k]; - } - - } - - } - + processGloBuffer (fglo, tglo, buf_glo); } } diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index 5496a26cb..88d51fb03 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -32,6 +32,8 @@ class GatherScatter using ioFieldDesc_v = std::vector; + using byte_v = std::vector; + atlas::idx_t max, nprc; std::vector _prcloc2glo; @@ -60,7 +62,9 @@ class GatherScatter void computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) const; void computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) const; void processLocBuffer (const ioFieldDesc_v & floc, const fldprc_t & tloc, - std::vector & buf_loc) const; + byte_v & buf_loc) const; + void processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tglo, + const byte_v & buf_glo) const; }; From ae522ab5048afa77262af44c1e0133a7620dabf0 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 10:30:24 +0000 Subject: [PATCH 30/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 24 ++++++++++++++---------- src/tests/functionspace/GatherScatter.h | 11 +++++++---- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 2633356da..d1387cea2 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -131,8 +131,10 @@ void GatherScatter::computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) co integrate (tglo.prc); } -void GatherScatter::processLocBuffer (const ioFieldDesc_v & floc, const fldprc_t & tloc, - byte_v & buf_loc) const + +template +void GatherScatter::processLocBuffer (ioFieldDesc_v & floc, const fldprc_t & tloc, + byte_v & buf_loc, A a) const { atlas::idx_t nfld = floc.size (); @@ -145,14 +147,15 @@ void GatherScatter::processLocBuffer (const ioFieldDesc_v & floc, const fldprc_t byte * buffer = &buf_loc[tloc.fld[jfld].off]; for (atlas::idx_t i = 0; i < f.ldim (); i++) for (int j = 0; j < f.dlen (); j++) - buffer[i*f.dlen ()+j] = f (i, j); + a (buffer[i*f.dlen ()+j], f (i, j)); } } } +template void GatherScatter::processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tglo, - const byte_v & buf_glo) const + byte_v & buf_glo, A a) const { auto & comm = eckit::mpi::comm (); atlas::idx_t nfld = fglo.size (); @@ -188,7 +191,7 @@ void GatherScatter::processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tgl for (int j = 0; j < len; j++) { size_t k = jloc * tglo.fld[jfld].len + j; - f (prcloc2glo (iprc, jloc), j) = buf_glo[off+k]; + a (buf_glo[off+k], f (prcloc2glo (iprc, jloc), j)); } } @@ -196,8 +199,11 @@ void GatherScatter::processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tgl } } -void GatherScatter::gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const +void GatherScatter::gather (const ioFieldDesc_v & _floc, ioFieldDesc_v & fglo) const { + +ioFieldDesc_v floc = _floc; + ATLAS_TRACE_SCOPE ("GatherScatter::gather") { auto & comm = eckit::mpi::comm (); @@ -213,11 +219,9 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") computeTLoc (floc, tloc); computeTGlo (fglo, tglo); - // Pack send buffer - byte_v buf_loc (tloc.fld.back ().off); - processLocBuffer (floc, tloc, buf_loc); + processLocBuffer (floc, tloc, buf_loc, [] (byte & a, const byte & b) { a = b; }); byte_v buf_glo (tglo.prc.back ().off); @@ -246,7 +250,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") comm.wait (r); } - processGloBuffer (fglo, tglo, buf_glo); + processGloBuffer (fglo, tglo, buf_glo, [] (const byte & a, byte & b) { b = a; }); } } diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index 88d51fb03..4e9adf53d 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -45,7 +45,7 @@ class GatherScatter public: GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist); - void gather (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const; + void gather (const ioFieldDesc_v & _floc, ioFieldDesc_v & fglo) const; private: atlas::gidx_t prcloc2glo (atlas::idx_t iprc, atlas::idx_t jloc) const @@ -61,10 +61,13 @@ class GatherScatter void reOrderFields (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const; void computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) const; void computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) const; - void processLocBuffer (const ioFieldDesc_v & floc, const fldprc_t & tloc, - byte_v & buf_loc) const; + + template + void processLocBuffer (ioFieldDesc_v & floc, const fldprc_t & tloc, + byte_v & buf_loc, A a) const; + template void processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tglo, - const byte_v & buf_glo) const; + byte_v & buf_glo, A a) const; }; From 0019e26d09f63ec6a9918f0401e3e607063b0aa6 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 11:22:00 +0000 Subject: [PATCH 31/58] Cleaning --- src/atlas/util/vector.h | 4 ++-- src/tests/functionspace/GatherScatter.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/atlas/util/vector.h b/src/atlas/util/vector.h index 26bdb916e..a721225de 100644 --- a/src/atlas/util/vector.h +++ b/src/atlas/util/vector.h @@ -140,8 +140,8 @@ class vector { private: value_type* data_{nullptr}; - idx_t size_{0}; - idx_t capacity_{0}; + size_t size_{0}; + size_t capacity_{0}; }; } // namespace atlas diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index 4e9adf53d..a090a4488 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -3,6 +3,7 @@ #include "ioFieldDesc.h" #include "atlas/grid.h" +#include "atlas/util/vector.h" class GatherScatter { @@ -32,7 +33,7 @@ class GatherScatter using ioFieldDesc_v = std::vector; - using byte_v = std::vector; + using byte_v = atlas::vector; atlas::idx_t max, nprc; From ce4fb6993d472755b96678c66b61ebe90737301f Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 17:44:25 +0000 Subject: [PATCH 32/58] Use size_t in vector.h --- src/atlas/util/vector.h | 11 ++++++++--- src/tests/functionspace/GatherScatter.cc | 10 ++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/atlas/util/vector.h b/src/atlas/util/vector.h index a721225de..0e7f70122 100644 --- a/src/atlas/util/vector.h +++ b/src/atlas/util/vector.h @@ -98,13 +98,18 @@ class vector { T* data() { return data_; } - idx_t size() const { return size_; } + size_t size() const { return size_; } void assign( idx_t n, const value_type& value ) { resize( n ); omp::fill( begin(), begin() + n, value ); } + void assign( size_t n, const value_type& value ) { + resize( n ); + omp::fill( begin(), begin() + n, value ); + } + template void assign( const Iter& first, const Iter& last ) { size_t size = std::distance( first, last ); @@ -121,11 +126,11 @@ class vector { } template void resize( size_t size ) { - if ( static_cast( size ) > 0 ) { + if ( size > 0 ) { if ( capacity_ == 0 ) { reserve( size ); } - if ( static_cast( size ) > capacity_ ) { + if ( size > capacity_ ) { ATLAS_NOTIMPLEMENTED; } size_ = size; diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index d1387cea2..1c87dd9e1 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -140,14 +140,16 @@ void GatherScatter::processLocBuffer (ioFieldDesc_v & floc, const fldprc_t & tlo ATLAS_TRACE_SCOPE ("GatherScatter::processLocBuffer") { -#pragma omp parallel for +#pragma omp parallel for for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) { auto & f = floc[jfld]; byte * buffer = &buf_loc[tloc.fld[jfld].off]; - for (atlas::idx_t i = 0; i < f.ldim (); i++) - for (int j = 0; j < f.dlen (); j++) - a (buffer[i*f.dlen ()+j], f (i, j)); + const size_t dlen = f.dlen (); + const size_t ldim = f.ldim (); + for (atlas::idx_t i = 0; i < ldim; i++) + for (int j = 0; j < dlen; j++) + a (buffer[i*dlen+j], f (i, j)); } } From cd4ad441adb65f859301e7e80d2611ef01f7ec4b Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 18:06:28 +0000 Subject: [PATCH 33/58] New GatherScatter routines --- src/tests/functionspace/GatherScatter.cc | 50 +++++++++++++++++------- src/tests/functionspace/GatherScatter.h | 3 ++ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 1c87dd9e1..cc5e91609 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -201,6 +201,38 @@ void GatherScatter::processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tgl } } +std::vector GatherScatter::postRecv (byte_v & buf, const fldprc_t & t) const +{ +ATLAS_TRACE_SCOPE ("GatherScatter::postRecv") +{ + std::vector rqr; + auto & comm = eckit::mpi::comm (); + atlas::idx_t nprc = comm.size (); + + for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) + if (t.prc[iprc].len > 0) + rqr.push_back (comm.iReceive (&buf[t.prc[iprc].off], t.prc[iprc].len, iprc, 100)); + + return rqr; +} +} + +std::vector GatherScatter::postSend (const byte_v & buf, const fldprc_t & t) const +{ +ATLAS_TRACE_SCOPE ("GatherScatter::postSend") +{ + std::vector rqs; + auto & comm = eckit::mpi::comm (); + atlas::idx_t nprc = comm.size (); + + for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) + if (t.prc[iprc].len > 0) + rqs.push_back (comm.iSend (&buf[t.prc[iprc].off], t.prc[iprc].len, iprc, 100)); + + return rqs; +} +} + void GatherScatter::gather (const ioFieldDesc_v & _floc, ioFieldDesc_v & fglo) const { @@ -229,25 +261,15 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") ATLAS_TRACE_SCOPE ("SEND/RECV") { - std::vector rqr; - - for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (tglo.prc[iprc].len > 0) - rqr.push_back (comm.iReceive (&buf_glo[tglo.prc[iprc].off], - tglo.prc[iprc].len, iprc, 100)); + std::vector rqr = postRecv (buf_glo, tglo); comm.barrier (); - std::vector rqs; - - for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) - if (tloc.prc[iprc].len > 0) - rqs.push_back (comm.iSend (&buf_loc[tloc.prc[iprc].off], - tloc.prc[iprc].len, iprc, 100)); - + std::vector rqs = postSend (buf_loc, tloc); + for (auto & r : rqr) comm.wait (r); - + for (auto & r : rqs) comm.wait (r); } diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index a090a4488..44a223963 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -4,6 +4,7 @@ #include "ioFieldDesc.h" #include "atlas/grid.h" #include "atlas/util/vector.h" +#include "atlas/parallel/mpi/mpi.h" class GatherScatter { @@ -70,6 +71,8 @@ class GatherScatter void processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tglo, byte_v & buf_glo, A a) const; + std::vector postRecv (byte_v & buf, const fldprc_t & t) const; + std::vector postSend (const byte_v & buf, const fldprc_t & t) const; }; From d615126d176b77f30f552397d32ac53a03c935dc Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 18:10:10 +0000 Subject: [PATCH 34/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 33 +++++++++--------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index cc5e91609..c23608b0b 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -241,40 +241,31 @@ ioFieldDesc_v floc = _floc; ATLAS_TRACE_SCOPE ("GatherScatter::gather") { auto & comm = eckit::mpi::comm (); - atlas::idx_t nfld = floc.size (); - atlas::idx_t nprc = comm.size (); - atlas::idx_t lprc = comm.rank (); - atlas::idx_t ldim = dist.nb_pts ()[lprc]; reOrderFields (floc, fglo); fldprc_t tloc, tglo; - computeTLoc (floc, tloc); computeTGlo (fglo, tglo); + byte_v buf_glo (tglo.prc.back ().off); + std::vector rqr = postRecv (buf_glo, tglo); + computeTLoc (floc, tloc); byte_v buf_loc (tloc.fld.back ().off); - processLocBuffer (floc, tloc, buf_loc, [] (byte & a, const byte & b) { a = b; }); + + comm.barrier (); + + std::vector rqs = postSend (buf_loc, tloc); - byte_v buf_glo (tglo.prc.back ().off); - - ATLAS_TRACE_SCOPE ("SEND/RECV") - { - std::vector rqr = postRecv (buf_glo, tglo); - - comm.barrier (); - - std::vector rqs = postSend (buf_loc, tloc); + for (auto & r : rqr) + comm.wait (r); - for (auto & r : rqr) - comm.wait (r); + processGloBuffer (fglo, tglo, buf_glo, [] (const byte & a, byte & b) { b = a; }); - for (auto & r : rqs) - comm.wait (r); - } + for (auto & r : rqs) + comm.wait (r); - processGloBuffer (fglo, tglo, buf_glo, [] (const byte & a, byte & b) { b = a; }); } } From aea8531cbb1b5242b7dadff7e316f1f970ddae8e Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 21 May 2020 20:33:56 +0000 Subject: [PATCH 35/58] Scatter works --- src/tests/functionspace/GatherScatter.cc | 54 ++++++++++++++++++--- src/tests/functionspace/GatherScatter.h | 5 +- src/tests/functionspace/test_batchgather.cc | 33 ++++++++++++- 3 files changed, 81 insertions(+), 11 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index c23608b0b..4253e2370 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -89,8 +89,9 @@ void GatherScatter::reOrderFields (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) c } -void GatherScatter::computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) const +GatherScatter::fldprc_t GatherScatter::computeTLoc (const ioFieldDesc_v & floc) const { + fldprc_t tloc; auto & comm = eckit::mpi::comm (); atlas::idx_t nprc = comm.size (); atlas::idx_t nfld = floc.size (); @@ -107,10 +108,13 @@ void GatherScatter::computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) co integrate (tloc.fld); integrate (tloc.prc); + + return tloc; } -void GatherScatter::computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) const +GatherScatter::fldprc_t GatherScatter::computeTGlo (const ioFieldDesc_v & fglo) const { + fldprc_t tglo; auto & comm = eckit::mpi::comm (); atlas::idx_t nprc = comm.size (); atlas::idx_t lprc = comm.rank (); @@ -129,6 +133,8 @@ void GatherScatter::computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) co tglo.prc[iprc].len = dist.nb_pts ()[iprc] * tglo.fld.back ().off; integrate (tglo.prc); + + return tglo; } @@ -182,6 +188,7 @@ void GatherScatter::processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tgl for (int ii = 0; ii < prcs.size (); ii++) for (int jj = 0; jj < flds.size (); jj++) { + const atlas::idx_t iprc = prcs[ii]; const atlas::idx_t jfld = flds[jj]; const atlas::idx_t ngptot = dist.nb_pts ()[iprc]; @@ -233,10 +240,11 @@ ATLAS_TRACE_SCOPE ("GatherScatter::postSend") } } -void GatherScatter::gather (const ioFieldDesc_v & _floc, ioFieldDesc_v & fglo) const +void GatherScatter::gather (const ioFieldDesc_v & _floc, ioFieldDesc_v & _fglo) const { ioFieldDesc_v floc = _floc; +ioFieldDesc_v fglo = _fglo; ATLAS_TRACE_SCOPE ("GatherScatter::gather") { @@ -244,13 +252,11 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") reOrderFields (floc, fglo); - fldprc_t tloc, tglo; - - computeTGlo (fglo, tglo); + fldprc_t tglo = computeTGlo (fglo); byte_v buf_glo (tglo.prc.back ().off); std::vector rqr = postRecv (buf_glo, tglo); - computeTLoc (floc, tloc); + fldprc_t tloc = computeTLoc (floc); byte_v buf_loc (tloc.fld.back ().off); processLocBuffer (floc, tloc, buf_loc, [] (byte & a, const byte & b) { a = b; }); @@ -270,3 +276,37 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") } } +void GatherScatter::scatter (const ioFieldDesc_v & _fglo, ioFieldDesc_v & _floc) const +{ + +ioFieldDesc_v fglo = _fglo; +ioFieldDesc_v floc = _floc; + +ATLAS_TRACE_SCOPE ("GatherScatter::scatter") +{ + auto & comm = eckit::mpi::comm (); + + reOrderFields (floc, fglo); + + fldprc_t tloc = computeTLoc (floc); + byte_v buf_loc (tloc.fld.back ().off); + std::vector rqr = postRecv (buf_loc, tloc); + + fldprc_t tglo = computeTGlo (fglo); + byte_v buf_glo (tglo.prc.back ().off); + processGloBuffer (fglo, tglo, buf_glo, [] (byte & a, const byte & b) { a = b; }); + + comm.barrier (); + + std::vector rqs = postSend (buf_glo, tglo); + + for (auto & r : rqr) + comm.wait (r); + + processLocBuffer (floc, tloc, buf_loc, [] (const byte & a, byte & b) { b = a; }); + + for (auto & r : rqs) + comm.wait (r); +} +} + diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index 44a223963..d79300ad4 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -48,6 +48,7 @@ class GatherScatter GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist); void gather (const ioFieldDesc_v & _floc, ioFieldDesc_v & fglo) const; + void scatter (const ioFieldDesc_v & _fglo, ioFieldDesc_v & floc) const; private: atlas::gidx_t prcloc2glo (atlas::idx_t iprc, atlas::idx_t jloc) const @@ -61,8 +62,8 @@ class GatherScatter } void reOrderFields (ioFieldDesc_v & floc, ioFieldDesc_v & fglo) const; - void computeTLoc (const ioFieldDesc_v & floc, fldprc_t & tloc) const; - void computeTGlo (const ioFieldDesc_v & fglo, fldprc_t & tglo) const; + fldprc_t computeTLoc (const ioFieldDesc_v & floc) const; + fldprc_t computeTGlo (const ioFieldDesc_v & fglo) const; template void processLocBuffer (ioFieldDesc_v & floc, const fldprc_t & tloc, diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index 2ca2ece8b..28569e350 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -129,7 +129,7 @@ CASE( "test_gatherscatter" ) auto checkgather = [ind, prc, grid, func, irank] (const atlas::FieldSet & sglo) { - ATLAS_TRACE_SCOPE ("check") + ATLAS_TRACE_SCOPE ("checkgather") { for (int i = 0; i < sglo.size (); i++) { @@ -149,6 +149,23 @@ CASE( "test_gatherscatter" ) } }; + auto checkscatter = [fs, func, irank] (const atlas::FieldSet & sloc) + { + ATLAS_TRACE_SCOPE ("checkscatter") + { + for (int i = 0; i < sloc.size (); i++) + { + const auto & floc = sloc[i]; + const auto v = array::make_view (floc); + for (int j = 0; j < fs.sizeOwned (); j++) + { + T v1 = v[j], v2 = func (i, irank, j); + EXPECT_EQ (v1, v2); + } + } + } + }; + for (int i = 0; i < nfields; i++) { int owner = i % nproc; @@ -211,10 +228,22 @@ CASE( "test_gatherscatter" ) if (debug) prff ("sglo2", sglo2); if (check) checkgather (sglo2); + + for (int i = 0; i < sloc.size (); i++) + { + auto v = array::make_view (sloc[i]); + for (int j = 0; j < fs.sizeOwned (); j++) + v (j) = 0; + } + + gs.scatter (dglo, dloc); + + if (check) checkscatter (sloc); } } - // Avoid Atlas barrier + + // Prevent error in Atlas barrier comm.barrier (); } From bd284752466e8424d0a9b28ba67b0e0cf45d03a1 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 22 May 2020 06:42:31 +0000 Subject: [PATCH 36/58] Cleaning --- src/tests/functionspace/GatherScatter.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index 4253e2370..caecae79a 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -36,6 +36,9 @@ std::vector grep (I n, F f) return g; } +inline void unpack (const byte & a, byte & b) { b = a; }; +inline void pack (byte & a, const byte & b) { a = b; }; + }; GatherScatter::GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist) @@ -258,7 +261,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") fldprc_t tloc = computeTLoc (floc); byte_v buf_loc (tloc.fld.back ().off); - processLocBuffer (floc, tloc, buf_loc, [] (byte & a, const byte & b) { a = b; }); + processLocBuffer (floc, tloc, buf_loc, pack); comm.barrier (); @@ -267,7 +270,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") for (auto & r : rqr) comm.wait (r); - processGloBuffer (fglo, tglo, buf_glo, [] (const byte & a, byte & b) { b = a; }); + processGloBuffer (fglo, tglo, buf_glo, unpack); for (auto & r : rqs) comm.wait (r); @@ -294,7 +297,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::scatter") fldprc_t tglo = computeTGlo (fglo); byte_v buf_glo (tglo.prc.back ().off); - processGloBuffer (fglo, tglo, buf_glo, [] (byte & a, const byte & b) { a = b; }); + processGloBuffer (fglo, tglo, buf_glo, pack); comm.barrier (); @@ -303,7 +306,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::scatter") for (auto & r : rqr) comm.wait (r); - processLocBuffer (floc, tloc, buf_loc, [] (const byte & a, byte & b) { b = a; }); + processLocBuffer (floc, tloc, buf_loc, unpack); for (auto & r : rqs) comm.wait (r); From 6683127e40a000d1f2ded542d63dd0f29b3e7629 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 22 May 2020 07:32:05 +0000 Subject: [PATCH 37/58] Add size accessor to distribution --- src/atlas/grid/Distribution.h | 5 +++ .../detail/distribution/DistributionImpl.cc | 7 +++- .../detail/distribution/DistributionImpl.h | 3 ++ src/tests/functionspace/GatherScatter.cc | 11 +++-- src/tests/functionspace/GatherScatter.h | 3 +- src/tests/functionspace/test_batchgather.cc | 41 +++++++++++++++---- 6 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/atlas/grid/Distribution.h b/src/atlas/grid/Distribution.h index 7a91230d8..46f5ee617 100644 --- a/src/atlas/grid/Distribution.h +++ b/src/atlas/grid/Distribution.h @@ -64,6 +64,11 @@ class Distribution : DOXYGEN_HIDE( public util::ObjectHandle ) const std::string& type() const; + gidx_t size () const + { + return get ()->size (); + } + friend std::ostream& operator<<( std::ostream& os, const Distribution& distribution ); }; diff --git a/src/atlas/grid/detail/distribution/DistributionImpl.cc b/src/atlas/grid/detail/distribution/DistributionImpl.cc index d6d85e1a2..e2e1912ae 100644 --- a/src/atlas/grid/detail/distribution/DistributionImpl.cc +++ b/src/atlas/grid/detail/distribution/DistributionImpl.cc @@ -40,9 +40,10 @@ DistributionImpl::DistributionImpl( const Grid& grid ) : nb_pts_( nb_partitions_, grid.size() ), max_pts_( grid.size() ), min_pts_( grid.size() ), - type_( distribution_type( nb_partitions_ ) ) {} + type_( distribution_type( nb_partitions_ ) ), + size_( grid.size ()) {} -DistributionImpl::DistributionImpl( const Grid& grid, const Partitioner& partitioner ) : part_( grid.size() ) { +DistributionImpl::DistributionImpl( const Grid& grid, const Partitioner& partitioner ) : part_( grid.size() ), size_ (grid.size ()) { partitioner.partition( grid, part_.data() ); nb_partitions_ = partitioner.nb_partitions(); @@ -99,6 +100,7 @@ DistributionImpl::DistributionImpl( int nb_partitions, idx_t npts, int part[], i max_pts_ = *std::max_element( nb_pts_.begin(), nb_pts_.end() ); min_pts_ = *std::min_element( nb_pts_.begin(), nb_pts_.end() ); type_ = distribution_type( nb_partitions_ ); + size_ = npts; } DistributionImpl::DistributionImpl( int nb_partitions, partition_t&& part ) : @@ -123,6 +125,7 @@ DistributionImpl::DistributionImpl( int nb_partitions, partition_t&& part ) : max_pts_ = *std::max_element( nb_pts_.begin(), nb_pts_.end() ); min_pts_ = *std::min_element( nb_pts_.begin(), nb_pts_.end() ); type_ = distribution_type( nb_partitions_ ); + size_ = size; } DistributionImpl::~DistributionImpl() = default; diff --git a/src/atlas/grid/detail/distribution/DistributionImpl.h b/src/atlas/grid/detail/distribution/DistributionImpl.h index 187b13e68..919bd8d64 100644 --- a/src/atlas/grid/detail/distribution/DistributionImpl.h +++ b/src/atlas/grid/detail/distribution/DistributionImpl.h @@ -59,6 +59,8 @@ class DistributionImpl : public util::Object { idx_t max_pts() const { return max_pts_; } idx_t min_pts() const { return min_pts_; } + gidx_t size () const { return size_; } + const std::string& type() const { return type_; } void print( std::ostream& ) const; @@ -70,6 +72,7 @@ class DistributionImpl : public util::Object { idx_t max_pts_; idx_t min_pts_; std::string type_; + gidx_t size_; }; extern "C" { diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/functionspace/GatherScatter.cc index caecae79a..76cc3f8d2 100644 --- a/src/tests/functionspace/GatherScatter.cc +++ b/src/tests/functionspace/GatherScatter.cc @@ -41,8 +41,7 @@ inline void pack (byte & a, const byte & b) { a = b; }; }; -GatherScatter::GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist) - : grid (_grid), dist (_dist) +GatherScatter::GatherScatter (const atlas::grid::Distribution & _dist) : dist (_dist) { ATLAS_TRACE_SCOPE ("GatherScatter::GatherScatter") { @@ -50,17 +49,17 @@ ATLAS_TRACE_SCOPE ("GatherScatter::GatherScatter") nprc = dist.nb_partitions (); std::vector count (nprc); - std::vector ind (grid.size ()); + std::vector ind (dist.size ()); - for (atlas::gidx_t i = 0; i < grid.size (); i++) + for (atlas::gidx_t i = 0; i < dist.size (); i++) ind[i] = count[dist.partition (i)]++; max = *std::max_element (count.begin (), count.end ()); _prcloc2glo.resize (max * nprc, std::numeric_limits::min ()); - _glo2prcloc.resize (grid.size ()); + _glo2prcloc.resize (dist.size ()); - for (atlas::gidx_t i = 0; i < grid.size (); i++) + for (atlas::gidx_t i = 0; i < dist.size (); i++) { _prcloc2glo[max * dist.partition (i) + ind[i]] = i; _glo2prcloc[i].loc = ind[i]; diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/functionspace/GatherScatter.h index d79300ad4..f01d3a571 100644 --- a/src/tests/functionspace/GatherScatter.h +++ b/src/tests/functionspace/GatherScatter.h @@ -41,11 +41,10 @@ class GatherScatter std::vector _prcloc2glo; std::vector _glo2prcloc; - const atlas::StructuredGrid & grid; const atlas::grid::Distribution & dist; public: - GatherScatter (const atlas::StructuredGrid & _grid, const atlas::grid::Distribution & _dist); + GatherScatter (const atlas::grid::Distribution & _dist); void gather (const ioFieldDesc_v & _floc, ioFieldDesc_v & fglo) const; void scatter (const ioFieldDesc_v & _fglo, ioFieldDesc_v & floc) const; diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/functionspace/test_batchgather.cc index 28569e350..5fefeeb4f 100644 --- a/src/tests/functionspace/test_batchgather.cc +++ b/src/tests/functionspace/test_batchgather.cc @@ -82,6 +82,8 @@ CASE( "test_gatherscatter" ) atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); bool gather1 (eckit::Resource ("--gather1", false)); bool gather2 (eckit::Resource ("--gather2", false)); + bool scatter1 (eckit::Resource ("--scatter1", false)); + bool scatter2 (eckit::Resource ("--scatter2", false)); bool debug (eckit::Resource ("--debug", false)); bool check (eckit::Resource ("--check", false)); @@ -206,11 +208,28 @@ CASE( "test_gatherscatter" ) if (check) checkgather (sglo1); if (debug) prff ("sglo1", sglo1); } + + if (scatter2) + { + ATLAS_TRACE_SCOPE ("test_scatter1") + { + for (int i = 0; i < sloc.size (); i++) + { + auto v = array::make_view (sloc[i]); + for (int j = 0; j < fs.sizeOwned (); j++) + v (j) = 0; + } + + fs.scatter (sglo1, sloc); + + if (check) checkscatter (sloc); + } + } } if (gather2) { - GatherScatter gs (grid, dist); + GatherScatter gs (dist); ATLAS_TRACE_SCOPE ("test_gather2") { std::vector dloc; @@ -229,16 +248,22 @@ CASE( "test_gatherscatter" ) if (debug) prff ("sglo2", sglo2); if (check) checkgather (sglo2); - for (int i = 0; i < sloc.size (); i++) + if (scatter2) { - auto v = array::make_view (sloc[i]); - for (int j = 0; j < fs.sizeOwned (); j++) - v (j) = 0; - } + ATLAS_TRACE_SCOPE ("test_scatter2") + { + for (int i = 0; i < sloc.size (); i++) + { + auto v = array::make_view (sloc[i]); + for (int j = 0; j < fs.sizeOwned (); j++) + v (j) = 0; + } - gs.scatter (dglo, dloc); + gs.scatter (dglo, dloc); - if (check) checkscatter (sloc); + if (check) checkscatter (sloc); + } + } } } From 8630dd837d1891012980b37fead78cfaae094db1 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 22 May 2020 07:41:18 +0000 Subject: [PATCH 38/58] Cleaning --- src/tests/CMakeLists.txt | 1 + src/tests/functionspace/CMakeLists.txt | 12 ----------- src/tests/gatherscatter/CMakeLists.txt | 20 +++++++++++++++++++ .../GatherScatter.cc | 0 .../GatherScatter.h | 0 .../arrayViewHelpers.h | 0 .../ioFieldDesc.cc | 0 .../ioFieldDesc.h | 0 .../test_arrayViewHelpers.cc} | 0 .../test_gatherscatter.cc} | 0 10 files changed, 21 insertions(+), 12 deletions(-) create mode 100644 src/tests/gatherscatter/CMakeLists.txt rename src/tests/{functionspace => gatherscatter}/GatherScatter.cc (100%) rename src/tests/{functionspace => gatherscatter}/GatherScatter.h (100%) rename src/tests/{functionspace => gatherscatter}/arrayViewHelpers.h (100%) rename src/tests/{functionspace => gatherscatter}/ioFieldDesc.cc (100%) rename src/tests/{functionspace => gatherscatter}/ioFieldDesc.h (100%) rename src/tests/{functionspace/testphi.cc => gatherscatter/test_arrayViewHelpers.cc} (100%) rename src/tests/{functionspace/test_batchgather.cc => gatherscatter/test_gatherscatter.cc} (100%) diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 25f4e3b73..5bad92b89 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -114,6 +114,7 @@ add_subdirectory( projection ) add_subdirectory( grid ) add_subdirectory( mesh ) add_subdirectory( functionspace ) +add_subdirectory( gatherscatter ) add_subdirectory( io ) add_subdirectory( numerics ) add_subdirectory( trans ) diff --git a/src/tests/functionspace/CMakeLists.txt b/src/tests/functionspace/CMakeLists.txt index 1c12428b2..9f3730375 100644 --- a/src/tests/functionspace/CMakeLists.txt +++ b/src/tests/functionspace/CMakeLists.txt @@ -23,18 +23,6 @@ if( HAVE_FCTEST ) endif() -ecbuild_add_test( TARGET test_batchgather - SOURCES test_batchgather.cc ioFieldDesc.cc GatherScatter.cc - LIBS atlas - ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} -) - -ecbuild_add_test( TARGET testphi - SOURCES testphi.cc ioFieldDesc.cc - LIBS atlas - ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} -) - ecbuild_add_test( TARGET atlas_test_functionspace SOURCES test_functionspace.cc LIBS atlas diff --git a/src/tests/gatherscatter/CMakeLists.txt b/src/tests/gatherscatter/CMakeLists.txt new file mode 100644 index 000000000..a8c482033 --- /dev/null +++ b/src/tests/gatherscatter/CMakeLists.txt @@ -0,0 +1,20 @@ +# (C) Copyright 2013 ECMWF. +# +# This software is licensed under the terms of the Apache Licence Version 2.0 +# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. +# In applying this licence, ECMWF does not waive the privileges and immunities +# granted to it by virtue of its status as an intergovernmental organisation nor +# does it submit to any jurisdiction. + +ecbuild_add_test( TARGET test_gatherscatter + SOURCES test_gatherscatter.cc ioFieldDesc.cc GatherScatter.cc + LIBS atlas + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} +) + +ecbuild_add_test( TARGET test_arrayViewHelpers + SOURCES test_arrayViewHelpers.cc ioFieldDesc.cc + LIBS atlas + ENVIRONMENT ${ATLAS_TEST_ENVIRONMENT} +) + diff --git a/src/tests/functionspace/GatherScatter.cc b/src/tests/gatherscatter/GatherScatter.cc similarity index 100% rename from src/tests/functionspace/GatherScatter.cc rename to src/tests/gatherscatter/GatherScatter.cc diff --git a/src/tests/functionspace/GatherScatter.h b/src/tests/gatherscatter/GatherScatter.h similarity index 100% rename from src/tests/functionspace/GatherScatter.h rename to src/tests/gatherscatter/GatherScatter.h diff --git a/src/tests/functionspace/arrayViewHelpers.h b/src/tests/gatherscatter/arrayViewHelpers.h similarity index 100% rename from src/tests/functionspace/arrayViewHelpers.h rename to src/tests/gatherscatter/arrayViewHelpers.h diff --git a/src/tests/functionspace/ioFieldDesc.cc b/src/tests/gatherscatter/ioFieldDesc.cc similarity index 100% rename from src/tests/functionspace/ioFieldDesc.cc rename to src/tests/gatherscatter/ioFieldDesc.cc diff --git a/src/tests/functionspace/ioFieldDesc.h b/src/tests/gatherscatter/ioFieldDesc.h similarity index 100% rename from src/tests/functionspace/ioFieldDesc.h rename to src/tests/gatherscatter/ioFieldDesc.h diff --git a/src/tests/functionspace/testphi.cc b/src/tests/gatherscatter/test_arrayViewHelpers.cc similarity index 100% rename from src/tests/functionspace/testphi.cc rename to src/tests/gatherscatter/test_arrayViewHelpers.cc diff --git a/src/tests/functionspace/test_batchgather.cc b/src/tests/gatherscatter/test_gatherscatter.cc similarity index 100% rename from src/tests/functionspace/test_batchgather.cc rename to src/tests/gatherscatter/test_gatherscatter.cc From 8e8f79d5cb3c3c6ff19c9b17eb9336767104450b Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 22 May 2020 10:33:21 +0000 Subject: [PATCH 39/58] Add missing header --- src/tests/gatherscatter/GatherScatter.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tests/gatherscatter/GatherScatter.cc b/src/tests/gatherscatter/GatherScatter.cc index 76cc3f8d2..4caf4b2c6 100644 --- a/src/tests/gatherscatter/GatherScatter.cc +++ b/src/tests/gatherscatter/GatherScatter.cc @@ -6,6 +6,8 @@ #include "atlas/parallel/mpi/mpi.h" #include "atlas/runtime/Trace.h" +#include + namespace { From e13517282ea75289f59b5716a7f44946a74746ac Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 22 May 2020 11:07:32 +0000 Subject: [PATCH 40/58] Change printf format --- src/tests/gatherscatter/test_arrayViewHelpers.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/gatherscatter/test_arrayViewHelpers.cc b/src/tests/gatherscatter/test_arrayViewHelpers.cc index 1ad704ba1..7c2e93071 100644 --- a/src/tests/gatherscatter/test_arrayViewHelpers.cc +++ b/src/tests/gatherscatter/test_arrayViewHelpers.cc @@ -42,7 +42,7 @@ int main (int argc, char * argv[]) prss ("c", c); - printf (" sizeof (c (0,0)) = %d\n", sizeof (c (0,0))); + printf (" sizeof (c (0,0)) = %ld\n", sizeof (c (0,0))); for (int i = 0; i < 4; i++) printf (" &c(0,0,%d) = 0x%llx\n", i, &c(0,0,i)); From 4e6926a79f7bba93525daedeadd830616b608406 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 22 May 2020 16:39:36 +0000 Subject: [PATCH 41/58] Cleaning --- src/tests/gatherscatter/GatherScatter.cc | 25 ++++++++++++------- .../gatherscatter/test_arrayViewHelpers.cc | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/tests/gatherscatter/GatherScatter.cc b/src/tests/gatherscatter/GatherScatter.cc index 4caf4b2c6..af4f65da6 100644 --- a/src/tests/gatherscatter/GatherScatter.cc +++ b/src/tests/gatherscatter/GatherScatter.cc @@ -29,15 +29,22 @@ void integrate (T & v) v[i].off = v[i-1].off + v[i-1].len; } -template -std::vector grep (I n, F f) +template +V grep (const V v, F f) { - std::vector r (n), g; - std::iota (r.begin (), r.end (), 0); - std::copy_if (r.begin (), r.end (), std::back_inserter (g), f); + V g; + std::copy_if (v.begin (), v.end (), std::back_inserter (g), f); return g; } +template +std::vector range (N n) +{ + std::vector r (n); + std::iota (r.begin (), r.end (), 0); + return r; +} + inline void unpack (const byte & a, byte & b) { b = a; }; inline void pack (byte & a, const byte & b) { a = b; }; @@ -175,10 +182,10 @@ void GatherScatter::processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tgl ATLAS_TRACE_SCOPE ("GatherScatter::processGloBuffer") { - std::vector prcs = grep (nprc, - [&tglo] (atlas::idx_t i) { return tglo.prc[i].len > 0; }); - std::vector flds = grep (nfld, - [&tglo] (atlas::idx_t i) { return tglo.fld[i].len > 0; }); + std::vector prcs = grep (range (nprc), + [&tglo] (atlas::idx_t i) { return tglo.prc[i].len > 0; }); + std::vector flds = grep (range (nfld), + [&tglo] (atlas::idx_t i) { return tglo.fld[i].len > 0; }); #ifdef UNDEF for (atlas::idx_t iprc = 0; iprc < nprc; iprc++) diff --git a/src/tests/gatherscatter/test_arrayViewHelpers.cc b/src/tests/gatherscatter/test_arrayViewHelpers.cc index 7c2e93071..95b0f2166 100644 --- a/src/tests/gatherscatter/test_arrayViewHelpers.cc +++ b/src/tests/gatherscatter/test_arrayViewHelpers.cc @@ -42,7 +42,7 @@ int main (int argc, char * argv[]) prss ("c", c); - printf (" sizeof (c (0,0)) = %ld\n", sizeof (c (0,0))); + printf (" sizeof (c (0,0)) = %lu\n", sizeof (c (0,0))); for (int i = 0; i < 4; i++) printf (" &c(0,0,%d) = 0x%llx\n", i, &c(0,0,i)); From 064179f2691905fdeee9337cfd1fe1fce97866ba Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 28 May 2020 07:23:52 +0000 Subject: [PATCH 42/58] Cleaning --- src/tests/gatherscatter/arrayViewHelpers.h | 7 ++++--- src/tests/gatherscatter/ioFieldDesc.cc | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/tests/gatherscatter/arrayViewHelpers.h b/src/tests/gatherscatter/arrayViewHelpers.h index a5659f990..068b709dc 100644 --- a/src/tests/gatherscatter/arrayViewHelpers.h +++ b/src/tests/gatherscatter/arrayViewHelpers.h @@ -37,9 +37,10 @@ dropDimension (const atlas::array::ArrayView & view, int dim, atlas: // Convert a view to a view of bytes (add an extra inner dimension) template -atlas::array::ArrayView +atlas::array::ArrayView::value, const byte, byte>::type,Rank+1> byteView (const atlas::array::ArrayView & view) { + using B = typename std::conditional::value, const byte, byte>::type; constexpr int rank = Rank+1; atlas::array::ArrayShape shape; atlas::array::ArrayStrides strides; @@ -55,8 +56,8 @@ byteView (const atlas::array::ArrayView & view) shape.push_back (dlen); strides.push_back (1); - byte * data = (byte *) (view.data ()); + B * data = (B *) (view.data ()); - return atlas::array::ArrayView (data, shape, strides); + return atlas::array::ArrayView (data, shape, strides); } diff --git a/src/tests/gatherscatter/ioFieldDesc.cc b/src/tests/gatherscatter/ioFieldDesc.cc index fb30f197b..cb306489a 100644 --- a/src/tests/gatherscatter/ioFieldDesc.cc +++ b/src/tests/gatherscatter/ioFieldDesc.cc @@ -2,6 +2,8 @@ #include "arrayViewHelpers.h" +namespace +{ // The following templates create a list of byte views of rank 2 from a view of any rank, any type // @@ -43,6 +45,9 @@ void createListOf1DByteView (atlas::array::ArrayView & view, listOf1DByteView (v, std::vector (), f, ldim, list); } +}; + + void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim) { int rank = f.rank (); From c824bff873f3cfba146d0edf2ba77cb16fc26d8f Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 28 May 2020 08:11:58 +0000 Subject: [PATCH 43/58] Add block dimension --- src/tests/gatherscatter/GatherScatter.cc | 11 ++++-- src/tests/gatherscatter/arrayViewHelpers.h | 25 +++++++++++++ src/tests/gatherscatter/ioFieldDesc.cc | 3 +- src/tests/gatherscatter/ioFieldDesc.h | 41 +++++++++------------- 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/tests/gatherscatter/GatherScatter.cc b/src/tests/gatherscatter/GatherScatter.cc index af4f65da6..a71afe204 100644 --- a/src/tests/gatherscatter/GatherScatter.cc +++ b/src/tests/gatherscatter/GatherScatter.cc @@ -164,9 +164,14 @@ void GatherScatter::processLocBuffer (ioFieldDesc_v & floc, const fldprc_t & tlo byte * buffer = &buf_loc[tloc.fld[jfld].off]; const size_t dlen = f.dlen (); const size_t ldim = f.ldim (); - for (atlas::idx_t i = 0; i < ldim; i++) + const size_t nblk = f.nblk (); + +auto jlonjblk2jgp = [] (atlas::idx_t jlon, atlas::idx_t jblk) { ATLAS_ASSERT (jblk == 0); return jlon; }; + + for (atlas::idx_t jblk = 0; jblk < nblk; jblk++) + for (atlas::idx_t jlon = 0; jlon < ldim; jlon++) for (int j = 0; j < dlen; j++) - a (buffer[i*dlen+j], f (i, j)); + a (buffer[jlonjblk2jgp (jlon, jblk)*dlen+j], f (jblk, jlon, j)); } } @@ -211,7 +216,7 @@ void GatherScatter::processGloBuffer (ioFieldDesc_v & fglo, const fldprc_t & tgl for (int j = 0; j < len; j++) { size_t k = jloc * tglo.fld[jfld].len + j; - a (buf_glo[off+k], f (prcloc2glo (iprc, jloc), j)); + a (buf_glo[off+k], f (0, prcloc2glo (iprc, jloc), j)); } } diff --git a/src/tests/gatherscatter/arrayViewHelpers.h b/src/tests/gatherscatter/arrayViewHelpers.h index 068b709dc..c458e45dd 100644 --- a/src/tests/gatherscatter/arrayViewHelpers.h +++ b/src/tests/gatherscatter/arrayViewHelpers.h @@ -61,3 +61,28 @@ byteView (const atlas::array::ArrayView & view) return atlas::array::ArrayView (data, shape, strides); } +// Add an extra outer dummy dimension + +template +atlas::array::ArrayView +addDummyDimension (const atlas::array::ArrayView & view) +{ + constexpr int rank = Rank+1; + atlas::array::ArrayShape shape = {1}; + atlas::array::ArrayStrides strides = {view.size ()}; + + for (int i = 0; i < Rank; i++) + { + shape.push_back (view.shape (i)); + strides.push_back (view.stride (i)); + } + + using nonConstValue = typename std::remove_const::type; + + Value * data = (nonConstValue *) (view.data ()); + + return atlas::array::ArrayView (data, shape, strides); +} + + + diff --git a/src/tests/gatherscatter/ioFieldDesc.cc b/src/tests/gatherscatter/ioFieldDesc.cc index cb306489a..b25c4b26f 100644 --- a/src/tests/gatherscatter/ioFieldDesc.cc +++ b/src/tests/gatherscatter/ioFieldDesc.cc @@ -33,7 +33,8 @@ void listOf1DByteView (atlas::array::ArrayView & view, const atlas::Field & f, size_t ldim, std::vector & list) { - list.push_back (ioFieldDesc (view, ind, f, ldim)); + auto v = addDummyDimension (view); + list.push_back (ioFieldDesc (v, ind, f, ldim)); } template diff --git a/src/tests/gatherscatter/ioFieldDesc.h b/src/tests/gatherscatter/ioFieldDesc.h index 1348ec0bc..13e370c2a 100644 --- a/src/tests/gatherscatter/ioFieldDesc.h +++ b/src/tests/gatherscatter/ioFieldDesc.h @@ -11,25 +11,20 @@ typedef char byte; class ioFieldDesc { public: - ioFieldDesc (atlas::array::ArrayView & v, + ioFieldDesc (atlas::array::ArrayView & v, const std::vector & ind, const atlas::Field & f, size_t ldim) : _v (v), _ind (ind), _f (f), _ldim (ldim) { - _dlen = _v.shape (1); + _nblk = _v.shape (0); + _dlen = _v.shape (2); if (_ldim == 0) - _ldim = _v.shape (0); - _size = _ldim * _v.shape (1); - _contiguous = (_dlen == _v.stride (0)); + _ldim = _v.shape (1); + _size = _nblk * _ldim * _dlen; } - bool contiguous () const - { - return _contiguous; - } - - atlas::array::ArrayView & view () + atlas::array::ArrayView & view () { return _v; } @@ -59,6 +54,11 @@ class ioFieldDesc return _size; } + size_t nblk () const + { + return _nblk; + } + size_t ldim () const { return _ldim; @@ -69,32 +69,25 @@ class ioFieldDesc return _dlen; } - void pack (byte * buffer) const - { - for (int i = 0; i < _ldim; i++) - for (int j = 0; j < _dlen; j++) - buffer[i*_dlen+j] = _v (i, j); - } - - byte & operator () (int i, int j) + byte & operator () (int jblk, int jlon, int k) { - return _v (i, j); + return _v (jblk, jlon, k); } - byte operator () (int i, int j) const + byte operator () (int jblk, int jlon, int k) const { - return _v (i, j); + return _v (jblk, jlon, k); } private: - atlas::array::ArrayView _v; + atlas::array::ArrayView _v; // NGPBKLS, NPROMA, sizeof (element) const std::vector _ind; const atlas::Field & _f; int _owner = 0; size_t _ldim; + size_t _nblk; size_t _size; size_t _dlen; - bool _contiguous; }; void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim = 0); From f8aaa3933450bfbe325a74d63f47a3983b9768cb Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 28 May 2020 16:27:38 +0000 Subject: [PATCH 44/58] test_gatherscatter_ngptotxnflevg --- src/tests/gatherscatter/ioFieldDesc.cc | 39 +++-- src/tests/gatherscatter/ioFieldDesc.h | 4 +- src/tests/gatherscatter/test_gatherscatter.cc | 137 +++++++++++++++++- 3 files changed, 158 insertions(+), 22 deletions(-) diff --git a/src/tests/gatherscatter/ioFieldDesc.cc b/src/tests/gatherscatter/ioFieldDesc.cc index b25c4b26f..e1e85c585 100644 --- a/src/tests/gatherscatter/ioFieldDesc.cc +++ b/src/tests/gatherscatter/ioFieldDesc.cc @@ -11,7 +11,7 @@ namespace template void listOf1DByteView (atlas::array::ArrayView & view, const std::vector & _ind, - const atlas::Field & f, size_t ldim, + const atlas::Field & f, size_t ldim, atlas::idx_t gdim, std::vector & list) { static_assert (Rank > 2, "listOf1DByteView should be called with views having a Rank > 2"); @@ -19,18 +19,30 @@ void listOf1DByteView (atlas::array::ArrayView & view, std::vector ind = _ind; ind.push_back (0); - for (int i = 0; i < view.shape (0); i++) + if (gdim == 0) { - auto v = dropDimension (view, 0, i); - ind.back () = i; - listOf1DByteView (v, ind, f, ldim, list); + for (int i = 0; i < view.shape (1); i++) + { + auto v = dropDimension (view, 1, i); + ind.back () = i; + listOf1DByteView (v, ind, f, ldim, 0, list); + } + } + else + { + for (int i = 0; i < view.shape (0); i++) + { + auto v = dropDimension (view, 0, i); + ind.back () = i; + listOf1DByteView (v, ind, f, ldim, gdim-1, list); + } } } template <> void listOf1DByteView (atlas::array::ArrayView & view, const std::vector & ind, - const atlas::Field & f, size_t ldim, + const atlas::Field & f, size_t ldim, atlas::idx_t gdim, std::vector & list) { auto v = addDummyDimension (view); @@ -39,26 +51,29 @@ void listOf1DByteView (atlas::array::ArrayView & view, template void createListOf1DByteView (atlas::array::ArrayView & view, - const atlas::Field & f, size_t ldim, + const atlas::Field & f, size_t ldim, atlas::idx_t gdim, std::vector & list) { auto v = byteView (view); - listOf1DByteView (v, std::vector (), f, ldim, list); + listOf1DByteView (v, std::vector (), f, ldim, gdim, list); } }; -void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim) +void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim, atlas::idx_t gdim) { int rank = f.rank (); auto type = f.datatype (); + if (gdim < 0) + gdim = gdim + rank; + #define HANDLE_TYPE_RANK(__type,__rank) \ if (rank == __rank) \ { \ auto v = atlas::array::make_view<__type,__rank> (f); \ - createListOf1DByteView (v, f, ldim, list); \ + createListOf1DByteView (v, f, ldim, gdim, list); \ goto done; \ } @@ -80,10 +95,10 @@ void createIoFieldDescriptors (atlas::Field & f, std::vector & list return; } -void createIoFieldDescriptors (atlas::FieldSet & s, std::vector & list, size_t ldim) +void createIoFieldDescriptors (atlas::FieldSet & s, std::vector & list, size_t ldim, atlas::idx_t gdim) { for (auto & f : s) - createIoFieldDescriptors (f, list, ldim); + createIoFieldDescriptors (f, list, ldim, gdim); } diff --git a/src/tests/gatherscatter/ioFieldDesc.h b/src/tests/gatherscatter/ioFieldDesc.h index 13e370c2a..e1af0ceb1 100644 --- a/src/tests/gatherscatter/ioFieldDesc.h +++ b/src/tests/gatherscatter/ioFieldDesc.h @@ -90,5 +90,5 @@ class ioFieldDesc size_t _dlen; }; -void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim = 0); -void createIoFieldDescriptors (atlas::FieldSet & s, std::vector & list, size_t ldim = 0); +void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim = 0, atlas::idx_t gdim = -1); +void createIoFieldDescriptors (atlas::FieldSet & s, std::vector & list, size_t ldim = 0, atlas::idx_t gdim = -1); diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index 5fefeeb4f..0d0f89ecc 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -53,13 +53,13 @@ void getprcind (const atlas::functionspace::StructuredColumns & fs, const atlas: } template -void prff (const std::string & name, const atlas::FieldSet & sglo) +void prff (const std::string & name, const atlas::FieldSet & s) { auto & comm = mpi::comm (); int irank = comm.rank (); - for (int i = 0; i < sglo.size (); i++) + for (int i = 0; i < s.size (); i++) { - auto v = array::make_view (sglo[i]); + auto v = array::make_view (s[i]); if (v.size () == 0) continue; @@ -72,13 +72,134 @@ void prff (const std::string & name, const atlas::FieldSet & sglo) } } +template +void prff (const std::string & name, const atlas::Field & f) +{ + atlas::FieldSet s; + s.add (f); + prff (name, f); +} + }; //----------------------------------------------------------------------------- -CASE( "test_gatherscatter" ) +CASE( "test_gatherscatter_ngptotxnflevg" ) +{ + if (! eckit::Resource ("--ngptotxnflevg", false)) + return; + int nfield = eckit::Resource ("--fields", 3); + int nflevg = eckit::Resource ("--nflevg", 10); + atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); + bool gather (eckit::Resource ("--gather", false)); + bool scatter (eckit::Resource ("--scatter", false)); + bool check (eckit::Resource ("--check", false)); + + + auto & comm = mpi::comm (); + int irank = comm.rank (); + int nproc = comm.size (); + + atlas::grid::Distribution dist (grid, atlas::grid::Partitioner ("equal_regions")); + atlas::functionspace::StructuredColumns fs (grid, dist, atlas::util::Config ("halo", 1) + | atlas::util::Config ("periodic_points", true)); + std::vector prc, ind; + + if (check) + getprcind (fs, dist, prc, ind); + + atlas::FieldSet sloc; + atlas::FieldSet sglo1; + atlas::FieldSet sglo2; + + using T = long; + + const int ind_bit = 24, ind_off = 0; + const int prc_bit = 12, prc_off = ind_off + ind_bit; + const int fld_bit = 14, fld_off = prc_off + prc_bit; + const int lev_bit = 14, lev_off = fld_off + fld_bit; + + if (check) + { + ATLAS_ASSERT (fs.sizeOwned () < (1 << ind_bit)); + ATLAS_ASSERT (nproc < (1 << prc_bit)); + ATLAS_ASSERT (nfield < (1 << fld_bit)); + ATLAS_ASSERT (nflevg < (1 << lev_bit)); + } + + using T = long; + + auto func = [check,ind_off,prc_off,fld_off,lev_off] (int fld, int lev, int prc, int ind) + { + long v = 0; + if (check) + { + v = (static_cast (fld) << fld_off) + (static_cast (lev) << lev_off) + + (static_cast (prc) << prc_off) + (static_cast (ind) << ind_off); + } + return v; + }; + + atlas::Field floc ("field", atlas::array::DataType::kind (), {nfield, nflevg, grid.size ()}); + + + auto v = array::make_view (floc); + + for (int jfld = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++) + for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) + v (jfld, jlev, jloc) = func (jfld, jlev, irank, jloc); + + atlas::FieldSet sglo; + + for (int jfld = 0, count = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++, count++) + { + int owner = count % nproc; + std::string name = std::string ("#") + std::to_string (jfld) + std::string (",") + std::to_string (jlev); + atlas::Field fglo = atlas::Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); + fglo.metadata ().set ("owner", owner); + sglo.add (fglo); + } + + std::vector dloc; + std::vector dglo; + + createIoFieldDescriptors (floc, dloc, fs.sizeOwned ()); + createIoFieldDescriptors (sglo, dglo, fs.sizeOwned ()); + + for (auto & d : dglo) + d.field ().metadata ().get ("owner", d.owner ()); + + GatherScatter gs (dist); + gs.gather (dloc, dglo); + + + for (int jfld = 0, count = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++, count++) + { + atlas::Field fglo = sglo[count]; + int owner; fglo.metadata ().get ("owner", owner); + if (owner == irank) + { + auto v = array::make_view (fglo); + for (int jglo = 0; jglo < grid.size (); jglo++) + { + T v1 = v (jglo), v2 = func (jfld, jlev, prc[jglo], ind[jglo]); + EXPECT (v1 == v2); + } + } + } + + +} + +CASE( "test_gatherscatter_simple" ) { - int nfields = eckit::Resource ("--fields", 3); + if (! eckit::Resource ("--simple", false)) + return; + + int nfield = eckit::Resource ("--fields", 3); atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); bool gather1 (eckit::Resource ("--gather1", false)); bool gather2 (eckit::Resource ("--gather2", false)); @@ -114,7 +235,7 @@ CASE( "test_gatherscatter" ) { ATLAS_ASSERT (fs.sizeOwned () < (1 << ind_bit)); ATLAS_ASSERT (nproc < (1 << prc_bit)); - ATLAS_ASSERT (nfields < (1 << fld_bit)); + ATLAS_ASSERT (nfield < (1 << fld_bit)); } auto func = [check,ind_off,prc_off,fld_off] (int fld, int prc, int ind) @@ -168,7 +289,7 @@ CASE( "test_gatherscatter" ) } }; - for (int i = 0; i < nfields; i++) + for (int i = 0; i < nfield; i++) { int owner = i % nproc; @@ -209,7 +330,7 @@ CASE( "test_gatherscatter" ) if (debug) prff ("sglo1", sglo1); } - if (scatter2) + if (scatter1) { ATLAS_TRACE_SCOPE ("test_scatter1") { From 4908463ea0703edeab0f204dc6007c53f1874803 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 29 May 2020 11:31:30 +0000 Subject: [PATCH 45/58] Fiddle with templates --- src/tests/gatherscatter/arrayViewHelpers.h | 68 ++++++++++ src/tests/gatherscatter/ioFieldDesc.cc | 6 +- src/tests/gatherscatter/test_gatherscatter.cc | 120 +++++++++++++++++- 3 files changed, 190 insertions(+), 4 deletions(-) diff --git a/src/tests/gatherscatter/arrayViewHelpers.h b/src/tests/gatherscatter/arrayViewHelpers.h index c458e45dd..5132d6a33 100644 --- a/src/tests/gatherscatter/arrayViewHelpers.h +++ b/src/tests/gatherscatter/arrayViewHelpers.h @@ -84,5 +84,73 @@ addDummyDimension (const atlas::array::ArrayView & view) return atlas::array::ArrayView (data, shape, strides); } +// Apply a function to view elements + +#ifdef UNDEF +template +class filterView +{ +public: + template + static void apply (atlas::array::ArrayView & view, Func func) + { + constexpr int rank = Rank-1; + for (int i = 0; i < view.shape (0); i++) + { + auto v = dropDimension (view, 0, i); + filterView::apply (v, func); + } + } +}; + +template +class filterView<1, Value> +{ + template + static void apply (atlas::array::ArrayView & view, Func func) + { + for (int i = 0; i < view.size (); i++) + func (view (i)); + } +}; + +#endif + + +template +class arr +{ +public: + arr (atlas::array::ArrayView v) : view (v) {} + Value val; + atlas::array::ArrayView view; +}; + +template +class ww +{ +public: + template + static void toto (arr x, Func func) + { + constexpr int rank = Rank-1; + arr y (dropDimension (x.view, 0, 0)); + y.val = x.val; + ww::toto (y, func); + } +}; + +template +class ww<1, Value> +{ +public: + template + static void toto (arr x, Func func) + { + func (x.val); + std::cout << "coucou" << std::endl; + } +}; + diff --git a/src/tests/gatherscatter/ioFieldDesc.cc b/src/tests/gatherscatter/ioFieldDesc.cc index e1e85c585..73554d660 100644 --- a/src/tests/gatherscatter/ioFieldDesc.cc +++ b/src/tests/gatherscatter/ioFieldDesc.cc @@ -61,7 +61,8 @@ void createListOf1DByteView (atlas::array::ArrayView & view, }; -void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim, atlas::idx_t gdim) +void createIoFieldDescriptors + (atlas::Field & f, std::vector & list, size_t ldim, atlas::idx_t gdim) { int rank = f.rank (); auto type = f.datatype (); @@ -95,7 +96,8 @@ void createIoFieldDescriptors (atlas::Field & f, std::vector & list return; } -void createIoFieldDescriptors (atlas::FieldSet & s, std::vector & list, size_t ldim, atlas::idx_t gdim) +void createIoFieldDescriptors + (atlas::FieldSet & s, std::vector & list, size_t ldim, atlas::idx_t gdim) { for (auto & f : s) createIoFieldDescriptors (f, list, ldim, gdim); diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index 0d0f89ecc..6c1df0983 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -18,6 +18,7 @@ #include "GatherScatter.h" #include "ioFieldDesc.h" +#include "arrayViewHelpers.h" using namespace eckit; using namespace atlas::functionspace; @@ -84,6 +85,123 @@ void prff (const std::string & name, const atlas::Field & f) //----------------------------------------------------------------------------- +CASE( "test_gatherscatter_nflevgxngptot" ) +{ + if (! eckit::Resource ("--nflevgxngptot", false)) + return; + + int nfield = eckit::Resource ("--fields", 3); + int nflevg = eckit::Resource ("--nflevg", 10); + atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); + bool gather (eckit::Resource ("--gather", false)); + bool scatter (eckit::Resource ("--scatter", false)); + bool check (eckit::Resource ("--check", false)); + + + auto & comm = mpi::comm (); + int irank = comm.rank (); + int nproc = comm.size (); + + atlas::grid::Distribution dist (grid, atlas::grid::Partitioner ("equal_regions")); + atlas::functionspace::StructuredColumns fs (grid, dist, atlas::util::Config ("halo", 1) + | atlas::util::Config ("periodic_points", true)); + std::vector prc, ind; + + if (check) + getprcind (fs, dist, prc, ind); + + atlas::FieldSet sloc; + + using T = long; + + const int ind_bit = 24, ind_off = 0; + const int prc_bit = 12, prc_off = ind_off + ind_bit; + const int fld_bit = 14, fld_off = prc_off + prc_bit; + const int lev_bit = 14, lev_off = fld_off + fld_bit; + + if (check) + { + ATLAS_ASSERT (fs.sizeOwned () < (1 << ind_bit)); + ATLAS_ASSERT (nproc < (1 << prc_bit)); + ATLAS_ASSERT (nfield < (1 << fld_bit)); + ATLAS_ASSERT (nflevg < (1 << lev_bit)); + } + + using T = long; + + auto func = [check,ind_off,prc_off,fld_off,lev_off] (int fld, int lev, int prc, int ind) + { + long v = 0; + if (check) + { + v = (static_cast (fld) << fld_off) + (static_cast (lev) << lev_off) + + (static_cast (prc) << prc_off) + (static_cast (ind) << ind_off); + } + return v; + }; + + atlas::Field floc ("field", atlas::array::DataType::kind (), {nfield, grid.size (), nflevg}); + + auto v = array::make_view (floc); + + for (int jfld = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++) + for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) + v (jfld, jloc, jlev) = func (jfld, jlev, irank, jloc); + + atlas::FieldSet sglo; + + for (int jfld = 0, count = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++, count++) + { + int owner = count % nproc; + std::string name = std::string ("#") + std::to_string (jfld) + std::string (",") + std::to_string (jlev); + atlas::Field fglo = atlas::Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); + fglo.metadata ().set ("owner", owner); + sglo.add (fglo); + } + + std::vector dloc; + std::vector dglo; + + createIoFieldDescriptors (floc, dloc, fs.sizeOwned (), 1); + createIoFieldDescriptors (sglo, dglo, fs.sizeOwned ()); + + for (auto & d : dglo) + d.field ().metadata ().get ("owner", d.owner ()); + + GatherScatter gs (dist); + gs.gather (dloc, dglo); + + + for (int jfld = 0, count = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++, count++) + { + atlas::Field fglo = sglo[count]; + int owner; fglo.metadata ().get ("owner", owner); + if (owner == irank) + { + auto v = array::make_view (fglo); + for (int jglo = 0; jglo < grid.size (); jglo++) + { + T v1 = v (jglo), v2 = func (jfld, jlev, prc[jglo], ind[jglo]); + EXPECT (v1 == v2); + } + } + } + + { + auto v = array::make_view (floc); +// filterView<3,T>::apply (v, [] (T & t) { t = 0; }); + arr x (v); + x.val = 12345; + ww<3,T>::toto (x, [](double z){ std::cout << " z = " << z << std::endl;}); + + } + + +} + CASE( "test_gatherscatter_ngptotxnflevg" ) { if (! eckit::Resource ("--ngptotxnflevg", false)) @@ -109,8 +227,6 @@ CASE( "test_gatherscatter_ngptotxnflevg" ) getprcind (fs, dist, prc, ind); atlas::FieldSet sloc; - atlas::FieldSet sglo1; - atlas::FieldSet sglo2; using T = long; From 4bac9dad5d29fe1e7943c54ac3f5161c905bce92 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 29 May 2020 11:39:17 +0000 Subject: [PATCH 46/58] Fiddle with templates --- src/tests/gatherscatter/arrayViewHelpers.h | 56 +++---------------- src/tests/gatherscatter/test_gatherscatter.cc | 5 +- 2 files changed, 10 insertions(+), 51 deletions(-) diff --git a/src/tests/gatherscatter/arrayViewHelpers.h b/src/tests/gatherscatter/arrayViewHelpers.h index 5132d6a33..6a270cc4e 100644 --- a/src/tests/gatherscatter/arrayViewHelpers.h +++ b/src/tests/gatherscatter/arrayViewHelpers.h @@ -86,69 +86,31 @@ addDummyDimension (const atlas::array::ArrayView & view) // Apply a function to view elements -#ifdef UNDEF template -class filterView +class filterViewHelper { public: template - static void apply (atlas::array::ArrayView & view, Func func) + static void apply (atlas::array::ArrayView x, Func func) { constexpr int rank = Rank-1; - for (int i = 0; i < view.shape (0); i++) + for (int i = 0; i < x.shape (0); i++) { - auto v = dropDimension (view, 0, i); - filterView::apply (v, func); + atlas::array::ArrayView y = dropDimension (x, 0, i); + filterViewHelper::apply (y, func); } } }; template -class filterView<1, Value> -{ - template - static void apply (atlas::array::ArrayView & view, Func func) - { - for (int i = 0; i < view.size (); i++) - func (view (i)); - } -}; - -#endif - - -template -class arr -{ -public: - arr (atlas::array::ArrayView v) : view (v) {} - Value val; - atlas::array::ArrayView view; -}; - -template -class ww -{ -public: - template - static void toto (arr x, Func func) - { - constexpr int rank = Rank-1; - arr y (dropDimension (x.view, 0, 0)); - y.val = x.val; - ww::toto (y, func); - } -}; - -template -class ww<1, Value> +class filterViewHelper<1, Value> { public: template - static void toto (arr x, Func func) + static void apply (atlas::array::ArrayView x, Func func) { - func (x.val); - std::cout << "coucou" << std::endl; + for (int i = 0; i < x.shape (0); i++) + func (x (i)); } }; diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index 6c1df0983..60d493de4 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -192,10 +192,7 @@ CASE( "test_gatherscatter_nflevgxngptot" ) { auto v = array::make_view (floc); -// filterView<3,T>::apply (v, [] (T & t) { t = 0; }); - arr x (v); - x.val = 12345; - ww<3,T>::toto (x, [](double z){ std::cout << " z = " << z << std::endl;}); + filterViewHelper<3,T>::apply (v, [](T & z){ z = 0; }); } From 00c96410867b3738076f4565cb57b9da53460000 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 29 May 2020 11:49:48 +0000 Subject: [PATCH 47/58] Fiddle with templates --- src/tests/gatherscatter/arrayViewHelpers.h | 20 ++++++++++++------- src/tests/gatherscatter/test_gatherscatter.cc | 3 +-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/tests/gatherscatter/arrayViewHelpers.h b/src/tests/gatherscatter/arrayViewHelpers.h index 6a270cc4e..cee5a36e4 100644 --- a/src/tests/gatherscatter/arrayViewHelpers.h +++ b/src/tests/gatherscatter/arrayViewHelpers.h @@ -91,13 +91,13 @@ class filterViewHelper { public: template - static void apply (atlas::array::ArrayView x, Func func) + static void apply (atlas::array::ArrayView view, Func func) { constexpr int rank = Rank-1; - for (int i = 0; i < x.shape (0); i++) + for (int i = 0; i < view.shape (0); i++) { - atlas::array::ArrayView y = dropDimension (x, 0, i); - filterViewHelper::apply (y, func); + atlas::array::ArrayView v = dropDimension (view, 0, i); + filterViewHelper::apply (v, func); } } }; @@ -107,12 +107,18 @@ class filterViewHelper<1, Value> { public: template - static void apply (atlas::array::ArrayView x, Func func) + static void apply (atlas::array::ArrayView view, Func func) { - for (int i = 0; i < x.shape (0); i++) - func (x (i)); + for (int i = 0; i < view.shape (0); i++) + func (view (i)); } }; +template +void filterView (atlas::array::ArrayView view, Func func) +{ + filterViewHelper::apply (view, func); +} + diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index 60d493de4..734ce2ec4 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -192,8 +192,7 @@ CASE( "test_gatherscatter_nflevgxngptot" ) { auto v = array::make_view (floc); - filterViewHelper<3,T>::apply (v, [](T & z){ z = 0; }); - + filterView (v, [](T & z){ z = 0; }); } From 81cf89e7aa8d00863f14dbfde87ab53247356d95 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 29 May 2020 12:26:17 +0000 Subject: [PATCH 48/58] Test gather --- src/tests/gatherscatter/test_gatherscatter.cc | 79 +++++++++++++------ 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index 734ce2ec4..813c3bedb 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -140,61 +140,87 @@ CASE( "test_gatherscatter_nflevgxngptot" ) return v; }; - atlas::Field floc ("field", atlas::array::DataType::kind (), {nfield, grid.size (), nflevg}); + + // Distributed field, Fortran dimensions (1:NFLEVG,1:NGPTOT,1:NFIELDS) + atlas::Field floc ("field", atlas::array::DataType::kind (), {nfield, fs.size (), nflevg}); auto v = array::make_view (floc); - for (int jfld = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++) - for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) - v (jfld, jloc, jlev) = func (jfld, jlev, irank, jloc); + if (check) + { + for (int jfld = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++) + for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) + v (jfld, jloc, jlev) = func (jfld, jlev, irank, jloc); + } + // Gather our multi-field, multi-level Atlas field to a set of fields (1:NGPTOTG) atlas::FieldSet sglo; for (int jfld = 0, count = 0; jfld < nfield; jfld++) for (int jlev = 0; jlev < nflevg; jlev++, count++) { - int owner = count % nproc; + int owner = count % nproc; // RR distribution std::string name = std::string ("#") + std::to_string (jfld) + std::string (",") + std::to_string (jlev); atlas::Field fglo = atlas::Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); fglo.metadata ().set ("owner", owner); sglo.add (fglo); } + // IO descriptors std::vector dloc; std::vector dglo; - createIoFieldDescriptors (floc, dloc, fs.sizeOwned (), 1); - createIoFieldDescriptors (sglo, dglo, fs.sizeOwned ()); + createIoFieldDescriptors (floc, dloc, fs.sizeOwned (), 1); // Grid dimension is 1 + createIoFieldDescriptors (sglo, dglo, fs.sizeOwned ()); // Default for grid dimension is inner dimension + // Set target processor for all fields for (auto & d : dglo) d.field ().metadata ().get ("owner", d.owner ()); GatherScatter gs (dist); - gs.gather (dloc, dglo); + // Gather - for (int jfld = 0, count = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++, count++) + if (gather) { - atlas::Field fglo = sglo[count]; - int owner; fglo.metadata ().get ("owner", owner); - if (owner == irank) - { - auto v = array::make_view (fglo); - for (int jglo = 0; jglo < grid.size (); jglo++) - { - T v1 = v (jglo), v2 = func (jfld, jlev, prc[jglo], ind[jglo]); - EXPECT (v1 == v2); - } - } + gs.gather (dloc, dglo); + + if (check) + for (int jfld = 0, count = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++, count++) + { + atlas::Field fglo = sglo[count]; + int owner; fglo.metadata ().get ("owner", owner); + if (owner == irank) + { + auto v = array::make_view (fglo); + for (int jglo = 0; jglo < grid.size (); jglo++) + { + T v1 = v (jglo), v2 = func (jfld, jlev, prc[jglo], ind[jglo]); + EXPECT (v1 == v2); + } + } + } } - { - auto v = array::make_view (floc); - filterView (v, [](T & z){ z = 0; }); - } + // Scatter + if (scatter) + { + // Set distributed field to zero + if (check) + filterView (v, [](T & z){ z = 0; }); + gs.scatter (dglo, dloc); + if (check) + for (int jfld = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++) + for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) + { + T v1 = v (jfld, jloc, jlev), v2 = func (jfld, jlev, irank, jloc); + EXPECT (v1 == v2); + } + } } @@ -284,6 +310,7 @@ CASE( "test_gatherscatter_ngptotxnflevg" ) d.field ().metadata ().get ("owner", d.owner ()); GatherScatter gs (dist); + gs.gather (dloc, dglo); From 3f14811db234a509532b8ebd2c16ef6893d8259d Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Fri, 29 May 2020 12:46:27 +0000 Subject: [PATCH 49/58] Test gather/scatter options --- src/tests/gatherscatter/test_gatherscatter.cc | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index 813c3bedb..d7a334dfb 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -144,14 +144,14 @@ CASE( "test_gatherscatter_nflevgxngptot" ) // Distributed field, Fortran dimensions (1:NFLEVG,1:NGPTOT,1:NFIELDS) atlas::Field floc ("field", atlas::array::DataType::kind (), {nfield, fs.size (), nflevg}); - auto v = array::make_view (floc); + auto vloc = array::make_view (floc); if (check) { for (int jfld = 0; jfld < nfield; jfld++) for (int jlev = 0; jlev < nflevg; jlev++) for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) - v (jfld, jloc, jlev) = func (jfld, jlev, irank, jloc); + vloc (jfld, jloc, jlev) = func (jfld, jlev, irank, jloc); } // Gather our multi-field, multi-level Atlas field to a set of fields (1:NGPTOTG) @@ -208,16 +208,34 @@ CASE( "test_gatherscatter_nflevgxngptot" ) if (scatter) { - // Set distributed field to zero if (check) - filterView (v, [](T & z){ z = 0; }); + { + // Set distributed field to zero + filterView (vloc, [](T & z){ z = 0; }); + + // Compute global fields + for (int jfld = 0, count = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++, count++) + { + atlas::Field fglo = sglo[count]; + int owner; fglo.metadata ().get ("owner", owner); + if (owner == irank) + { + auto v = array::make_view (fglo); + for (int jglo = 0; jglo < grid.size (); jglo++) + v (jglo) = func (jfld, jlev, prc[jglo], ind[jglo]); + } + } + } + gs.scatter (dglo, dloc); + if (check) for (int jfld = 0; jfld < nfield; jfld++) for (int jlev = 0; jlev < nflevg; jlev++) for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) { - T v1 = v (jfld, jloc, jlev), v2 = func (jfld, jlev, irank, jloc); + T v1 = vloc (jfld, jloc, jlev), v2 = func (jfld, jlev, irank, jloc); EXPECT (v1 == v2); } } From 6932a92eda5d169ac520ef98bdebcd5d3efb97a2 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 3 Jun 2020 12:39:23 +0000 Subject: [PATCH 50/58] More Atlas traces --- src/tests/gatherscatter/GatherScatter.cc | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/tests/gatherscatter/GatherScatter.cc b/src/tests/gatherscatter/GatherScatter.cc index a71afe204..058c7ed8f 100644 --- a/src/tests/gatherscatter/GatherScatter.cc +++ b/src/tests/gatherscatter/GatherScatter.cc @@ -276,18 +276,26 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") byte_v buf_loc (tloc.fld.back ().off); processLocBuffer (floc, tloc, buf_loc, pack); + ATLAS_TRACE_SCOPE ("barrier") + { comm.barrier (); + } std::vector rqs = postSend (buf_loc, tloc); + ATLAS_TRACE_SCOPE ("waitRecv") + { for (auto & r : rqr) comm.wait (r); + } processGloBuffer (fglo, tglo, buf_glo, unpack); + ATLAS_TRACE_SCOPE ("waitSend") + { for (auto & r : rqs) comm.wait (r); - + }; } } @@ -312,17 +320,26 @@ ATLAS_TRACE_SCOPE ("GatherScatter::scatter") byte_v buf_glo (tglo.prc.back ().off); processGloBuffer (fglo, tglo, buf_glo, pack); + ATLAS_TRACE_SCOPE ("barrier") + { comm.barrier (); + } std::vector rqs = postSend (buf_glo, tglo); + ATLAS_TRACE_SCOPE ("waitRecv") + { for (auto & r : rqr) - comm.wait (r); + comm.wait (r); + } processLocBuffer (floc, tloc, buf_loc, unpack); + ATLAS_TRACE_SCOPE ("waitSend") + { for (auto & r : rqs) comm.wait (r); + } } } From b1179c548b8e3a5879bf245435f31bf695334af7 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 3 Jun 2020 14:48:47 +0000 Subject: [PATCH 51/58] Prepare for NPROMA blocks --- src/tests/gatherscatter/GatherScatter.cc | 18 +-- src/tests/gatherscatter/ioFieldDesc.cc | 94 ++++++++++++++- src/tests/gatherscatter/ioFieldDesc.h | 48 +++++--- .../gatherscatter/test_arrayViewHelpers.cc | 109 ++++++------------ src/tests/gatherscatter/test_gatherscatter.cc | 106 ++++++++++++++++- 5 files changed, 267 insertions(+), 108 deletions(-) diff --git a/src/tests/gatherscatter/GatherScatter.cc b/src/tests/gatherscatter/GatherScatter.cc index 058c7ed8f..2756a08ce 100644 --- a/src/tests/gatherscatter/GatherScatter.cc +++ b/src/tests/gatherscatter/GatherScatter.cc @@ -136,7 +136,7 @@ GatherScatter::fldprc_t GatherScatter::computeTGlo (const ioFieldDesc_v & fglo) for (atlas::idx_t jfld = 0; jfld < nfld; jfld++) if (lprc == fglo[jfld].owner ()) - tglo.fld[jfld].len = fglo[jfld].dlen (); + tglo.fld[jfld].len = fglo[jfld].dlength (); integrate (tglo.fld); @@ -162,16 +162,16 @@ void GatherScatter::processLocBuffer (ioFieldDesc_v & floc, const fldprc_t & tlo { auto & f = floc[jfld]; byte * buffer = &buf_loc[tloc.fld[jfld].off]; - const size_t dlen = f.dlen (); - const size_t ldim = f.ldim (); - const size_t nblk = f.nblk (); + const size_t dlength = f.dlength (); + const size_t ngptot = f.ngptot (); + const size_t ngpblks = f.ngpblks (); -auto jlonjblk2jgp = [] (atlas::idx_t jlon, atlas::idx_t jblk) { ATLAS_ASSERT (jblk == 0); return jlon; }; + auto jlonjblk2jgp = [] (atlas::idx_t jlon, atlas::idx_t jblk) { ATLAS_ASSERT (jblk == 0); return jlon; }; - for (atlas::idx_t jblk = 0; jblk < nblk; jblk++) - for (atlas::idx_t jlon = 0; jlon < ldim; jlon++) - for (int j = 0; j < dlen; j++) - a (buffer[jlonjblk2jgp (jlon, jblk)*dlen+j], f (jblk, jlon, j)); + for (atlas::idx_t jblk = 0; jblk < ngpblks; jblk++) + for (atlas::idx_t jlon = 0; jlon < ngptot; jlon++) + for (int j = 0; j < dlength; j++) + a (buffer[jlonjblk2jgp (jlon, jblk)*dlength+j], f (jblk, jlon, j)); } } diff --git a/src/tests/gatherscatter/ioFieldDesc.cc b/src/tests/gatherscatter/ioFieldDesc.cc index 73554d660..2c17af556 100644 --- a/src/tests/gatherscatter/ioFieldDesc.cc +++ b/src/tests/gatherscatter/ioFieldDesc.cc @@ -1,12 +1,15 @@ #include "ioFieldDesc.h" #include "arrayViewHelpers.h" +#include "atlas/runtime/Exception.h" namespace { // The following templates create a list of byte views of rank 2 from a view of any rank, any type -// + + +// Non-blocked (1:NGPTOT) template void listOf1DByteView (atlas::array::ArrayView & view, @@ -58,9 +61,96 @@ void createListOf1DByteView (atlas::array::ArrayView & view, listOf1DByteView (v, std::vector (), f, ldim, gdim, list); } +// Blocked (1:NPROMA,1:NGPBLKS) + +template +void listOf1DByteViewBlocked + (atlas::array::ArrayView & view, + const std::vector & _ind, + const atlas::Field & f, atlas::idx_t bdim, atlas::idx_t gdim, size_t ldim, + std::vector & list) +{ + static_assert (Rank > 3, "listOf1DByteViewBlocked should be called with views having a Rank > 3"); + + std::vector ind = _ind; + ind.push_back (0); + + + // First dimension is block + if (bdim == 0) + { + // Grid dimension is second + if (gdim == 1) + { + // Drop dimensions after grid dimension + for (int i = 0; i < view.shape (2); i++) + { + auto v = dropDimension (view, 2, i); + ind.back () = i; + listOf1DByteViewBlocked (v, ind, f, bdim, gdim, ldim, list); + } + } + else + { + // Remove second dimension + for (int i = 0; i < view.shape (1); i++) + { + auto v = dropDimension (view, 1, i); + ind.back () = i; + listOf1DByteViewBlocked (v, ind, f, bdim, gdim-1, ldim, list); + } + } + } + else + { + // Remove another leading dimension + for (int i = 0; i < view.shape (0); i++) + { + auto v = dropDimension (view, 0, i); + ind.back () = i; + listOf1DByteViewBlocked (v, ind, f, bdim-1, gdim-1, ldim, list); + } + } + +} + +template <> +void listOf1DByteViewBlocked + (atlas::array::ArrayView & view, + const std::vector & ind, + const atlas::Field & f, atlas::idx_t bdim, atlas::idx_t gdim, size_t ldim, + std::vector & list) +{ + list.push_back (ioFieldDesc (view, ind, f, ldim)); +} + +template +void createListOf1DByteViewBlocked (atlas::array::ArrayView & view, + const atlas::Field & f, atlas::idx_t bdim, atlas::idx_t gdim, + size_t ldim, std::vector & list) +{ + auto v = byteView (view); + listOf1DByteViewBlocked (v, std::vector (), f, bdim, gdim, ldim, list); +} + }; +void createIoFieldDescriptorsBlocked + (atlas::Field & f, std::vector & list, atlas::idx_t bdim, atlas::idx_t gdim, size_t ldim) +{ + int rank = f.rank (); + auto type = f.datatype (); + + if (gdim < 0) + gdim = gdim + rank; + + auto v = atlas::array::make_view (f); + + createListOf1DByteViewBlocked (v, f, bdim, gdim, ldim, list); +} + + void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim, atlas::idx_t gdim) { @@ -91,6 +181,8 @@ void createIoFieldDescriptors HANDLE_TYPE (int); HANDLE_TYPE (float); + atlas::throw_NotImplemented ("createIoFieldDescriptors type/rank", Here ()); + done: return; diff --git a/src/tests/gatherscatter/ioFieldDesc.h b/src/tests/gatherscatter/ioFieldDesc.h index e1af0ceb1..845354cd9 100644 --- a/src/tests/gatherscatter/ioFieldDesc.h +++ b/src/tests/gatherscatter/ioFieldDesc.h @@ -13,14 +13,15 @@ class ioFieldDesc public: ioFieldDesc (atlas::array::ArrayView & v, const std::vector & ind, - const atlas::Field & f, size_t ldim) - : _v (v), _ind (ind), _f (f), _ldim (ldim) + const atlas::Field & f, size_t ngptot) + : _v (v), _ind (ind), _f (f), _ngptot (ngptot) { - _nblk = _v.shape (0); - _dlen = _v.shape (2); - if (_ldim == 0) - _ldim = _v.shape (1); - _size = _nblk * _ldim * _dlen; + _ngpblks = _v.shape (0); + _nproma = _v.shape (1); + _dlength = _v.shape (2); + if (_ngptot == 0) + _ngptot = _ngpblks * _nproma; + _size = _ngptot * _dlength; } @@ -54,19 +55,24 @@ class ioFieldDesc return _size; } - size_t nblk () const + size_t ngpblks () const { - return _nblk; + return _ngpblks; } - size_t ldim () const + size_t ngptot () const { - return _ldim; + return _ngptot; } - size_t dlen () const + size_t nproma () const { - return _dlen; + return _nproma; + } + + size_t dlength () const + { + return _dlength; } byte & operator () (int jblk, int jlon, int k) @@ -84,11 +90,15 @@ class ioFieldDesc const std::vector _ind; const atlas::Field & _f; int _owner = 0; - size_t _ldim; - size_t _nblk; - size_t _size; - size_t _dlen; + size_t _ngptot; // Total number of elements in a distributed field + size_t _nproma; // Blocking factor; may be equal to NGPTOT + size_t _ngpblks; // Number of blocks + size_t _size; // Size in bytes + size_t _dlength; // Element length }; -void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ldim = 0, atlas::idx_t gdim = -1); -void createIoFieldDescriptors (atlas::FieldSet & s, std::vector & list, size_t ldim = 0, atlas::idx_t gdim = -1); +void createIoFieldDescriptorsBlocked + (atlas::Field & f, std::vector & list, atlas::idx_t bdim, atlas::idx_t gdim = -1, size_t ngptot = 0); + +void createIoFieldDescriptors (atlas::Field & f, std::vector & list, size_t ngptot = 0, atlas::idx_t gdim = -1); +void createIoFieldDescriptors (atlas::FieldSet & s, std::vector & list, size_t ngptot = 0, atlas::idx_t gdim = -1); diff --git a/src/tests/gatherscatter/test_arrayViewHelpers.cc b/src/tests/gatherscatter/test_arrayViewHelpers.cc index 95b0f2166..55ac1b499 100644 --- a/src/tests/gatherscatter/test_arrayViewHelpers.cc +++ b/src/tests/gatherscatter/test_arrayViewHelpers.cc @@ -17,96 +17,55 @@ void prss (const std::string & t, const V & v) int main (int argc, char * argv[]) { - atlas::Field f ("f", atlas::array::DataType::kind (), {5, 7}); + const int ngpblks = 10, nflevg = 20, nproma = 16; - auto v = atlas::array::make_view (f); + const int ngptot = ngpblks * nproma; - prss ("v", v); + atlas::Field f ("f", atlas::array::DataType::kind (), {ngpblks, nflevg, nproma}); - for (int i = 0; i < v.shape ()[0]; i++) - for (int j = 0; j < v.shape ()[1]; j++) - v (i, j) = i * 100 + j; + auto v = atlas::array::make_view (f); - - printf (" &v(0,0) = 0x%llx\n", &v(0,0)); - printf (" &v(1,0) = 0x%llx\n", &v(1,0)); - printf (" &v(0,1) = 0x%llx\n", &v(0,1)); - - auto c = byteView (v); - - std::vector list; - - createIoFieldDescriptors (f, list); - - std::cout << " list.size () = " << list.size () << std::endl; - - prss ("c", c); - - printf (" sizeof (c (0,0)) = %lu\n", sizeof (c (0,0))); - - for (int i = 0; i < 4; i++) - printf (" &c(0,0,%d) = 0x%llx\n", i, &c(0,0,i)); - - for (int i = 0; i < 4; i++) - printf (" &c(0,%d,0) = 0x%llx\n", i, &c(0,i,0)); - - for (int i = 0; i < 4; i++) - printf (" &c(%d,0,0) = 0x%llx\n", i, &c(i,0,0)); - - -if(1) - for (int i = 0; i < 3; i++) - { - c (i, i, 0) = 0xff; - c (i, i, 1) = 0xff; - c (i, i, 2) = 0xff; - c (i, i, 3) = 0xff; - c (i, i, 4) = 0xff; - c (i, i, 5) = 0xff; - c (i, i, 6) = 0xff; - c (i, i, 7) = 0xff; - } - - printf (" %8s |", ""); - for (int j = 0; j < v.shape ()[1]; j++) - printf (" %12d", j); + printf (" shape = "); + for (int i = 0; i < v.rank (); i++) + printf (" %8d", v.shape (i)); printf ("\n"); - for (int i = 0; i < v.shape ()[0]; i++) - { - printf (" %8d |", i); - for (int j = 0; j < v.shape ()[1]; j++) - printf (" %12d", v (i, j)); - printf ("\n"); - } - + for (int jblk = 0; jblk < ngpblks; jblk++) + for (int jlev = 0, jloc = 0; jlev < nflevg; jlev++) + for (int jlon = 0; jlon < nproma; jlon++) + v (jblk, jlev, jlon) = 1000 * jlev + jlon + jblk * nproma; - auto v1 = dropDimension (v, -1, 0); + std::vector df; + createIoFieldDescriptorsBlocked (f, df, 0, 2, ngptot); // NGPBLKS dimension, NPROMA dimension, NGPTOT - prss ("v1", v1); - - std::cout << " v1.rank () = " << v1.rank () << std::endl; + for (int i = 0; i < df.size (); i++) + { + auto & d = df[i]; + auto & v = d.view (); - for (int i = 0; i < v1.shape (0); i++) - printf (" %8d > %12d\n", i, v1 (i)); - + printf (" %8d | %8d | %8d | %8d | %8d\n", i, v.rank (), v.shape (0), v.shape (1), v.shape (2)); - auto v2 = dropDimension (v, -1, 1); + if (i == 3) + { + for (int jblk = 0; jblk < v.shape (0); jblk++) + for (int jlon = 0; jlon < v.shape (1); jlon++) + { + long x = 0; + for (int j = 0; j < 8; j++) + { + byte * b = (byte *)&x + j; + *b = v (jblk, jlon, j); + } + printf (" %8d", x); + } + printf ("\n"); + } - std::cout << " v2.rank () = " << v2.rank () << std::endl; - for (int i = 0; i < v2.shape (0); i++) - printf (" %8d > %12d\n", i, v2 (i)); - - auto v3 = dropDimension (v, 0, 2); - std::cout << " v3.rank () = " << v3.rank () << std::endl; + } - prss ("v3", v3); - for (int i = 0; i < v3.shape (0); i++) - printf (" %8d > %12d\n", i, v3 (i)); - return 0; diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index d7a334dfb..9855d697c 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -85,9 +85,107 @@ void prff (const std::string & name, const atlas::Field & f) //----------------------------------------------------------------------------- -CASE( "test_gatherscatter_nflevgxngptot" ) +CASE( "test_gatherscatter_NPROMAxNFLEVGxNGPBLKS" ) { - if (! eckit::Resource ("--nflevgxngptot", false)) + if (! eckit::Resource ("--NPROMAxNFLEVGxNGPBLKS", false)) + return; + + int nproma = eckit::Resource ("--nproma", 8); + int nflevg = eckit::Resource ("--nflevg", 10); + bool gather (eckit::Resource ("--gather", false)); + bool scatter (eckit::Resource ("--scatter", false)); + bool check (eckit::Resource ("--check", false)); + + + atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); + + auto & comm = mpi::comm (); + int irank = comm.rank (); + int nproc = comm.size (); + + atlas::grid::Distribution dist (grid, atlas::grid::Partitioner ("equal_regions")); + atlas::functionspace::StructuredColumns fs (grid, dist, atlas::util::Config ("halo", 1) + | atlas::util::Config ("periodic_points", true)); + + int ngptot = fs.sizeOwned (); + int ngpblks = ngptot / nproma; + + if (fs.sizeOwned () % nproma) + ngpblks++; + + std::vector prc, ind; + + if (check) + getprcind (fs, dist, prc, ind); + + atlas::FieldSet sloc; + + using T = long; + + const int ind_bit = 21, ind_off = 0; + const int prc_bit = 21, prc_off = ind_off + ind_bit; + const int lev_bit = 22, lev_off = prc_off + prc_bit; + + if (check) + { + ATLAS_ASSERT (fs.sizeOwned () < (1 << ind_bit)); + ATLAS_ASSERT (nproc < (1 << prc_bit)); + ATLAS_ASSERT (nflevg < (1 << lev_bit)); + } + + using T = long; + + auto func = [check,ind_off,prc_off,lev_off] (int lev, int prc, int ind) + { + long v = 0; + if (check) + { + v = (static_cast (lev) << lev_off) + + (static_cast (prc) << prc_off) + + (static_cast (ind) << ind_off); + } + return v; + }; + + // Distributed field, Fortran dimensions (1:NPROMA,1:NFLEVG,1:NGPBLKS) + atlas::Field floc ("field", atlas::array::DataType::kind (), {nproma, nflevg, ngpblks}); + + auto vloc = array::make_view (floc); + + if (check) + { + for (int jblk = 0; jblk < ngpblks; jblk++) + { + const int jidia = 0, jfdia = std::min (nproma, ngptot - jblk * nproma); + for (int jlev = 0; jlev < nflevg; jlev++) + for (int jlon = jidia; jlon < jfdia; jlon++) + vloc (jlon, jlev, jblk) = func (jlev, irank, jlon + jblk * nproma); + } + } + + // Gather our multi-field, multi-level Atlas field to a set of fields (1:NGPTOTG) + atlas::FieldSet sglo; + + for (int jlev = 0; jlev < nflevg; jlev++) + { + int owner = jlev % nproc; // RR distribution + std::string name = std::string ("#") + std::to_string (jlev); + atlas::Field fglo = atlas::Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); + fglo.metadata ().set ("owner", owner); + sglo.add (fglo); + } + + // IO descriptors + std::vector dloc; + std::vector dglo; + + createIoFieldDescriptors (sglo, dglo, fs.sizeOwned ()); // Default for grid dimension is inner dimension + +} + +CASE( "test_gatherscatter_NFLEVGxNGPTOT" ) +{ + if (! eckit::Resource ("--NFLEVGxNGPTOT", false)) return; int nfield = eckit::Resource ("--fields", 3); @@ -242,9 +340,9 @@ CASE( "test_gatherscatter_nflevgxngptot" ) } -CASE( "test_gatherscatter_ngptotxnflevg" ) +CASE( "test_gatherscatter_NGPTOTxNFLEVG" ) { - if (! eckit::Resource ("--ngptotxnflevg", false)) + if (! eckit::Resource ("--NGPTOTxNFLEVG", false)) return; int nfield = eckit::Resource ("--fields", 3); int nflevg = eckit::Resource ("--nflevg", 10); From 412ae85433ff42a5185600f8534b606889ff6d0b Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 3 Jun 2020 15:22:57 +0000 Subject: [PATCH 52/58] Prepare for NPROMA blocks --- src/tests/gatherscatter/GatherScatter.cc | 17 +++++--- src/tests/gatherscatter/ioFieldDesc.cc | 42 +++++++++---------- src/tests/gatherscatter/test_gatherscatter.cc | 8 ++-- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/tests/gatherscatter/GatherScatter.cc b/src/tests/gatherscatter/GatherScatter.cc index 2756a08ce..bf96c398f 100644 --- a/src/tests/gatherscatter/GatherScatter.cc +++ b/src/tests/gatherscatter/GatherScatter.cc @@ -163,15 +163,20 @@ void GatherScatter::processLocBuffer (ioFieldDesc_v & floc, const fldprc_t & tlo auto & f = floc[jfld]; byte * buffer = &buf_loc[tloc.fld[jfld].off]; const size_t dlength = f.dlength (); - const size_t ngptot = f.ngptot (); + const size_t ngptot = f.ngptot (); + const size_t nproma = f.nproma (); const size_t ngpblks = f.ngpblks (); - auto jlonjblk2jgp = [] (atlas::idx_t jlon, atlas::idx_t jblk) { ATLAS_ASSERT (jblk == 0); return jlon; }; - for (atlas::idx_t jblk = 0; jblk < ngpblks; jblk++) - for (atlas::idx_t jlon = 0; jlon < ngptot; jlon++) - for (int j = 0; j < dlength; j++) - a (buffer[jlonjblk2jgp (jlon, jblk)*dlength+j], f (jblk, jlon, j)); + { + const int jidia = 0, jfdia = std::min (nproma, ngptot - jblk * nproma); + for (atlas::idx_t jlon = jidia; jlon < jfdia; jlon++) + { + atlas::idx_t k = (jlon+jblk*ngptot)*dlength; + for (int j = 0; j < dlength; j++) + a (buffer[k+j], f (jblk, jlon, j)); + } + } } } diff --git a/src/tests/gatherscatter/ioFieldDesc.cc b/src/tests/gatherscatter/ioFieldDesc.cc index 2c17af556..52d9c6b4b 100644 --- a/src/tests/gatherscatter/ioFieldDesc.cc +++ b/src/tests/gatherscatter/ioFieldDesc.cc @@ -14,7 +14,7 @@ namespace template void listOf1DByteView (atlas::array::ArrayView & view, const std::vector & _ind, - const atlas::Field & f, size_t ldim, atlas::idx_t gdim, + const atlas::Field & f, size_t ngptot, atlas::idx_t gdim, std::vector & list) { static_assert (Rank > 2, "listOf1DByteView should be called with views having a Rank > 2"); @@ -28,7 +28,7 @@ void listOf1DByteView (atlas::array::ArrayView & view, { auto v = dropDimension (view, 1, i); ind.back () = i; - listOf1DByteView (v, ind, f, ldim, 0, list); + listOf1DByteView (v, ind, f, ngptot, 0, list); } } else @@ -37,7 +37,7 @@ void listOf1DByteView (atlas::array::ArrayView & view, { auto v = dropDimension (view, 0, i); ind.back () = i; - listOf1DByteView (v, ind, f, ldim, gdim-1, list); + listOf1DByteView (v, ind, f, ngptot, gdim-1, list); } } } @@ -45,20 +45,20 @@ void listOf1DByteView (atlas::array::ArrayView & view, template <> void listOf1DByteView (atlas::array::ArrayView & view, const std::vector & ind, - const atlas::Field & f, size_t ldim, atlas::idx_t gdim, + const atlas::Field & f, size_t ngptot, atlas::idx_t gdim, std::vector & list) { auto v = addDummyDimension (view); - list.push_back (ioFieldDesc (v, ind, f, ldim)); + list.push_back (ioFieldDesc (v, ind, f, ngptot)); } template void createListOf1DByteView (atlas::array::ArrayView & view, - const atlas::Field & f, size_t ldim, atlas::idx_t gdim, + const atlas::Field & f, size_t ngptot, atlas::idx_t gdim, std::vector & list) { auto v = byteView (view); - listOf1DByteView (v, std::vector (), f, ldim, gdim, list); + listOf1DByteView (v, std::vector (), f, ngptot, gdim, list); } // Blocked (1:NPROMA,1:NGPBLKS) @@ -67,7 +67,7 @@ template void listOf1DByteViewBlocked (atlas::array::ArrayView & view, const std::vector & _ind, - const atlas::Field & f, atlas::idx_t bdim, atlas::idx_t gdim, size_t ldim, + const atlas::Field & f, atlas::idx_t bdim, atlas::idx_t gdim, size_t ngptot, std::vector & list) { static_assert (Rank > 3, "listOf1DByteViewBlocked should be called with views having a Rank > 3"); @@ -87,7 +87,7 @@ void listOf1DByteViewBlocked { auto v = dropDimension (view, 2, i); ind.back () = i; - listOf1DByteViewBlocked (v, ind, f, bdim, gdim, ldim, list); + listOf1DByteViewBlocked (v, ind, f, bdim, gdim, ngptot, list); } } else @@ -97,7 +97,7 @@ void listOf1DByteViewBlocked { auto v = dropDimension (view, 1, i); ind.back () = i; - listOf1DByteViewBlocked (v, ind, f, bdim, gdim-1, ldim, list); + listOf1DByteViewBlocked (v, ind, f, bdim, gdim-1, ngptot, list); } } } @@ -108,7 +108,7 @@ void listOf1DByteViewBlocked { auto v = dropDimension (view, 0, i); ind.back () = i; - listOf1DByteViewBlocked (v, ind, f, bdim-1, gdim-1, ldim, list); + listOf1DByteViewBlocked (v, ind, f, bdim-1, gdim-1, ngptot, list); } } @@ -118,26 +118,26 @@ template <> void listOf1DByteViewBlocked (atlas::array::ArrayView & view, const std::vector & ind, - const atlas::Field & f, atlas::idx_t bdim, atlas::idx_t gdim, size_t ldim, + const atlas::Field & f, atlas::idx_t bdim, atlas::idx_t gdim, size_t ngptot, std::vector & list) { - list.push_back (ioFieldDesc (view, ind, f, ldim)); + list.push_back (ioFieldDesc (view, ind, f, ngptot)); } template void createListOf1DByteViewBlocked (atlas::array::ArrayView & view, const atlas::Field & f, atlas::idx_t bdim, atlas::idx_t gdim, - size_t ldim, std::vector & list) + size_t ngptot, std::vector & list) { auto v = byteView (view); - listOf1DByteViewBlocked (v, std::vector (), f, bdim, gdim, ldim, list); + listOf1DByteViewBlocked (v, std::vector (), f, bdim, gdim, ngptot, list); } }; void createIoFieldDescriptorsBlocked - (atlas::Field & f, std::vector & list, atlas::idx_t bdim, atlas::idx_t gdim, size_t ldim) + (atlas::Field & f, std::vector & list, atlas::idx_t bdim, atlas::idx_t gdim, size_t ngptot) { int rank = f.rank (); auto type = f.datatype (); @@ -147,12 +147,12 @@ void createIoFieldDescriptorsBlocked auto v = atlas::array::make_view (f); - createListOf1DByteViewBlocked (v, f, bdim, gdim, ldim, list); + createListOf1DByteViewBlocked (v, f, bdim, gdim, ngptot, list); } void createIoFieldDescriptors - (atlas::Field & f, std::vector & list, size_t ldim, atlas::idx_t gdim) + (atlas::Field & f, std::vector & list, size_t ngptot, atlas::idx_t gdim) { int rank = f.rank (); auto type = f.datatype (); @@ -164,7 +164,7 @@ void createIoFieldDescriptors if (rank == __rank) \ { \ auto v = atlas::array::make_view<__type,__rank> (f); \ - createListOf1DByteView (v, f, ldim, gdim, list); \ + createListOf1DByteView (v, f, ngptot, gdim, list); \ goto done; \ } @@ -189,10 +189,10 @@ void createIoFieldDescriptors } void createIoFieldDescriptors - (atlas::FieldSet & s, std::vector & list, size_t ldim, atlas::idx_t gdim) + (atlas::FieldSet & s, std::vector & list, size_t ngptot, atlas::idx_t gdim) { for (auto & f : s) - createIoFieldDescriptors (f, list, ldim, gdim); + createIoFieldDescriptors (f, list, ngptot, gdim); } diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index 9855d697c..d8a9468b7 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -179,7 +179,7 @@ CASE( "test_gatherscatter_NPROMAxNFLEVGxNGPBLKS" ) std::vector dloc; std::vector dglo; - createIoFieldDescriptors (sglo, dglo, fs.sizeOwned ()); // Default for grid dimension is inner dimension + createIoFieldDescriptors (sglo, dglo); // Default for grid dimension is inner dimension } @@ -270,7 +270,7 @@ CASE( "test_gatherscatter_NFLEVGxNGPTOT" ) std::vector dglo; createIoFieldDescriptors (floc, dloc, fs.sizeOwned (), 1); // Grid dimension is 1 - createIoFieldDescriptors (sglo, dglo, fs.sizeOwned ()); // Default for grid dimension is inner dimension + createIoFieldDescriptors (sglo, dglo); // Default for grid dimension is inner dimension // Set target processor for all fields for (auto & d : dglo) @@ -420,7 +420,7 @@ CASE( "test_gatherscatter_NGPTOTxNFLEVG" ) std::vector dglo; createIoFieldDescriptors (floc, dloc, fs.sizeOwned ()); - createIoFieldDescriptors (sglo, dglo, fs.sizeOwned ()); + createIoFieldDescriptors (sglo, dglo); for (auto & d : dglo) d.field ().metadata ().get ("owner", d.owner ()); @@ -614,7 +614,7 @@ CASE( "test_gatherscatter_simple" ) ATLAS_TRACE_SCOPE ("create io descriptors") { createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); - createIoFieldDescriptors (sglo2, dglo, grid.size ()); + createIoFieldDescriptors (sglo2, dglo); for (auto & d : dglo) d.field ().metadata ().get ("owner", d.owner ()); } From 15aaf8716743ffd0e0b662f0c26f3305fe18f7b9 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Wed, 3 Jun 2020 20:29:28 +0000 Subject: [PATCH 53/58] Test gather/scatter for (1:NPROMA,1:NFLEVG,1:NGPBLKS) --- src/tests/gatherscatter/GatherScatter.cc | 4 +- src/tests/gatherscatter/test_gatherscatter.cc | 83 +++++++++++++++---- 2 files changed, 68 insertions(+), 19 deletions(-) diff --git a/src/tests/gatherscatter/GatherScatter.cc b/src/tests/gatherscatter/GatherScatter.cc index bf96c398f..d823345c6 100644 --- a/src/tests/gatherscatter/GatherScatter.cc +++ b/src/tests/gatherscatter/GatherScatter.cc @@ -172,7 +172,7 @@ void GatherScatter::processLocBuffer (ioFieldDesc_v & floc, const fldprc_t & tlo const int jidia = 0, jfdia = std::min (nproma, ngptot - jblk * nproma); for (atlas::idx_t jlon = jidia; jlon < jfdia; jlon++) { - atlas::idx_t k = (jlon+jblk*ngptot)*dlength; + atlas::idx_t k = (jlon+jblk*nproma)*dlength; for (int j = 0; j < dlength; j++) a (buffer[k+j], f (jblk, jlon, j)); } @@ -280,7 +280,7 @@ ATLAS_TRACE_SCOPE ("GatherScatter::gather") fldprc_t tloc = computeTLoc (floc); byte_v buf_loc (tloc.fld.back ().off); processLocBuffer (floc, tloc, buf_loc, pack); - + ATLAS_TRACE_SCOPE ("barrier") { comm.barrier (); diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index d8a9468b7..800374305 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -90,13 +90,12 @@ CASE( "test_gatherscatter_NPROMAxNFLEVGxNGPBLKS" ) if (! eckit::Resource ("--NPROMAxNFLEVGxNGPBLKS", false)) return; - int nproma = eckit::Resource ("--nproma", 8); + int nproma = eckit::Resource ("--nproma", 24); int nflevg = eckit::Resource ("--nflevg", 10); bool gather (eckit::Resource ("--gather", false)); bool scatter (eckit::Resource ("--scatter", false)); bool check (eckit::Resource ("--check", false)); - atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); auto & comm = mpi::comm (); @@ -148,20 +147,7 @@ CASE( "test_gatherscatter_NPROMAxNFLEVGxNGPBLKS" ) }; // Distributed field, Fortran dimensions (1:NPROMA,1:NFLEVG,1:NGPBLKS) - atlas::Field floc ("field", atlas::array::DataType::kind (), {nproma, nflevg, ngpblks}); - - auto vloc = array::make_view (floc); - - if (check) - { - for (int jblk = 0; jblk < ngpblks; jblk++) - { - const int jidia = 0, jfdia = std::min (nproma, ngptot - jblk * nproma); - for (int jlev = 0; jlev < nflevg; jlev++) - for (int jlon = jidia; jlon < jfdia; jlon++) - vloc (jlon, jlev, jblk) = func (jlev, irank, jlon + jblk * nproma); - } - } + atlas::Field floc ("field", atlas::array::DataType::kind (), {ngpblks, nflevg, nproma}); // Gather our multi-field, multi-level Atlas field to a set of fields (1:NGPTOTG) atlas::FieldSet sglo; @@ -179,8 +165,71 @@ CASE( "test_gatherscatter_NPROMAxNFLEVGxNGPBLKS" ) std::vector dloc; std::vector dglo; - createIoFieldDescriptors (sglo, dglo); // Default for grid dimension is inner dimension + createIoFieldDescriptors (sglo, dglo); // Default for grid dimension is inner dimension + createIoFieldDescriptorsBlocked (floc, dloc, 0, 2, fs.sizeOwned ()); // NGPBLKS dimension, NPROMA dimension, NGPTOT + // Set target processor for all fields + for (auto & d : dglo) + d.field ().metadata ().get ("owner", d.owner ()); + + GatherScatter gs (dist); + + + auto walkLoc = [&floc,ngpblks,nproma,nflevg,ngptot,func,irank] (std::function f) + { + auto vloc = array::make_view (floc); + for (int jblk = 0; jblk < ngpblks; jblk++) + { + const int jidia = 0, jfdia = std::min (nproma, ngptot - jblk * nproma); + for (int jlev = 0; jlev < nflevg; jlev++) + for (int jlon = jidia; jlon < jfdia; jlon++) + f (vloc (jblk, jlev, jlon), func (jlev, irank, jlon + jblk * nproma)); + } + }; + + auto walkGlo = [&sglo,nflevg,&grid,&irank,&prc,&ind,func] (std::function f) + { + for (int jlev = 0; jlev < nflevg; jlev++) + { + auto fglo = sglo[jlev]; + int owner; + fglo.metadata ().get ("owner", owner); + if (irank == owner) + { + auto vglo = array::make_view (fglo); + for (int jglo = 0; jglo < grid.size (); jglo++) + f (vglo (jglo), func (jlev, prc[jglo], ind[jglo])); + } + } + }; + + auto set = [](T & v, T r) { v = r; }; + auto cmp = [](T & v, T r) { EXPECT (v == r); }; + auto clear = [](T & v, T r) { v = 0; }; + + if (gather) + { + if (check) + { + walkLoc (set); + walkGlo (clear); + } + gs.gather (dloc, dglo); + if (check) + walkGlo (cmp); + } + + if (scatter) + { + if (check) + { + walkGlo (set); + walkLoc (clear); + } + gs.scatter (dglo, dloc); + if (check) + walkGlo (cmp); + } } CASE( "test_gatherscatter_NFLEVGxNGPTOT" ) From 1cec258971eb57b744769084da8f9713e4d98b2f Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 4 Jun 2020 08:04:50 +0000 Subject: [PATCH 54/58] Clean simple test case --- src/tests/gatherscatter/test_gatherscatter.cc | 164 +++++++++--------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index 800374305..2e894158d 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -175,7 +175,7 @@ CASE( "test_gatherscatter_NPROMAxNFLEVGxNGPBLKS" ) GatherScatter gs (dist); - auto walkLoc = [&floc,ngpblks,nproma,nflevg,ngptot,func,irank] (std::function f) + auto walkLoc = [&floc, ngpblks, nproma, nflevg, ngptot, func, irank] (std::function f) { auto vloc = array::make_view (floc); for (int jblk = 0; jblk < ngpblks; jblk++) @@ -187,7 +187,7 @@ CASE( "test_gatherscatter_NPROMAxNFLEVGxNGPBLKS" ) } }; - auto walkGlo = [&sglo,nflevg,&grid,&irank,&prc,&ind,func] (std::function f) + auto walkGlo = [&sglo, nflevg, &grid, &irank, &prc, &ind, func] (std::function f) { for (int jlev = 0; jlev < nflevg; jlev++) { @@ -526,8 +526,7 @@ CASE( "test_gatherscatter_simple" ) getprcind (fs, dist, prc, ind); atlas::FieldSet sloc; - atlas::FieldSet sglo1; - atlas::FieldSet sglo2; + atlas::FieldSet sglo; using T = long; @@ -554,45 +553,34 @@ CASE( "test_gatherscatter_simple" ) return v; }; - auto checkgather = [ind, prc, grid, func, irank] (const atlas::FieldSet & sglo) + auto walkGlo = [&ind, &prc, &grid, func, irank] (atlas::FieldSet &sglo, std::function f) { - ATLAS_TRACE_SCOPE ("checkgather") - { for (int i = 0; i < sglo.size (); i++) { - const auto & fglo = sglo[i]; + auto & fglo = sglo[i]; int owner; EXPECT (fglo.metadata ().get ("owner", owner)); if (owner == irank) { - const auto v = array::make_view (fglo); + auto v = array::make_view (fglo); for (int j = 0; j < grid.size (); j++) - { - T v1 = v[j], v2 = func (i, prc[j], ind[j]); - EXPECT_EQ (v1, v2); - } + f (v[j], func (i, prc[j], ind[j])); } } - } }; - auto checkscatter = [fs, func, irank] (const atlas::FieldSet & sloc) + auto walkLoc = [&fs,func,irank] (atlas::FieldSet & sloc, std::function f) { - ATLAS_TRACE_SCOPE ("checkscatter") - { for (int i = 0; i < sloc.size (); i++) { - const auto & floc = sloc[i]; - const auto v = array::make_view (floc); + auto & floc = sloc[i]; + auto v = array::make_view (floc); for (int j = 0; j < fs.sizeOwned (); j++) - { - T v1 = v[j], v2 = func (i, irank, j); - EXPECT_EQ (v1, v2); - } + f (v[j], func (i, irank, j)); } - } }; + for (int i = 0; i < nfield; i++) { int owner = i % nproc; @@ -600,61 +588,60 @@ CASE( "test_gatherscatter_simple" ) std::string name = std::string ("#") + std::to_string (i); atlas::Field floc = fs.createField (atlas::util::Config ("name", name) | atlas::util::Config ("owner", owner)); - auto v = array::make_view (floc); - for (int j = 0; j < fs.sizeOwned (); j++) - v[j] = func (i, irank, j); - sloc.add (floc); - - if (gather1) - { - Field fglo1 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); - fglo1.metadata ().set ("owner", owner); - sglo1.add (fglo1); - } - if (gather2) - { - Field fglo2 = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); - fglo2.metadata ().set ("owner", owner); - sglo2.add (fglo2); - } + sloc.add (floc); + Field fglo = Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); + fglo.metadata ().set ("owner", owner); + sglo.add (fglo); } + auto set = [](T & v, T r) { v = r; }; + auto cmp = [](T & v, T r) { EXPECT (v == r); }; + auto clear = [](T & v, T r) { v = 0; }; + if (gather1) { - { - atlas::FieldSet loc, glo; - fs.gather (loc, glo); - } + if (check) + { + walkLoc (sloc, set); + walkGlo (sglo, clear); + } + ATLAS_TRACE_SCOPE ("test_gather1") { - fs.gather (sloc, sglo1); - if (check) checkgather (sglo1); - if (debug) prff ("sglo1", sglo1); + fs.gather (sloc, sglo); } - if (scatter1) - { - ATLAS_TRACE_SCOPE ("test_scatter1") - { - for (int i = 0; i < sloc.size (); i++) - { - auto v = array::make_view (sloc[i]); - for (int j = 0; j < fs.sizeOwned (); j++) - v (j) = 0; - } + if (check) + walkGlo (sglo, cmp); - fs.scatter (sglo1, sloc); + if (debug) prff ("sglo1", sglo); + } - if (check) checkscatter (sloc); - } + if (scatter1) + { + if (check) + { + walkGlo (sglo, set); + walkLoc (sloc, clear); } + ATLAS_TRACE_SCOPE ("test_scatter1") + { + fs.scatter (sglo, sloc); + }; + if (check) + walkLoc (sloc, cmp); } if (gather2) { GatherScatter gs (dist); + if (check) + { + walkLoc (sloc, set); + walkGlo (sglo, clear); + } ATLAS_TRACE_SCOPE ("test_gather2") { std::vector dloc; @@ -662,34 +649,47 @@ CASE( "test_gatherscatter_simple" ) ATLAS_TRACE_SCOPE ("create io descriptors") { - createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); - createIoFieldDescriptors (sglo2, dglo); - for (auto & d : dglo) - d.field ().metadata ().get ("owner", d.owner ()); + createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); + createIoFieldDescriptors (sglo, dglo); + for (auto & d : dglo) + EXPECT (d.field ().metadata ().get ("owner", d.owner ())); } gs.gather (dloc, dglo); + }; - if (debug) prff ("sglo2", sglo2); - if (check) checkgather (sglo2); + if (check) + walkGlo (sglo, cmp); - if (scatter2) - { - ATLAS_TRACE_SCOPE ("test_scatter2") - { - for (int i = 0; i < sloc.size (); i++) - { - auto v = array::make_view (sloc[i]); - for (int j = 0; j < fs.sizeOwned (); j++) - v (j) = 0; - } + if (debug) prff ("sglo2", sglo); + } - gs.scatter (dglo, dloc); + if (scatter2) + { + GatherScatter gs (dist); + if (check) + { + walkGlo (sglo, set); + walkLoc (sloc, clear); + } + ATLAS_TRACE_SCOPE ("test_scatter2") + { + std::vector dloc; + std::vector dglo; - if (check) checkscatter (sloc); - } - } - } + ATLAS_TRACE_SCOPE ("create io descriptors") + { + createIoFieldDescriptors (sloc, dloc, fs.sizeOwned ()); + createIoFieldDescriptors (sglo, dglo); + for (auto & d : dglo) + EXPECT (d.field ().metadata ().get ("owner", d.owner ())); + } + + gs.scatter (dglo, dloc); + }; + + if (check) + walkLoc (sloc, cmp); } From 44cba0dacb08925dec34c12501b8007c962aa8e8 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 4 Jun 2020 08:06:28 +0000 Subject: [PATCH 55/58] Remove useless test case --- src/tests/gatherscatter/test_gatherscatter.cc | 109 ------------------ 1 file changed, 109 deletions(-) diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index 2e894158d..ddc0b0e5e 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -389,115 +389,6 @@ CASE( "test_gatherscatter_NFLEVGxNGPTOT" ) } -CASE( "test_gatherscatter_NGPTOTxNFLEVG" ) -{ - if (! eckit::Resource ("--NGPTOTxNFLEVG", false)) - return; - int nfield = eckit::Resource ("--fields", 3); - int nflevg = eckit::Resource ("--nflevg", 10); - atlas::StructuredGrid grid (eckit::Resource ("--grid", "N16")); - bool gather (eckit::Resource ("--gather", false)); - bool scatter (eckit::Resource ("--scatter", false)); - bool check (eckit::Resource ("--check", false)); - - - auto & comm = mpi::comm (); - int irank = comm.rank (); - int nproc = comm.size (); - - atlas::grid::Distribution dist (grid, atlas::grid::Partitioner ("equal_regions")); - atlas::functionspace::StructuredColumns fs (grid, dist, atlas::util::Config ("halo", 1) - | atlas::util::Config ("periodic_points", true)); - std::vector prc, ind; - - if (check) - getprcind (fs, dist, prc, ind); - - atlas::FieldSet sloc; - - using T = long; - - const int ind_bit = 24, ind_off = 0; - const int prc_bit = 12, prc_off = ind_off + ind_bit; - const int fld_bit = 14, fld_off = prc_off + prc_bit; - const int lev_bit = 14, lev_off = fld_off + fld_bit; - - if (check) - { - ATLAS_ASSERT (fs.sizeOwned () < (1 << ind_bit)); - ATLAS_ASSERT (nproc < (1 << prc_bit)); - ATLAS_ASSERT (nfield < (1 << fld_bit)); - ATLAS_ASSERT (nflevg < (1 << lev_bit)); - } - - using T = long; - - auto func = [check,ind_off,prc_off,fld_off,lev_off] (int fld, int lev, int prc, int ind) - { - long v = 0; - if (check) - { - v = (static_cast (fld) << fld_off) + (static_cast (lev) << lev_off) - + (static_cast (prc) << prc_off) + (static_cast (ind) << ind_off); - } - return v; - }; - - atlas::Field floc ("field", atlas::array::DataType::kind (), {nfield, nflevg, grid.size ()}); - - - auto v = array::make_view (floc); - - for (int jfld = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++) - for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) - v (jfld, jlev, jloc) = func (jfld, jlev, irank, jloc); - - atlas::FieldSet sglo; - - for (int jfld = 0, count = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++, count++) - { - int owner = count % nproc; - std::string name = std::string ("#") + std::to_string (jfld) + std::string (",") + std::to_string (jlev); - atlas::Field fglo = atlas::Field (name, atlas::array::DataType::kind (), {irank == owner ? grid.size () : 0}); - fglo.metadata ().set ("owner", owner); - sglo.add (fglo); - } - - std::vector dloc; - std::vector dglo; - - createIoFieldDescriptors (floc, dloc, fs.sizeOwned ()); - createIoFieldDescriptors (sglo, dglo); - - for (auto & d : dglo) - d.field ().metadata ().get ("owner", d.owner ()); - - GatherScatter gs (dist); - - gs.gather (dloc, dglo); - - - for (int jfld = 0, count = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++, count++) - { - atlas::Field fglo = sglo[count]; - int owner; fglo.metadata ().get ("owner", owner); - if (owner == irank) - { - auto v = array::make_view (fglo); - for (int jglo = 0; jglo < grid.size (); jglo++) - { - T v1 = v (jglo), v2 = func (jfld, jlev, prc[jglo], ind[jglo]); - EXPECT (v1 == v2); - } - } - } - - -} - CASE( "test_gatherscatter_simple" ) { if (! eckit::Resource ("--simple", false)) From 90753b2ee24bd28aa3371fcc13e0f1dc03b5ddf0 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 4 Jun 2020 08:37:02 +0000 Subject: [PATCH 56/58] Cleanup --- src/tests/gatherscatter/test_gatherscatter.cc | 142 ++++++++---------- 1 file changed, 61 insertions(+), 81 deletions(-) diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index ddc0b0e5e..ddb992c27 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -137,12 +137,9 @@ CASE( "test_gatherscatter_NPROMAxNFLEVGxNGPBLKS" ) auto func = [check,ind_off,prc_off,lev_off] (int lev, int prc, int ind) { long v = 0; - if (check) - { - v = (static_cast (lev) << lev_off) - + (static_cast (prc) << prc_off) - + (static_cast (ind) << ind_off); - } + v = (static_cast (lev) << lev_off) + + (static_cast (prc) << prc_off) + + (static_cast (ind) << ind_off); return v; }; @@ -279,29 +276,14 @@ CASE( "test_gatherscatter_NFLEVGxNGPTOT" ) auto func = [check,ind_off,prc_off,fld_off,lev_off] (int fld, int lev, int prc, int ind) { long v = 0; - if (check) - { - v = (static_cast (fld) << fld_off) + (static_cast (lev) << lev_off) - + (static_cast (prc) << prc_off) + (static_cast (ind) << ind_off); - } + v = (static_cast (fld) << fld_off) + (static_cast (lev) << lev_off) + + (static_cast (prc) << prc_off) + (static_cast (ind) << ind_off); return v; }; // Distributed field, Fortran dimensions (1:NFLEVG,1:NGPTOT,1:NFIELDS) atlas::Field floc ("field", atlas::array::DataType::kind (), {nfield, fs.size (), nflevg}); - - auto vloc = array::make_view (floc); - - if (check) - { - for (int jfld = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++) - for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) - vloc (jfld, jloc, jlev) = func (jfld, jlev, irank, jloc); - } - - // Gather our multi-field, multi-level Atlas field to a set of fields (1:NGPTOTG) atlas::FieldSet sglo; for (int jfld = 0, count = 0; jfld < nfield; jfld++) @@ -314,6 +296,35 @@ CASE( "test_gatherscatter_NFLEVGxNGPTOT" ) sglo.add (fglo); } + auto walkLoc = [&floc, nfield, nflevg, &fs, irank, func] (std::function f) + { + auto vloc = array::make_view (floc); + for (int jfld = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++) + for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) + f (vloc (jfld, jloc, jlev), func (jfld, jlev, irank, jloc)); + }; + + auto walkGlo = [&sglo, nfield, nflevg, irank, func, &grid, &prc, &ind] (std::function f) + { + for (int jfld = 0, count = 0; jfld < nfield; jfld++) + for (int jlev = 0; jlev < nflevg; jlev++, count++) + { + atlas::Field fglo = sglo[count]; + int owner; EXPECT (fglo.metadata ().get ("owner", owner)); + if (owner == irank) + { + auto v = array::make_view (fglo); + for (int jglo = 0; jglo < grid.size (); jglo++) + f (v (jglo), func (jfld, jlev, prc[jglo], ind[jglo])); + } + } + }; + + auto set = [](T & v, T r) { v = r; }; + auto cmp = [](T & v, T r) { EXPECT (v == r); }; + auto clear = [](T & v, T r) { v = 0; }; + // IO descriptors std::vector dloc; std::vector dglo; @@ -331,24 +342,16 @@ CASE( "test_gatherscatter_NFLEVGxNGPTOT" ) if (gather) { + if (check) + { + walkLoc (set); + walkGlo (clear); + } + gs.gather (dloc, dglo); if (check) - for (int jfld = 0, count = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++, count++) - { - atlas::Field fglo = sglo[count]; - int owner; fglo.metadata ().get ("owner", owner); - if (owner == irank) - { - auto v = array::make_view (fglo); - for (int jglo = 0; jglo < grid.size (); jglo++) - { - T v1 = v (jglo), v2 = func (jfld, jlev, prc[jglo], ind[jglo]); - EXPECT (v1 == v2); - } - } - } + walkGlo (cmp); } // Scatter @@ -357,34 +360,14 @@ CASE( "test_gatherscatter_NFLEVGxNGPTOT" ) { if (check) { - // Set distributed field to zero - filterView (vloc, [](T & z){ z = 0; }); - - // Compute global fields - for (int jfld = 0, count = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++, count++) - { - atlas::Field fglo = sglo[count]; - int owner; fglo.metadata ().get ("owner", owner); - if (owner == irank) - { - auto v = array::make_view (fglo); - for (int jglo = 0; jglo < grid.size (); jglo++) - v (jglo) = func (jfld, jlev, prc[jglo], ind[jglo]); - } - } + walkGlo (set); + walkLoc (clear); } gs.scatter (dglo, dloc); if (check) - for (int jfld = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++) - for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) - { - T v1 = vloc (jfld, jloc, jlev), v2 = func (jfld, jlev, irank, jloc); - EXPECT (v1 == v2); - } + walkLoc (cmp); } } @@ -435,16 +418,13 @@ CASE( "test_gatherscatter_simple" ) auto func = [check,ind_off,prc_off,fld_off] (int fld, int prc, int ind) { long v = 0; - if (check) - { - v = (static_cast (fld) << fld_off) - + (static_cast (prc) << prc_off) - + (static_cast (ind) << ind_off); - } + v = (static_cast (fld) << fld_off) + + (static_cast (prc) << prc_off) + + (static_cast (ind) << ind_off); return v; }; - auto walkGlo = [&ind, &prc, &grid, func, irank] (atlas::FieldSet &sglo, std::function f) + auto walkGlo = [&sglo, &ind, &prc, &grid, func, irank] (std::function f) { for (int i = 0; i < sglo.size (); i++) { @@ -460,7 +440,7 @@ CASE( "test_gatherscatter_simple" ) } }; - auto walkLoc = [&fs,func,irank] (atlas::FieldSet & sloc, std::function f) + auto walkLoc = [&sloc, &fs, func, irank] (std::function f) { for (int i = 0; i < sloc.size (); i++) { @@ -495,8 +475,8 @@ CASE( "test_gatherscatter_simple" ) { if (check) { - walkLoc (sloc, set); - walkGlo (sglo, clear); + walkLoc (set); + walkGlo (clear); } ATLAS_TRACE_SCOPE ("test_gather1") @@ -505,7 +485,7 @@ CASE( "test_gatherscatter_simple" ) } if (check) - walkGlo (sglo, cmp); + walkGlo (cmp); if (debug) prff ("sglo1", sglo); } @@ -514,15 +494,15 @@ CASE( "test_gatherscatter_simple" ) { if (check) { - walkGlo (sglo, set); - walkLoc (sloc, clear); + walkGlo (set); + walkLoc (clear); } ATLAS_TRACE_SCOPE ("test_scatter1") { fs.scatter (sglo, sloc); }; if (check) - walkLoc (sloc, cmp); + walkLoc (cmp); } if (gather2) @@ -530,8 +510,8 @@ CASE( "test_gatherscatter_simple" ) GatherScatter gs (dist); if (check) { - walkLoc (sloc, set); - walkGlo (sglo, clear); + walkLoc (set); + walkGlo (clear); } ATLAS_TRACE_SCOPE ("test_gather2") { @@ -550,7 +530,7 @@ CASE( "test_gatherscatter_simple" ) }; if (check) - walkGlo (sglo, cmp); + walkGlo (cmp); if (debug) prff ("sglo2", sglo); } @@ -560,8 +540,8 @@ CASE( "test_gatherscatter_simple" ) GatherScatter gs (dist); if (check) { - walkGlo (sglo, set); - walkLoc (sloc, clear); + walkGlo (set); + walkLoc (clear); } ATLAS_TRACE_SCOPE ("test_scatter2") { @@ -580,7 +560,7 @@ CASE( "test_gatherscatter_simple" ) }; if (check) - walkLoc (sloc, cmp); + walkLoc (cmp); } From 6724f9f75484ca81731ec3b764e889910854f579 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Thu, 4 Jun 2020 10:16:57 +0000 Subject: [PATCH 57/58] Handle other types/ranks --- src/tests/gatherscatter/ioFieldDesc.cc | 33 +++++++++++++++++-- .../gatherscatter/test_arrayViewHelpers.cc | 2 +- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/tests/gatherscatter/ioFieldDesc.cc b/src/tests/gatherscatter/ioFieldDesc.cc index 52d9c6b4b..3c86f40ac 100644 --- a/src/tests/gatherscatter/ioFieldDesc.cc +++ b/src/tests/gatherscatter/ioFieldDesc.cc @@ -145,9 +145,35 @@ void createIoFieldDescriptorsBlocked if (gdim < 0) gdim = gdim + rank; - auto v = atlas::array::make_view (f); +#define HANDLE_TYPE_RANK(__type,__rank) \ + if (rank == __rank) \ + { \ + auto v = atlas::array::make_view<__type,__rank> (f); \ + createListOf1DByteViewBlocked (v, f, bdim, gdim, ngptot, list); \ + goto done; \ + } + +#define HANDLE_TYPE(__type) \ + if (type.kind () == atlas::array::DataType::create<__type> ().kind ()) \ + { \ + HANDLE_TYPE_RANK (__type, 2); HANDLE_TYPE_RANK (__type, 3); \ + HANDLE_TYPE_RANK (__type, 4); HANDLE_TYPE_RANK (__type, 5); HANDLE_TYPE_RANK (__type, 6); \ + HANDLE_TYPE_RANK (__type, 7); HANDLE_TYPE_RANK (__type, 8); HANDLE_TYPE_RANK (__type, 9); \ + } + + HANDLE_TYPE (long); + HANDLE_TYPE (double); + HANDLE_TYPE (int); + HANDLE_TYPE (float); - createListOf1DByteViewBlocked (v, f, bdim, gdim, ngptot, list); +#undef HANDLE_TYPE_RANK +#undef HANDLE_TYPE + + atlas::throw_NotImplemented ("createIoFieldDescriptorsBlocked type/rank", Here ()); + +done: + + return; } @@ -181,6 +207,9 @@ void createIoFieldDescriptors HANDLE_TYPE (int); HANDLE_TYPE (float); +#undef HANDLE_TYPE_RANK +#undef HANDLE_TYPE + atlas::throw_NotImplemented ("createIoFieldDescriptors type/rank", Here ()); done: diff --git a/src/tests/gatherscatter/test_arrayViewHelpers.cc b/src/tests/gatherscatter/test_arrayViewHelpers.cc index 55ac1b499..348221cf5 100644 --- a/src/tests/gatherscatter/test_arrayViewHelpers.cc +++ b/src/tests/gatherscatter/test_arrayViewHelpers.cc @@ -56,7 +56,7 @@ int main (int argc, char * argv[]) byte * b = (byte *)&x + j; *b = v (jblk, jlon, j); } - printf (" %8d", x); + printf (" %8ld", x); } printf ("\n"); } From 196d2d8c7b70ec9914c512793580b222f5c64b3c Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Tue, 16 Jun 2020 15:42:30 +0000 Subject: [PATCH 58/58] Use viewLoop template --- src/tests/gatherscatter/arrayViewHelpers.h | 34 ++++++-------- .../gatherscatter/test_arrayViewHelpers.cc | 46 +++---------------- src/tests/gatherscatter/test_gatherscatter.cc | 16 ++----- 3 files changed, 25 insertions(+), 71 deletions(-) diff --git a/src/tests/gatherscatter/arrayViewHelpers.h b/src/tests/gatherscatter/arrayViewHelpers.h index cee5a36e4..22c5f6565 100644 --- a/src/tests/gatherscatter/arrayViewHelpers.h +++ b/src/tests/gatherscatter/arrayViewHelpers.h @@ -86,39 +86,33 @@ addDummyDimension (const atlas::array::ArrayView & view) // Apply a function to view elements -template -class filterViewHelper +template +class viewLoopHelper { public: - template - static void apply (atlas::array::ArrayView view, Func func) + template + static void apply (atlas::array::ArrayView view, Func func, Index... index) { - constexpr int rank = Rank-1; - for (int i = 0; i < view.shape (0); i++) - { - atlas::array::ArrayView v = dropDimension (view, 0, i); - filterViewHelper::apply (v, func); - } + for (int i = 0; i < view.shape (Rank - Count); i++) + viewLoopHelper::apply (view, func, index..., i); } }; -template -class filterViewHelper<1, Value> +template <> +class viewLoopHelper<0> { public: - template - static void apply (atlas::array::ArrayView view, Func func) + template + static void apply (atlas::array::ArrayView view, Func func, Index... index) { - for (int i = 0; i < view.shape (0); i++) - func (view (i)); + func (view (index...), index...); } }; + template -void filterView (atlas::array::ArrayView view, Func func) +void viewLoop (atlas::array::ArrayView view, Func func) { - filterViewHelper::apply (view, func); + viewLoopHelper::apply (view, func); } - - diff --git a/src/tests/gatherscatter/test_arrayViewHelpers.cc b/src/tests/gatherscatter/test_arrayViewHelpers.cc index 348221cf5..2da9cffbc 100644 --- a/src/tests/gatherscatter/test_arrayViewHelpers.cc +++ b/src/tests/gatherscatter/test_arrayViewHelpers.cc @@ -4,6 +4,7 @@ #include "atlas/field.h" #include "atlas/array.h" #include +#include template @@ -25,47 +26,12 @@ int main (int argc, char * argv[]) auto v = atlas::array::make_view (f); - printf (" shape = "); - for (int i = 0; i < v.rank (); i++) - printf (" %8d", v.shape (i)); - printf ("\n"); - - for (int jblk = 0; jblk < ngpblks; jblk++) - for (int jlev = 0, jloc = 0; jlev < nflevg; jlev++) - for (int jlon = 0; jlon < nproma; jlon++) - v (jblk, jlev, jlon) = 1000 * jlev + jlon + jblk * nproma; - - std::vector df; - createIoFieldDescriptorsBlocked (f, df, 0, 2, ngptot); // NGPBLKS dimension, NPROMA dimension, NGPTOT - - for (int i = 0; i < df.size (); i++) - { - auto & d = df[i]; - auto & v = d.view (); - - printf (" %8d | %8d | %8d | %8d | %8d\n", i, v.rank (), v.shape (0), v.shape (1), v.shape (2)); - - if (i == 3) - { - for (int jblk = 0; jblk < v.shape (0); jblk++) - for (int jlon = 0; jlon < v.shape (1); jlon++) - { - long x = 0; - for (int j = 0; j < 8; j++) - { - byte * b = (byte *)&x + j; - *b = v (jblk, jlon, j); - } - printf (" %8ld", x); - } - printf ("\n"); - } - - - - } - + viewLoop (v, [] (long & x, int i, int j, int k) { x = 100000 * i + 100 * j + k; }); + for (int i = 0; i < v.shape (0); i++) + for (int j = 0; j < v.shape (1); j++) + for (int k = 0; k < v.shape (2); k++) + printf (" %10.10d\n", v (i, j, k)); return 0; diff --git a/src/tests/gatherscatter/test_gatherscatter.cc b/src/tests/gatherscatter/test_gatherscatter.cc index ddb992c27..3caeb64fb 100644 --- a/src/tests/gatherscatter/test_gatherscatter.cc +++ b/src/tests/gatherscatter/test_gatherscatter.cc @@ -175,13 +175,10 @@ CASE( "test_gatherscatter_NPROMAxNFLEVGxNGPBLKS" ) auto walkLoc = [&floc, ngpblks, nproma, nflevg, ngptot, func, irank] (std::function f) { auto vloc = array::make_view (floc); - for (int jblk = 0; jblk < ngpblks; jblk++) - { - const int jidia = 0, jfdia = std::min (nproma, ngptot - jblk * nproma); - for (int jlev = 0; jlev < nflevg; jlev++) - for (int jlon = jidia; jlon < jfdia; jlon++) - f (vloc (jblk, jlev, jlon), func (jlev, irank, jlon + jblk * nproma)); - } + viewLoop (vloc, + [func,f,&irank,&nproma] (T & x, int jblk, int jlev, int jlon) + { f (x, func (jlev, irank, jlon + jblk * nproma)); }); +std::cout << " walkLoc " << std::endl; }; auto walkGlo = [&sglo, nflevg, &grid, &irank, &prc, &ind, func] (std::function f) @@ -299,10 +296,7 @@ CASE( "test_gatherscatter_NFLEVGxNGPTOT" ) auto walkLoc = [&floc, nfield, nflevg, &fs, irank, func] (std::function f) { auto vloc = array::make_view (floc); - for (int jfld = 0; jfld < nfield; jfld++) - for (int jlev = 0; jlev < nflevg; jlev++) - for (int jloc = 0; jloc < fs.sizeOwned (); jloc++) - f (vloc (jfld, jloc, jlev), func (jfld, jlev, irank, jloc)); + viewLoop (vloc, [func,&irank,f] (T & x, int jfld, int jloc, int jlev) { f (x, func (jfld, jlev, irank, jloc)); }); }; auto walkGlo = [&sglo, nfield, nflevg, irank, func, &grid, &prc, &ind] (std::function f)