From cd69b7ea0dbbdc6cd287da9a33514f85e0c5cbe7 Mon Sep 17 00:00:00 2001 From: Willem Deconinck Date: Thu, 19 Dec 2024 16:25:38 +0000 Subject: [PATCH] Improved error handling for maybe uninmplemented ectrans GPU features --- src/tests/trans/CMakeLists.txt | 1 + src/tests/trans/test_trans.cc | 70 ++++++++++++++++++++-------- src/tests/trans/test_transgeneral.cc | 48 +++++++++++++++++-- 3 files changed, 96 insertions(+), 23 deletions(-) diff --git a/src/tests/trans/CMakeLists.txt b/src/tests/trans/CMakeLists.txt index bc2f3a165..48fd6bcfb 100644 --- a/src/tests/trans/CMakeLists.txt +++ b/src/tests/trans/CMakeLists.txt @@ -6,6 +6,7 @@ # granted to it by virtue of its status as an intergovernmental organisation nor # does it submit to any jurisdiction. +list( APPEND ATLAS_TEST_ENVIRONMENT ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED=1 ) if( HAVE_FCTEST ) if( atlas_HAVE_ECTRANS ) diff --git a/src/tests/trans/test_trans.cc b/src/tests/trans/test_trans.cc index 90e426e2e..c98c476d2 100644 --- a/src/tests/trans/test_trans.cc +++ b/src/tests/trans/test_trans.cc @@ -9,6 +9,7 @@ */ #include +#include #include "eckit/exception/Exceptions.h" #include "eckit/filesystem/PathName.h" @@ -48,6 +49,44 @@ #endif #endif +bool ignore_ectrans_not_implemented(std::exception& e) { + static bool ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED = []() -> bool { + const char* env = ::getenv("ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED"); + if (env) { + return std::atoi(env); + } + return false; + }(); + if (ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED == false) { + return false; + } + std::string errstr(e.what()); + for(auto& c : errstr){ c = std::tolower(c); } + std::vector search{"trans", "not", "implemented"}; + return std::all_of(search.begin() ,search.end(),[&](const std::string& s)->bool { + return errstr.find(s) != std::string::npos; + }); +} + +#define ECTRANS_MAYBE_NOT_IMPLEMENTED(expr) \ + do { \ + try { \ + expr; \ + } \ + catch (std::exception & e) { \ + if( ignore_ectrans_not_implemented(e) ) { \ + atlas::Log::error() << "ERROR IGNORED: Not implemented with ectrans code path\n" \ + << "Skipping remainder of test" \ + << std::endl; \ + return; \ + } \ + throw eckit::testing::TestException("Unexpected exception caught: "+std::string(e.what()), Here()); \ + } \ + catch (...) { \ + throw eckit::testing::TestException("Unexpected and unknown exception caught", Here()); \ + } \ + } while (false) + using namespace eckit; using atlas::grid::detail::partitioner::EqualRegionsPartitioner; using atlas::grid::detail::partitioner::TransPartitioner; @@ -166,7 +205,6 @@ CASE("test_trans_options") { Log::info() << "trans_opts = " << opts << std::endl; } -#ifdef TRANS_HAVE_IO CASE("test_write_read_cache") { Log::info() << "test_write_read_cache" << std::endl; using namespace trans; @@ -193,7 +231,6 @@ CASE("test_write_read_cache") { Trans trans_cache_O24(legendre_cache_O24, Grid("O24"), 23, option::flt(false)); } } -#endif CASE("test_distspec") { trans::TransIFS trans(Grid("F80"), 159); @@ -516,13 +553,11 @@ CASE("test_trans_using_functionspace_StructuredColumns") { EXPECT_THROWS_AS(trans.dirtrans(gpfields, spfields), eckit::Exception); } -#if 0 -// NOT SUPPORTED IN ECTRANS WITH GPU CASE("test_trans_MIR_lonlat") { Log::info() << "test_trans_MIR_lonlat" << std::endl; - Grid grid("L48"); - trans::Trans trans(grid, 47); + trans::Trans trans; + ECTRANS_MAYBE_NOT_IMPLEMENTED((trans = trans::Trans(grid, 47))); // global fields std::vector spf(trans.spectralCoefficients(), 0.); @@ -534,10 +569,7 @@ CASE("test_trans_MIR_lonlat") { EXPECT_NO_THROW(trans.dirtrans(1, gpf.data(), spf.data(), option::global())); } } -#endif -#if 0 -// NOT SUPPORTED IN ECTRANS WITH GPU CASE("test_trans_VorDivToUV") { int nfld = 1; // TODO: test for nfld>1 std::vector truncation_array{1}; // truncation_array{159,160,1279}; @@ -566,7 +598,9 @@ CASE("test_trans_VorDivToUV") { std::vector field_U(nfld * nspec2); std::vector field_V(nfld * nspec2); - vordiv_to_UV.execute(nspec2, nfld, field_vor.data(), field_div.data(), field_U.data(), field_V.data()); + ECTRANS_MAYBE_NOT_IMPLEMENTED( + vordiv_to_UV.execute(nspec2, nfld, field_vor.data(), field_div.data(), field_U.data(), field_V.data()); + ); // TODO: do some meaningful checks Log::info() << "Trans library" << std::endl; @@ -585,8 +619,9 @@ CASE("test_trans_VorDivToUV") { std::vector field_U(nfld * nspec2); std::vector field_V(nfld * nspec2); - vordiv_to_UV.execute(nspec2, nfld, field_vor.data(), field_div.data(), field_U.data(), field_V.data()); - + EXPECT_NO_THROW( + vordiv_to_UV.execute(nspec2, nfld, field_vor.data(), field_div.data(), field_U.data(), field_V.data()); + ); // TODO: do some meaningful checks Log::info() << "Local transform" << std::endl; Log::info() << "U: " << std::endl; @@ -597,9 +632,7 @@ CASE("test_trans_VorDivToUV") { } } } -#endif -#ifdef TRANS_HAVE_IO CASE("ATLAS-256: Legendre coefficient expected unique identifiers") { if (mpi::comm().size() == 1) { util::Config options; @@ -685,13 +718,13 @@ CASE("ATLAS-256: Legendre coefficient expected unique identifiers") { for (auto& domain : domains) { for (int T : spectral_T) { for (auto name : grids) { - Log::info() << "Case name:" << name << ", T:" << T << ", domain:" << domain << ", UID:'" << *uid - << "'" << std::endl; + //Log::info() << "Case name:" << name << ", T:" << T << ", domain:" << domain << ", UID:'" << *uid + // << "'" << std::endl; Grid grid(name, domain); auto test = trans::LegendreCacheCreator(grid, T, options).uid(); - ATLAS_DEBUG_VAR(test); - EXPECT(test == *uid); + //ATLAS_DEBUG_VAR(test); + EXPECT_EQ(test, *uid); uid++; } @@ -699,7 +732,6 @@ CASE("ATLAS-256: Legendre coefficient expected unique identifiers") { } } } -#endif //----------------------------------------------------------------------------- diff --git a/src/tests/trans/test_transgeneral.cc b/src/tests/trans/test_transgeneral.cc index 2318a2b36..722a649cb 100644 --- a/src/tests/trans/test_transgeneral.cc +++ b/src/tests/trans/test_transgeneral.cc @@ -46,6 +46,45 @@ #endif #endif +bool ignore_ectrans_not_implemented(std::exception& e) { + static bool ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED = []() -> bool { + const char* env = ::getenv("ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED"); + if (env) { + std::cout << "ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED=" << env << std::endl; + return std::atoi(env); + } + return false; + }(); + if (ATLAS_TEST_IGNORE_ECTRANS_NOT_IMPLEMENTED == false) { + return false; + } + std::string errstr(e.what()); + for(auto& c : errstr){ c = std::tolower(c); } + std::vector search{"trans", "not", "implemented"}; + return std::all_of(search.begin() ,search.end(),[&](const std::string& s)->bool { + return errstr.find(s) != std::string::npos; + }); +} + +#define ECTRANS_MAYBE_NOT_IMPLEMENTED(expr) \ + do { \ + try { \ + expr; \ + } \ + catch (std::exception & e) { \ + if( ignore_ectrans_not_implemented(e) ) { \ + atlas::Log::error() << "ERROR IGNORED: Not implemented with ectrans code path\n" \ + << "Skipping remainder of test" \ + << std::endl; \ + return; \ + } \ + throw eckit::testing::TestException("Unexpected exception caught: "+std::string(e.what()), Here()); \ + } \ + catch (...) { \ + throw eckit::testing::TestException("Unexpected and unknown exception caught", Here()); \ + } \ + } while (false) + using namespace eckit; using atlas::array::Array; @@ -1581,7 +1620,7 @@ CASE("test_trans_levels") { } #endif -#if 0 +#if 1 // ECTRANS GPU VERSION DOES NOT YET SUPPORT THIS #if ATLAS_HAVE_TRANS #if ATLAS_HAVE_ECTRANS || defined(TRANS_HAVE_INVTRANS_ADJ) @@ -1656,7 +1695,7 @@ CASE("test_2level_adjoint_test_with_powerspectrum_convolution") { // transform fields to spectral and view if (test_name[test_type].compare("inverse") == 0) { - transIFS.invtrans_adj(gpf, spf); + ECTRANS_MAYBE_NOT_IMPLEMENTED(transIFS.invtrans_adj(gpf, spf)); } else if (test_name[test_type].compare("direct") == 0) { transIFS.dirtrans(gpf, spf); } @@ -1696,8 +1735,9 @@ CASE("test_2level_adjoint_test_with_powerspectrum_convolution") { if (test_name[test_type].compare("inverse") == 0) { transIFS.invtrans(spf, gpf2); } else if (test_name[test_type].compare("direct") == 0) { - transIFS.dirtrans_adj(spf, gpf2); + ECTRANS_MAYBE_NOT_IMPLEMENTED(transIFS.dirtrans_adj(spf, gpf2)); } + Log::info() << "adjoint test transforms " << test_name[test_type] << std::endl; @@ -1795,7 +1835,7 @@ CASE("test_2level_adjoint_test_with_vortdiv") { } atlas::mpi::comm().allReduceInPlace(adj_value, eckit::mpi::sum()); - transIFS.dirtrans_wind2vordiv_adj(spfvor, spfdiv, gpfuv2); + ECTRANS_MAYBE_NOT_IMPLEMENTED(transIFS.dirtrans_wind2vordiv_adj(spfvor, spfdiv, gpfuv2)); double adj_value2(0.0); for (atlas::idx_t j = gridFS.j_begin(); j < gridFS.j_end(); ++j) {