From 9523fa251a4128705e6b1396e19656921ef88426 Mon Sep 17 00:00:00 2001 From: Joonmoo Huh Date: Wed, 24 Jan 2018 09:31:22 -0700 Subject: [PATCH 1/7] Throw exceptions instead of exiting on bad API calls --- Makefile | 24 ++ include/yask_common_api.hpp | 25 +- include/yask_compiler_api.hpp | 4 +- include/yask_kernel_api.hpp | 6 +- src/common/common_utils.cpp | 13 + src/common/output.cpp | 12 +- src/compiler/Makefile | 33 +- src/compiler/lib/Eqs.cpp | 56 ++- src/compiler/lib/Expr.cpp | 8 +- src/compiler/lib/Expr.hpp | 32 +- src/compiler/lib/Grid.cpp | 58 ++- src/compiler/lib/Grid.hpp | 2 +- src/compiler/lib/Parse.hpp | 9 +- src/compiler/lib/Soln.cpp | 10 +- src/compiler/lib/Soln.hpp | 2 +- src/compiler/lib/YaskKernel.cpp | 9 +- src/compiler/main.cpp | 36 +- .../yask_compiler_api_exception_test.cpp | 154 +++++++ src/compiler/tests/yask_compiler_api_test.cpp | 2 +- .../yc-api-test-with-exception-cxx-readonly | 1 + .../yc-api-test-with-exception-py-readonly | 1 + src/kernel/Makefile | 33 +- src/kernel/lib/context.cpp | 102 +++-- src/kernel/lib/context.hpp | 10 +- src/kernel/lib/new_grid.cpp | 32 +- src/kernel/lib/realv.hpp | 8 +- src/kernel/lib/realv_grids.cpp | 120 ++++-- src/kernel/lib/realv_grids.hpp | 34 +- src/kernel/lib/settings.cpp | 32 +- src/kernel/lib/utils.cpp | 32 +- .../tests/yask_kernel_api_exception_test.cpp | 229 ++++++++++ src/kernel/yask_main.cpp | 404 +++++++++--------- 32 files changed, 1158 insertions(+), 375 deletions(-) create mode 100644 src/compiler/tests/yask_compiler_api_exception_test.cpp create mode 100644 src/compiler/yc-api-test-with-exception-cxx-readonly create mode 100644 src/compiler/yc-api-test-with-exception-py-readonly create mode 100644 src/kernel/tests/yask_kernel_api_exception_test.cpp diff --git a/Makefile b/Makefile index d373cdfd..5b12591e 100644 --- a/Makefile +++ b/Makefile @@ -193,6 +193,26 @@ py-yc-api-and-cxx-yk-api-test: $(YK_MAKE) py-yc-api-test $(YK_MAKE) cxx-yk-api-test +# Run C++ compiler API test with exception, then run C++ kernel API test with exception. +cxx-yc-api-and-cxx-yk-api-test-with-exception: + $(YK_MAKE) cxx-yc-api-test-with-exception + $(YK_MAKE) cxx-yk-api-test-with-exception + +# Run python compiler API test with exception, then run python kernel API test with exception. +py-yc-api-and-py-yk-api-test-with-exception: + $(YK_MAKE) py-yc-api-test-with-exception + $(YK_MAKE) py-yk-api-test-with-exception + +# Run C++ compiler API test with exception, then run python kernel API test with exception. +cxx-yc-api-and-py-yk-api-test-with-exception: + $(YK_MAKE) cxx-yc-api-test-with-exception + $(YK_MAKE) py-yk-api-test-with-exception + +# Run python compiler API test with exception, then run C++ kernel API test with exception. +py-yc-api-and-cxx-yk-api-test-with-exception: + $(YK_MAKE) py-yc-api-test-with-exception + $(YK_MAKE) cxx-yk-api-test-with-exception + api-tests: $(MAKE) yc-and-cxx-yk-api-test $(MAKE) yc-and-py-yk-api-test @@ -202,6 +222,10 @@ api-tests: $(MAKE) stencil=test py-yc-api-and-py-yk-api-test $(MAKE) stencil=test cxx-yc-api-and-py-yk-api-test $(MAKE) stencil=test py-yc-api-and-cxx-yk-api-test + $(MAKE) stencil=test cxx-yc-api-and-cxx-yk-api-test-with-exception + $(MAKE) stencil=test py-yc-api-and-py-yk-api-test-with-exception + $(MAKE) stencil=test cxx-yc-api-and-py-yk-api-test-with-exception + $(MAKE) stencil=test py-yc-api-and-cxx-yk-api-test-with-exception ######## Misc targets diff --git a/include/yask_common_api.hpp b/include/yask_common_api.hpp index 2bbb4e60..96eed5a8 100644 --- a/include/yask_common_api.hpp +++ b/include/yask_common_api.hpp @@ -67,6 +67,29 @@ namespace yask { /// Shared pointer to \ref yask_null_output typedef std::shared_ptr yask_null_output_ptr; + /// Exception from yask framework + /** Objects of this exception contain additional message from yask framework */ + class yask_exception: public std::exception { + private: + /// Additional message container + std::string msg; + + public: + virtual ~yask_exception() {}; + + /// Get default message. + /** Returns a C-style character string describing the general cause of the current error. + @returns default message of the exception. */ + virtual const char* what() noexcept; + + /// Add additional message to this exception. + void add_message(std::string message /**< [in] Additional message as string. */ ); + + /// Get additional message. + /** @returns additional message as string */ + std::string get_message(); + }; + /// Factory to create output objects. class yask_output_factory { public: @@ -81,7 +104,7 @@ namespace yask { virtual yask_file_output_ptr new_file_output(const std::string& file_name /**< [in] Name of file to open. - Any existing file will be truncated. */ ) const; + Any existing file will be truncated. */ ) const throw(yask_exception); /// Create a string output object. /** diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 0108e3fa..52aac47e 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -300,7 +300,7 @@ namespace yask { /**< [in] Name of type from above table. */, yask_output_ptr output /**< [out] Pointer to object to receive formatted output. - See \ref yask_output_factory. */) =0; + See \ref yask_output_factory. */) throw(yask_exception) =0; }; /// A compile-time grid. @@ -350,7 +350,7 @@ namespace yask { @returns Pointer to AST node used to read from or write to point in grid. */ virtual yc_grid_point_node_ptr new_relative_grid_point(std::vector dim_offsets - /**< [in] offset from evaluation index in each dim. */ ) =0; + /**< [in] offset from evaluation index in each dim. */ ) throw(yask_exception) =0; #ifndef SWIG /// Create a reference to a point in a grid. diff --git a/include/yask_kernel_api.hpp b/include/yask_kernel_api.hpp index 9f0ea1d0..2a1b1780 100644 --- a/include/yask_kernel_api.hpp +++ b/include/yask_kernel_api.hpp @@ -599,7 +599,7 @@ namespace yask { */ virtual void run_solution(idx_t first_step_index /**< [in] First index in the step dimension */, - idx_t last_step_index /**< [in] Last index in the step dimension */ ) =0; + idx_t last_step_index /**< [in] Last index in the step dimension */ ) throw(yask_exception) =0; /// Run the stencil solution for the specified step. /** @@ -612,7 +612,7 @@ namespace yask { wave-front tiling. */ virtual void - run_solution(idx_t step_index /**< [in] Index in the step dimension */ ) =0; + run_solution(idx_t step_index /**< [in] Index in the step dimension */ ) throw(yask_exception) =0; /// **[Advanced]** Restart or disable the auto-tuner on this rank. /** @@ -665,7 +665,7 @@ namespace yask { virtual void run_auto_tuner_now(bool verbose = true /**< [in] If _true_, print progress information to the debug object - set via set_debug_output(). */ ) =0; + set via set_debug_output(). */ ) throw(yask_exception) =0; /// **[Advanced]** Use data-storage from existing grids in specified solution. /** diff --git a/src/common/common_utils.cpp b/src/common/common_utils.cpp index 92ba681f..882c46f5 100644 --- a/src/common/common_utils.cpp +++ b/src/common/common_utils.cpp @@ -46,4 +46,17 @@ namespace yask { string yask_get_version_string() { return version; } + + // See yask_common_api.hpp for documentation. + const char* yask_exception::what() noexcept { + return msg.c_str(); + } + + void yask_exception::add_message(string arg_msg) { + msg.append(arg_msg); + } + + string yask_exception::get_message() { + return msg; + } } diff --git a/src/common/output.cpp b/src/common/output.cpp index 4e6274c7..13ef928c 100644 --- a/src/common/output.cpp +++ b/src/common/output.cpp @@ -66,11 +66,13 @@ namespace yask { _fname = file_name; _ofs.open(file_name, ofstream::out | ofstream::trunc); if (!_ofs.is_open()) { - - // TODO: throw exception. - cerr << "Error: cannot open '" << file_name << + yask_exception e; + stringstream err; + err << "Error: cannot open '" << file_name << "' for output.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } } @@ -116,7 +118,7 @@ namespace yask { // See yask_common_api.hpp for documentation. yask_file_output_ptr - yask_output_factory::new_file_output(const string& file_name) const { + yask_output_factory::new_file_output(const string& file_name) const throw(yask_exception) { auto p = make_shared(); assert(p.get()); p->open(file_name); diff --git a/src/compiler/Makefile b/src/compiler/Makefile index de9d5121..cfcfa973 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -50,6 +50,7 @@ YC_BASE := yask_compiler YC_MODULE := $(YC_BASE) YC_EXEC := $(BIN_DIR)/$(YC_BASE).exe YC_TEST_EXEC := $(BIN_DIR)/$(YC_BASE)_api_test.exe +YC_TEST_EXEC_WITH_EXCEPTION := $(BIN_DIR)/$(YC_BASE)_api_exception_test.exe YC_LIB := $(LIB_DIR)/lib$(YC_BASE)$(SO_SUFFIX) YC_PY_LIB := $(YASK_DIR)/_$(YC_MODULE)$(SO_SUFFIX) YC_PY_MOD := $(YASK_DIR)/$(YC_MODULE).py @@ -134,8 +135,10 @@ $(YC_SWIG_DIR)/yask_compiler_api_wrap.cpp: $(YC_SWIG_DIR)/yask*.i $(INC_DIR)/*.h $(SWIG) -version $(SWIG) -v -DYC_MODULE=$(YC_MODULE) -cppext cpp \ -I$(INC_DIR) -I$(COMM_DIR) -I$(COMM_DIR)/swig \ - -c++ -python -outdir $(YASK_DIR) -builtin $< - + -c++ -python -outdir $(YASK_DIR) $< +# TODO: '-builtin' flag prevents to handle exception correctly, so disable for now +# -c++ -python -outdir $(YASK_DIR) -builtin $< + $(YC_SWIG_DIR)/yask_compiler_api_wrap.o: $(YC_SWIG_DIR)/yask_compiler_api_wrap.cpp $(YC_CXX) $(YC_CXXFLAGS) $(PYINC) -fPIC -c -o $@ $< @@ -164,11 +167,35 @@ cxx-yc-api-test: $(YC_TEST_EXEC) - dot -Tpdf -O yc-api-test-cxx.dot ls -l yc-api-test-cxx.* +# Build C++ compiler API test with exception. +$(YC_TEST_EXEC_WITH_EXCEPTION): ./tests/yask_compiler_api_exception_test.cpp $(YC_LIB) + $(YC_CXX) $(YC_CXXFLAGS) $< $(YC_LFLAGS) -o $@ + +# Run Python compiler API test with exceptions to create stencil-code file. +# Also create .pdf rendering of stencil AST if Graphviz is installed. +py-yc-api-test-with-exception: $(BIN_DIR)/yask_compiler_api_exception_test.py $(YC_PY_LIB) + chmod 440 yc-api-test-with-exception-py-readonly + @echo '*** Running the Python YASK compiler API test with exception...' + $(RUN_PYTHON) $< + - dot -Tpdf -O yc-api-test-with-exception-py.dot + ls -l yc-api-test-with-exception-py.* + +# Run C++ compiler API test with exceptions to create stencil-code file. +# Also create .pdf rendering of stencil AST if Graphviz is installed. +cxx-yc-api-test-with-exception: $(YC_TEST_EXEC_WITH_EXCEPTION) + chmod 440 yc-api-test-with-exception-cxx-readonly + @echo '*** Running the C++ YASK compiler API test with exception...' + $< + - dot -Tpdf -O yc-api-test-with-exception-cxx.dot + ls -l yc-api-test-with-exception-cxx.* + ######## Misc targets all-tests: $(MAKE) cxx-yc-api-test $(MAKE) py-yc-api-test + $(MAKE) cxx-yc-api-test-with-exception + $(MAKE) py-yc-api-test-with-exception all: $(MAKE) compiler @@ -186,7 +213,7 @@ clean: # Remove executables, libs, etc. realclean: clean - rm -fv $(YC_LIB) $(YC_EXEC) $(YC_TEST_EXEC) $(YC_PY_MOD)* $(YC_PY_LIB) + rm -fv $(YC_LIB) $(YC_EXEC) $(YC_TEST_EXEC) $(YC_TEST_EXEC_WITH_EXCEPTION) $(YC_PY_MOD)* $(YC_PY_LIB) rm -fv *api-test*.dot* *api-test*.hpp* - find . -name '*.pyc' -print -delete - find . -name '*~' -print -delete diff --git a/src/compiler/lib/Eqs.cpp b/src/compiler/lib/Eqs.cpp index f1cbbd5d..e6f08b68 100644 --- a/src/compiler/lib/Eqs.cpp +++ b/src/compiler/lib/Eqs.cpp @@ -244,10 +244,14 @@ namespace yask { // LHS of an equation must use step dim w/a simple offset. auto* si1p = i1->getArgOffsets().lookup(stepDim); if (!si1p || abs(*si1p) != 1) { - cerr << "Error: equation " << eq1->makeQuotedStr() << + yask_exception e; + stringstream err; + err << "Error: equation " << eq1->makeQuotedStr() << " does not use offset +/- 1 from step-dimension index var '" << stepDim << "' on LHS.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } assert(si1p); si1 = *si1p; @@ -255,10 +259,14 @@ namespace yask { // Step direction already set? if (dims._stepDir) { if (dims._stepDir != si1) { - cerr << "Error: equation " << eq1->makeQuotedStr() << + yask_exception e; + stringstream err; + err << "Error: equation " << eq1->makeQuotedStr() << " LHS has offset " << si1 << " from step-dimesion index var, " "which is different than a previous equation with offset " << dims._stepDir << ".\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } } else dims._stepDir = si1; @@ -266,10 +274,14 @@ namespace yask { // LHS of an equation must be vectorizable. // TODO: relax this restriction. if (i1->getVecType() != GridPoint::VEC_FULL) { - cerr << "Error: equation " << eq1->makeQuotedStr() << + yask_exception e; + stringstream err; + err << "Error: equation " << eq1->makeQuotedStr() << " is not fully vectorizable on LHS because not all folded" " dimensions are accessed via simple offsets from their respective indices.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } } @@ -284,10 +296,14 @@ namespace yask { // Must be in proper relation to LHS. if ((si1 > 0 && rsi1 > si1) || (si1 < 0 && rsi1 < si1)) { - cerr << "Error: equation " << eq1->makeQuotedStr() << + yask_exception e; + stringstream err; + err << "Error: equation " << eq1->makeQuotedStr() << " RHS has offset " << rsi1 << " from step-dimesion index var, " "which is incompatible with LHS offset " << si1 << ".\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } // TODO: should make some dependency checks when rsi1 == si1. @@ -317,11 +333,15 @@ namespace yask { // cannot update the exact same point. if (!same_eq && same_cond && pt_vis.do_sets_intersect(op1, op2)) { - cerr << "Error: two equations with condition " << + yask_exception e; + stringstream err; + err << "Error: two equations with condition " << cond1->makeQuotedStr() << " update the same point: " << eq1->makeQuotedStr() << " and " << eq2->makeQuotedStr() << endl; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } // eq2 dep on eq1 => some output of eq1 is an input to eq2. @@ -334,10 +354,14 @@ namespace yask { if (same_eq) { // Exit with error. - cerr << "Error: illegal dependency between LHS and RHS of equation " << + yask_exception e; + stringstream err; + err << "Error: illegal dependency between LHS and RHS of equation " << eq1->makeQuotedStr() << " within offsets in range " << pts.makeDimValStr(" * ") << ".\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } // Save dependency. @@ -726,10 +750,14 @@ namespace yask { // Must swap on certain deps. if (egi.isDepOn(certain_dep, egj)) { if (egj.isDepOn(certain_dep, egi)) { - cerr << "Error: circular dependency between eq-groups " << + yask_exception e; + stringstream err; + err << "Error: circular dependency between eq-groups " << egi.getDescription() << " and " << egj.getDescription() << endl; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } do_swap = true; } diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index 5b6878cf..077e325e 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -389,10 +389,14 @@ namespace yask { // Check for correct number of args. size_t nd = grid->getDims().size(); if (nd != args.size()) { - cerr << "Error: attempt to create a grid point in " << + yask_exception e; + stringstream err; + err << "Error: attempt to create a grid point in " << nd << "-D grid '" << getGridName() << "' with " << args.size() << " indices.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } // Eval each arg. diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index 773841b0..a87da144 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -136,9 +136,13 @@ namespace yask { template shared_ptr castExpr(ExprPtr ep, const string& descrip) { auto tp = dynamic_pointer_cast(ep); if (!tp) { - cerr << "Error: expression '" << ep->makeStr() << "' is not a " << + yask_exception e; + stringstream err; + err << "Error: expression '" << ep->makeStr() << "' is not a " << descrip << "." << endl; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } return tp; } @@ -168,9 +172,13 @@ namespace yask { // Get the current value. // Exit with error if not known. virtual double getNumVal() const { - cerr << "Error: cannot evaluate '" << makeStr() << + yask_exception e; + stringstream err; + err << "Error: cannot evaluate '" << makeStr() << "' for a known numerical value.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } // Get the value as an integer. @@ -179,9 +187,13 @@ namespace yask { double val = getNumVal(); int ival = int(val); if (val != double(ival)) { - cerr << "Error: '" << makeStr() << + yask_exception e; + stringstream err; + err << "Error: '" << makeStr() << "' does not evaluate to an integer.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } return ival; } @@ -285,9 +297,13 @@ namespace yask { // Get the current value. // Exit with error if not known. virtual bool getBoolVal() const { - cerr << "Error: cannot evaluate '" << makeStr() << + yask_exception e; + stringstream err; + err << "Error: cannot evaluate '" << makeStr() << "' for a known boolean value.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } // Create a deep copy of this expression. diff --git a/src/compiler/lib/Grid.cpp b/src/compiler/lib/Grid.cpp index 5f54c249..e3314cc5 100644 --- a/src/compiler/lib/Grid.cpp +++ b/src/compiler/lib/Grid.cpp @@ -37,14 +37,18 @@ namespace yask { // grid APIs. yc_grid_point_node_ptr - Grid::new_relative_grid_point(std::vector dim_offsets) { + Grid::new_relative_grid_point(std::vector dim_offsets) throw(yask_exception) { // Check for correct number of indices. if (_dims.size() != dim_offsets.size()) { - cerr << "Error: attempt to create a relative grid point in " << + yask_exception e; + stringstream err; + err << "Error: attempt to create a relative grid point in " << _dims.size() << "D grid '" << _name << "' with " << dim_offsets.size() << " indices.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } // Check dim types. @@ -53,11 +57,15 @@ namespace yask { for (size_t i = 0; i < _dims.size(); i++) { auto dim = _dims.at(i); if (dim->getType() == MISC_INDEX) { - cerr << "Error: attempt to create a relative grid point in " << + yask_exception e; + stringstream err; + err << "Error: attempt to create a relative grid point in " << _dims.size() << "D grid '" << _name << "' containing non-step or non-domain dim '" << dim->getName() << "'.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } auto ie = dim->clone(); args.push_back(ie); @@ -294,9 +302,13 @@ namespace yask { case STEP_INDEX: if (_stepDim.length() && _stepDim != dname) { - cerr << "Error: step dimensions '" << _stepDim << + yask_exception e; + stringstream err; + err << "Error: step dimensions '" << _stepDim << "' and '" << dname << "' found; only one allowed.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } _stepDim = dname; _stencilDims.addDimFront(dname, 0); // must be first! @@ -315,18 +327,30 @@ namespace yask { break; default: - cerr << "Error: unexpected dim type " << type << ".\n"; - exit(1); + yask_exception e; + stringstream err; + err << "Error: unexpected dim type " << type << ".\n"; + e.add_message(err.str()); + throw e; + //exit(1); } } } if (_stepDim.length() == 0) { - cerr << "Error: no step dimension defined.\n"; - exit(1); + yask_exception e; + stringstream err; + err << "Error: no step dimension defined.\n"; + e.add_message(err.str()); + throw e; + //exit(1); } if (!_domainDims.getNumDims()) { - cerr << "Error: no domain dimensions defined.\n"; - exit(1); + yask_exception e; + stringstream err; + err << "Error: no domain dimensions defined.\n"; + e.add_message(err.str()); + throw e; + //exit(1); } // Use last domain dim as inner one. @@ -421,9 +445,13 @@ namespace yask { // Checks for unaligned loads. if (settings._allowUnalignedLoads) { if (_foldGT1.size() > 1) { - cerr << "Error: attempt to allow unaligned loads when there are " << + yask_exception e; + stringstream err; + err << "Error: attempt to allow unaligned loads when there are " << _foldGT1.size() << " dimensions in the vector-fold that are > 1." << endl; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } else if (_foldGT1.size() > 0) cerr << "Notice: memory layout MUST have unit-stride in " << diff --git a/src/compiler/lib/Grid.hpp b/src/compiler/lib/Grid.hpp index dd42b658..f5b95ebe 100644 --- a/src/compiler/lib/Grid.hpp +++ b/src/compiler/lib/Grid.hpp @@ -233,7 +233,7 @@ namespace yask { } virtual std::vector get_dim_names() const; virtual yc_grid_point_node_ptr - new_relative_grid_point(std::vector dim_offsets); + new_relative_grid_point(std::vector dim_offsets) throw(yask_exception); virtual yc_grid_point_node_ptr new_relative_grid_point(const std::initializer_list& dim_offsets) { std::vector dim_ofs_vec(dim_offsets); diff --git a/src/compiler/lib/Parse.hpp b/src/compiler/lib/Parse.hpp index 5a9c8df2..d44e2eba 100644 --- a/src/compiler/lib/Parse.hpp +++ b/src/compiler/lib/Parse.hpp @@ -45,7 +45,8 @@ namespace yask { class ArgParser { public: - + virtual ~ArgParser() {} + // For strings like x=4,y=2, call the lambda function for // each key, value pair. virtual void parseKeyValuePairs(const string& argStr, @@ -73,8 +74,12 @@ namespace yask { // split by equal sign. size_t ep = pStr.find("="); if (ep == string::npos) { + yask_exception e; + stringstream err; cerr << "Error: no equal sign in '" << pStr << "'." << endl; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } string key = pStr.substr(0, ep); string value = pStr.substr(ep+1); diff --git a/src/compiler/lib/Soln.cpp b/src/compiler/lib/Soln.cpp index 23fecb7d..6d6b1ef4 100644 --- a/src/compiler/lib/Soln.cpp +++ b/src/compiler/lib/Soln.cpp @@ -119,7 +119,7 @@ namespace yask { // Format in given format-type. void StencilSolution::format(const string& format_type, - yask_output_ptr output) { + yask_output_ptr output) throw(yask_exception) { // Look for format match. // Most args to the printers just set references to data. @@ -142,9 +142,13 @@ namespace yask { else if (format_type == "pov-ray") // undocumented. printer = new POVRayPrinter(*this, _clusterEqGroups); else { - cerr << "Error: format-type '" << format_type << + yask_exception e; + stringstream err; + err << "Error: format-type '" << format_type << "' is not recognized." << endl; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } assert(printer); int vlen = printer->num_vec_elems(); diff --git a/src/compiler/lib/Soln.hpp b/src/compiler/lib/Soln.hpp index 38dad0f1..422cb351 100644 --- a/src/compiler/lib/Soln.hpp +++ b/src/compiler/lib/Soln.hpp @@ -167,7 +167,7 @@ namespace yask { virtual void set_element_bytes(int nbytes) { _settings._elem_bytes = nbytes; } virtual int get_element_bytes() const { return _settings._elem_bytes; } virtual void format(const std::string& format_type, - yask_output_ptr output); + yask_output_ptr output) throw(yask_exception) ; }; // A stencil solution that does not define any grids. diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index 52d1ca2a..b175e015 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -230,10 +230,14 @@ namespace yask { if (dtype == STEP_INDEX) { assert(dname == _dims->_stepDim); if (dn > 0) { - cerr << "Error: cannot create grid '" << grid << + yask_exception e; + stringstream err; + err << "Error: cannot create grid '" << grid << "' with dimensions '" << gdims.makeDimStr() << "' because '" << dname << "' must be first dimension.\n"; - exit(1); + e.add_message(err.str()); + throw e; + //exit(1); } if (folded) { step_posn = dn + 1; @@ -722,4 +726,3 @@ namespace yask { } } // namespace yask. - diff --git a/src/compiler/main.cpp b/src/compiler/main.cpp index 00cd3ee7..3d5b90cf 100644 --- a/src/compiler/main.cpp +++ b/src/compiler/main.cpp @@ -305,21 +305,27 @@ int main(int argc, const char* argv[]) { "Copyright (c) 2014-2018, Intel Corporation.\n" "Version: " << yask_get_version_string() << endl; - // Parse options and create the stencil-solution object. - parseOpts(argc, argv); - - // Create the requested output... - for (auto i : outfiles) { - auto& type = i.first; - auto& fname = i.second; - - yask_output_factory ofac; - yask_output_ptr os; - if (fname == "-") - os = ofac.new_stdout_output(); - else - os = ofac.new_file_output(fname); - stencilSoln->format(type, os); + try { + // Parse options and create the stencil-solution object. + parseOpts(argc, argv); + + // Create the requested output... + for (auto i : outfiles) { + auto& type = i.first; + auto& fname = i.second; + + yask_output_factory ofac; + yask_output_ptr os; + if (fname == "-") + os = ofac.new_stdout_output(); + else + os = ofac.new_file_output(fname); + stencilSoln->format(type, os); + } + } catch (yask_exception e) { + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + exit(1); } cout << "YASK Stencil Compiler done.\n"; diff --git a/src/compiler/tests/yask_compiler_api_exception_test.cpp b/src/compiler/tests/yask_compiler_api_exception_test.cpp new file mode 100644 index 00000000..5444d948 --- /dev/null +++ b/src/compiler/tests/yask_compiler_api_exception_test.cpp @@ -0,0 +1,154 @@ +/***************************************************************************** + +YASK: Yet Another Stencil Kernel +Copyright (c) 2014-2018, Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +*****************************************************************************/ + +// Test the YASK stencil compiler API for C++. + +#include "yask_compiler_api.hpp" +#include + +using namespace std; +using namespace yask; + +int main() { + + // Counter for exception test + int num_exception = 0; + + // Compiler 'bootstrap' factories. + yc_factory cfac; + yask_output_factory ofac; + yc_node_factory fac; + + // Create a new stencil solution. + auto soln = cfac.new_solution("api_cxx_test"); + auto stdos = ofac.new_stdout_output(); + soln->set_debug_output(stdos); + + // Define the problem dimensions. + auto t = fac.new_step_index("t"); + auto x = fac.new_domain_index("x"); + auto y = fac.new_domain_index("y"); + auto z = fac.new_domain_index("z"); + + // Create a grid var. + auto g1 = soln->new_grid("test_grid", {t, x, y, z}); + + // Create an equation for the grid. + + auto n1 = fac.new_const_number_node(3.14); + cout << n1->format_simple() << endl; + + auto n2 = fac.new_negate_node(n1); + cout << n2->format_simple() << endl; + + // Exception test + cout << "Exception Test: Call 'new_relative_grid_point' with wrong argument.\n"; + try { + auto n3 = g1->new_relative_grid_point({0, +1, 0, -2, 1}); + } catch (yask_exception e) { + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } + + auto n3 = g1->new_relative_grid_point({0, +1, 0, -2}); + cout << n3->format_simple() << endl; + + auto n4a = fac.new_add_node(n2, n3); + auto n4b = fac.new_add_node(n4a, n1); + cout << n4b->format_simple() << endl; + + auto n5 = g1->new_relative_grid_point({0, +1, -1, 0}); + cout << n5->format_simple() << endl; + + auto n6 = fac.new_multiply_node(n4b, n5); + cout << n6->format_simple() << endl; + + auto n_lhs = g1->new_relative_grid_point({+1, 0, 0, 0}); + cout << n_lhs->format_simple() << endl; + + auto n_eq = fac.new_equation_node(n_lhs, n6); + cout << n_eq->format_simple() << endl; + + cout << "Solution '" << soln->get_name() << "' contains " << + soln->get_num_grids() << " grid(s), and " << + soln->get_num_equations() << " equation(s)." << endl; + + // Number of bytes in each FP value. + soln->set_element_bytes(4); + + // Exception test + cout << "Exception Test: Call 'new_file_output' with read-only file name.\n"; + try { + auto dot_file = ofac.new_file_output("yc-api-test-with-exception-cxx-readonly"); + } catch (yask_exception e) { + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } + + // Generate DOT output. + auto dot_file = ofac.new_file_output("yc-api-test-with-exception-cxx.dot"); + soln->format("dot", dot_file); + cout << "DOT-format written to '" << dot_file->get_filename() << "'.\n"; + + // Generate YASK output. + auto yask_file = ofac.new_file_output("yc-api-test-with-exception-cxx.hpp"); + soln->format("avx", yask_file); + cout << "YASK-format written to '" << yask_file->get_filename() << "'.\n"; + + // Exception test + cout << "Exception Test: Call 'format' with wrong format.\n"; + try { + soln->format("wrong_format", dot_file); + } catch (yask_exception e) { + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } + + // TODO: better to have exception test for the methods below + // Eqs::findDeps (<-EqGroups::makeEqGroups<-StencilSolution::analyze_solution<-StencilSolution::format()) + // EqGroups::sort (<-EqGroups::makeEqGroups<-StencilSolution::analyze_solution<-StencilSolution::format()) + // GridPoint::GridPoint + // castExpr + // NumExpr::getNumVal, NumExpr::getIntVal, NumExpr::getBoolVal + // Dimensions::setDims (<-StencilSolution::analyze_solution<-StencilSolution::format) + // ArgParser::parseKeyValuePairs + // YASKCppPrinter::printData (<-YASKCppPrinter::print<-StencilSolution::format) + + // Check whether program handles exceptions or not. + if (num_exception != 3) { + cout << "There is a problem in exception test.\n"; + exit(1); + } + else + cout << "End of YASK compiler API test with exception.\n"; + + return 0; +} diff --git a/src/compiler/tests/yask_compiler_api_test.cpp b/src/compiler/tests/yask_compiler_api_test.cpp index 66b8b60b..1cbf425d 100644 --- a/src/compiler/tests/yask_compiler_api_test.cpp +++ b/src/compiler/tests/yask_compiler_api_test.cpp @@ -48,7 +48,7 @@ int main() { auto x = fac.new_domain_index("x"); auto y = fac.new_domain_index("y"); auto z = fac.new_domain_index("z"); - + // Create a grid var. auto g1 = soln->new_grid("test_grid", {t, x, y, z}); diff --git a/src/compiler/yc-api-test-with-exception-cxx-readonly b/src/compiler/yc-api-test-with-exception-cxx-readonly new file mode 100644 index 00000000..16ba9801 --- /dev/null +++ b/src/compiler/yc-api-test-with-exception-cxx-readonly @@ -0,0 +1 @@ +Exception Test diff --git a/src/compiler/yc-api-test-with-exception-py-readonly b/src/compiler/yc-api-test-with-exception-py-readonly new file mode 100644 index 00000000..16ba9801 --- /dev/null +++ b/src/compiler/yc-api-test-with-exception-py-readonly @@ -0,0 +1 @@ +Exception Test diff --git a/src/kernel/Makefile b/src/kernel/Makefile index ceafa833..3e9ecbce 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -364,6 +364,7 @@ YK_PY_LIB := $(YASK_DIR)/_$(YK_MODULE)$(SO_SUFFIX) YK_PY_MOD := $(YASK_DIR)/$(YK_MODULE).py YK_API_TEST_EXEC := $(BIN_DIR)/$(YK_BASE)_api_test.exe YK_GRID_TEST_EXEC := $(BIN_DIR)/$(YK_BASE)_grid_test.exe +YK_API_TEST_EXEC_WITH_EXCEPTION := $(BIN_DIR)/$(YK_BASE)_api_exception_test.exe MAKE_REPORT_FILE:= make-report.$(YK_TAG).txt @@ -621,7 +622,9 @@ $(YK_SWIG_DIR)/yask_kernel_api_wrap.cpp: $(YK_SWIG_DIR)/yask*.i $(INC_DIR)/*.hpp $(SWIG) -version $(SWIG) -v -DYK_MODULE=$(YK_MODULE) -cppext cpp \ -I$(INC_DIR) -I$(COMM_DIR) -I$(COMM_DIR)/swig \ - -c++ -python -outdir $(YASK_DIR) -builtin $< + -c++ -python -outdir $(YASK_DIR) $< +# TODO: '-builtin' flag prevents to handle exception correctly, so disable for now +# -c++ -python -outdir $(YASK_DIR) -builtin $< $(YK_SWIG_DIR)/yask_kernel_api_wrap.o: $(YK_SWIG_DIR)/yask_kernel_api_wrap.cpp $(YK_CXX) $(YK_CXXFLAGS) $(PYINC) -fPIC -c -o $@ $< @@ -654,6 +657,20 @@ py-yk-api-test: $(BIN_DIR)/yask_kernel_api_test.py $(YK_PY_LIB) @echo '*** Running the Python YASK kernel API test...' $(RUN_PYTHON) $< +# Build C++ kernel tests with exceptions. +$(YK_API_TEST_EXEC_WITH_EXCEPTION): ./tests/yask_kernel_api_exception_test.cpp $(YK_LIB) + $(YK_CXX) $(YK_CXXFLAGS) $< $(YK_LFLAGS) -o $@ + +# Run C++ tests with exceptions. +cxx-yk-api-test-with-exception: $(YK_API_TEST_EXEC_WITH_EXCEPTION) + @echo '*** Running the C++ YASK kernel API test with exception...' + $(RUN_PREFIX) $< + +# Run Python kernel API test with exceptions. +py-yk-api-test-with-exception: $(BIN_DIR)/yask_kernel_api_exception_test.py $(YK_PY_LIB) + @echo '*** Running the Python YASK kernel API test with exception...' + $(RUN_PYTHON) $< + ### API tests for the compiler. # These targets run the tests in the compiler directory, # then they move the output files into the correct location @@ -670,6 +687,18 @@ cxx-yc-api-test: $(MAKE) -C $(YC_SRC_DIR) $@ $(YK_MK_GEN_DIR) mv $(YC_SRC_DIR)/yc-api-test-cxx.hpp $(YK_CODE_FILE) + +# Run Python compiler API test with exceptions to create stencil-code file. +py-yc-api-test-with-exception: + $(MAKE) -C $(YC_SRC_DIR) $@ + $(YK_MK_GEN_DIR) + mv $(YC_SRC_DIR)/yc-api-test-with-exception-py.hpp $(YK_CODE_FILE) + +# Run C++ compiler API test with exceptions to create stencil-code file. +cxx-yc-api-test-with-exception: + $(MAKE) -C $(YC_SRC_DIR) $@ + $(YK_MK_GEN_DIR) + mv $(YC_SRC_DIR)/yc-api-test-with-exception-cxx.hpp $(YK_CODE_FILE) ######## Misc targets @@ -729,7 +758,7 @@ clean: # Remove executables, libs, etc. realclean: clean - rm -fv $(YK_LIB) $(YK_EXEC) $(YK_API_TEST_EXEC) $(YK_PY_MOD)* $(YK_PY_LIB) + rm -fv $(YK_LIB) $(YK_EXEC) $(YK_API_TEST_EXEC) $(YK_API_TEST_EXEC_WITH_EXCEPTION) $(YK_PY_MOD)* $(YK_PY_LIB) rm -fv make-report.*.txt - find . -name '*.pyc' -print -delete - find . -name '*~' -print -delete diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index ec9a900e..894fd214 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -208,7 +208,7 @@ namespace yask { // Eval stencil group(s) over grid(s) using optimized code. void StencilContext::run_solution(idx_t first_step_index, - idx_t last_step_index) + idx_t last_step_index) throw(yask_exception) { run_time.start(); @@ -233,8 +233,12 @@ namespace yask { TRACE_MSG("run_solution: " << begin.makeDimValStr() << " ... (end before) " << end.makeDimValStr() << " by " << step.makeDimValStr()); if (!bb_valid) { - cerr << "Error: run_solution() called without calling prepare_solution() first.\n"; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: run_solution() called without calling prepare_solution() first.\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } if (bb_size < 1) { TRACE_MSG("nothing to do in solution"); @@ -345,14 +349,22 @@ namespace yask { // TODO: enable reverse time w/wave-fronts. if (step_t < 0) { - cerr << "Error: reverse time with wave-fronts not yet supported.\n"; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: reverse time with wave-fronts not yet supported.\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } // TODO: enable halo exchange for wave-fronts. if (_env->num_ranks > 1) { - cerr << "Error: halo exchange with wave-fronts not yet supported.\n"; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: halo exchange with wave-fronts not yet supported.\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } // Eval all stencil groups. @@ -428,8 +440,12 @@ namespace yask { // Not yet supporting temporal blocking. if (_opts->_block_sizes[step_dim] != 1) { - cerr << "Error: temporal blocking not yet supported." << endl; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: temporal blocking not yet supported." << endl; + e.add_message(err.str()); + throw e; + //exit_yask(1); } // Steps within a region are based on block sizes. @@ -767,10 +783,14 @@ namespace yask { } // Apply auto-tuning to some of the settings. - void StencilContext::run_auto_tuner_now(bool verbose) { + void StencilContext::run_auto_tuner_now(bool verbose) throw(yask_exception) { if (!bb_valid) { - cerr << "Error: tune_settings() called without calling prepare_solution() first.\n"; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: tune_settings() called without calling prepare_solution() first.\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } ostream& os = get_ostr(); os << "Auto-tuning...\n" << flush; @@ -824,8 +844,12 @@ namespace yask { void StencilContext::addGrid(YkGridPtr gp, bool is_output) { auto& gname = gp->get_name(); if (gridMap.count(gname)) { - cerr << "Error: grid '" << gname << "' already exists.\n"; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: grid '" << gname << "' already exists.\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } // Add to list and map. @@ -852,10 +876,14 @@ namespace yask { // Check ranks. idx_t req_ranks = _opts->_num_ranks.product(); if (req_ranks != _env->num_ranks) { - cerr << "error: " << req_ranks << " rank(s) requested (" << + yask_exception e; + stringstream err; + err << "error: " << req_ranks << " rank(s) requested (" << _opts->_num_ranks.makeDimValStr(" * ") << "), but " << _env->num_ranks << " rank(s) are active." << endl; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } assertEqualityOverRanks(_opts->_rank_sizes[step_dim], _env->comm, "num steps"); @@ -920,17 +948,25 @@ namespace yask { // Myself. if (rn == me) { if (mandist != 0) { - cerr << "Internal error: distance to own rank == " << mandist << endl; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Internal error: distance to own rank == " << mandist << endl; + e.add_message(err.str()); + throw e; + //exit_yask(1); } } // Someone else. else { if (mandist == 0) { - cerr << "Error: ranks " << me << + yask_exception e; + stringstream err; + err << "Error: ranks " << me << " and " << rn << " at same coordinates." << endl; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } @@ -969,14 +1005,18 @@ namespace yask { auto rnsz = rsizes[rn][dj]; if (mysz != rnsz) { auto& dnamej = _opts->_rank_indices.getDimName(dj); - cerr << "Error: rank " << rn << " and " << me << + yask_exception e; + stringstream err; + err << "Error: rank " << rn << " and " << me << " are both at rank-index " << coords[me][di] << " in the '" << dname << "' dimension , but their rank-domain sizes are " << rnsz << " and " << mysz << " (resp.) in the '" << dj << "' dimension, making them unaligned.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } } @@ -1035,10 +1075,14 @@ namespace yask { // Is domain size at least as large as halo in direction // with multiple ranks? if (_opts->_num_ranks[dname] > 1 && rnsz < max_halos[di]) { - cerr << "Error: rank-domain size of " << rnsz << " in '" << + yask_exception e; + stringstream err; + err << "Error: rank-domain size of " << rnsz << " in '" << dname << "' in rank " << rn << " is less than largest halo size of " << max_halos[di] << endl; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } @@ -1468,7 +1512,7 @@ namespace yask { // Allocate grids and MPI bufs. // Initialize some data structures. - void StencilContext::prepare_solution() { + void StencilContext::prepare_solution() throw(yask_exception) { // Don't continue until all ranks are this far. _env->global_barrier(); @@ -1539,8 +1583,12 @@ namespace yask { // TODO: enable multi-rank wave-front tiling. auto& step_dim = _dims->_step_dim; if (_opts->_region_sizes[step_dim] > 1 && _env->num_ranks > 1) { - cerr << "MPI communication is not currently enabled with wave-front tiling." << endl; - exit_yask(1); + yask_exception e; + stringstream err; + err << "MPI communication is not currently enabled with wave-front tiling." << endl; + e.add_message(err.str()); + throw e; + //exit_yask(1); } os << endl; diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index 53424b9a..6dc44538 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -356,7 +356,7 @@ namespace yask { // Calculate rank position in problem. // Initialize some other data structures. // Print lots of stats. - virtual void prepare_solution(); + virtual void prepare_solution() throw(yask_exception); /// Get statistics associated with preceding calls to run_solution(). @@ -566,7 +566,7 @@ namespace yask { virtual yk_grid_ptr new_fixed_size_grid(const std::string& name, const GridDimNames& dims, - const GridDimSizes& dim_sizes) { + const GridDimSizes& dim_sizes) throw(yask_exception) { return newGrid(name, dims, &dim_sizes); } virtual yk_grid_ptr @@ -602,8 +602,8 @@ namespace yask { virtual idx_t get_overall_domain_size(const std::string& dim) const; virtual void run_solution(idx_t first_step_index, - idx_t last_step_index); - virtual void run_solution(idx_t step_index) { + idx_t last_step_index) throw(yask_exception); + virtual void run_solution(idx_t step_index) throw(yask_exception) { run_solution(step_index, step_index); } virtual void share_grid_storage(yk_solution_ptr source); @@ -627,7 +627,7 @@ namespace yask { virtual void reset_auto_tuner(bool enable, bool verbose = false) { _at.clear(!enable, verbose); } - virtual void run_auto_tuner_now(bool verbose = true); + virtual void run_auto_tuner_now(bool verbose = true) throw(yask_exception); virtual bool is_auto_tuner_enabled() { return !_at.is_done(); } diff --git a/src/kernel/lib/new_grid.cpp b/src/kernel/lib/new_grid.cpp index 17cdf461..d5ae32a6 100644 --- a/src/kernel/lib/new_grid.cpp +++ b/src/kernel/lib/new_grid.cpp @@ -37,10 +37,14 @@ namespace yask { bool got_sizes = sizes != NULL; if (got_sizes) { if (dims.size() != sizes->size()) { - cerr << "Error: attempt to create grid '" << name << "' with " << + yask_exception e; + stringstream err; + err << "Error: attempt to create grid '" << name << "' with " << dims.size() << " dimension names but " << sizes->size() << " dimension sizes.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } @@ -59,19 +63,27 @@ namespace yask { // Already used? if (seenDims.count(dims[i])) { - cerr << "Error: cannot create grid '" << name << + yask_exception e; + stringstream err; + err << "Error: cannot create grid '" << name << "': dimension '" << dims[i] << "' used more than once.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } // Step dim? if (dims[i] == _dims->_step_dim) { step_posn = i; if (i > 0) { - cerr << "Error: cannot create grid '" << name << + yask_exception e; + stringstream err; + err << "Error: cannot create grid '" << name << "' because step dimension '" << dims[i] << "' must be first dimension.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } } @@ -85,10 +97,14 @@ namespace yask { #include "yask_grid_code.hpp" if (!gp) { - cerr << "Error in new_grid: cannot create grid '" << name << + yask_exception e; + stringstream err; + err << "Error in new_grid: cannot create grid '" << name << "' with " << ndims << " dimensions; only up to " << MAX_DIMS << " dimensions supported.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } diff --git a/src/kernel/lib/realv.hpp b/src/kernel/lib/realv.hpp index cbf395fc..6efb635b 100644 --- a/src/kernel/lib/realv.hpp +++ b/src/kernel/lib/realv.hpp @@ -646,8 +646,12 @@ namespace yask { } #elif defined(ARCH_KNC) - std::cerr << "error: 2-input permute not supported on KNC" << std::endl; - exit_yask(1); + yask_exception e; + std::stringstream err; + err << "error: 2-input permute not supported on KNC" << std::endl; + e.add_message(err.str()); + throw e; + //exit_yask(1); #else res.u.mi = INAMEI(permutex2var)(a.u.mi, ctrl.u.mi, b.u.mi); #endif diff --git a/src/kernel/lib/realv_grids.cpp b/src/kernel/lib/realv_grids.cpp index 4282b828..b309a174 100644 --- a/src/kernel/lib/realv_grids.cpp +++ b/src/kernel/lib/realv_grids.cpp @@ -128,11 +128,15 @@ namespace yask { auto& dims = _ggb->get_dims(); int posn = dims.lookup_posn(dim); if (posn < 0 && die_on_failure) { - cerr << "Error: " << die_msg << ": dimension '" << + yask_exception e; + stringstream err; + err << "Error: " << die_msg << ": dimension '" << dim << "' not found in "; print_info(cerr); - cerr << ".\n"; - exit_yask(1); + err << ".\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } return posn; } @@ -159,12 +163,16 @@ namespace yask { // Attempt to change alloc with existing storage? if (p && old_allocs != new_allocs) { - cerr << "Error: attempt to change allocation size of grid '" << + yask_exception e; + stringstream err; + err << "Error: attempt to change allocation size of grid '" << get_name() << "' from " << makeIndexString(old_allocs, " * ") << " to " << makeIndexString(new_allocs, " * ") << " after storage has been allocated.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } // Do the resize. @@ -199,11 +207,15 @@ namespace yask { bool domain_ok, bool misc_ok) const { if (!is_dim_used(dim)) { - cerr << "Error in " << fn_name << "(): dimension '" << + yask_exception e; + stringstream err; + err << "Error in " << fn_name << "(): dimension '" << dim << "' not found in "; print_info(cerr); - cerr << ".\n"; - exit_yask(1); + err << ".\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } _dims->checkDimType(dim, fn_name, step_ok, domain_ok, misc_ok); } @@ -242,8 +254,12 @@ namespace yask { assert(sp); if (!sp->get_raw_storage_buffer()) { - cerr << "Error: share_storage() called without source storage allocated.\n"; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: share_storage() called without source storage allocated.\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } // NB: requirements to successful share_storage() is not as strict as @@ -254,12 +270,16 @@ namespace yask { // Same dims? if (sp->get_num_dims() != get_num_dims() || sp->get_dim_name(i) != dname) { - cerr << "Error: share_storage() called with incompatible grids: "; + yask_exception e; + stringstream err; + err << "Error: share_storage() called with incompatible grids: "; print_info(cerr); - cerr << "; and "; + err << "; and "; sp->print_info(cerr); - cerr << ".\n"; - exit_yask(1); + err << ".\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } // Not a domain dim? @@ -268,10 +288,14 @@ namespace yask { auto tas = get_alloc_size(dname); auto sas = sp->get_alloc_size(dname); if (tas != sas) { - cerr << "Error: attempt to share storage from grid '" << sp->get_name() << + yask_exception e; + stringstream err; + err << "Error: attempt to share storage from grid '" << sp->get_name() << "' of alloc-size " << sas << " with grid '" << get_name() << "' of alloc-size " << tas << " in '" << dname << "' dim.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } @@ -280,10 +304,14 @@ namespace yask { auto tdom = get_rank_domain_size(dname); auto sdom = sp->get_rank_domain_size(dname); if (tdom != sdom) { - cerr << "Error: attempt to share storage from grid '" << sp->get_name() << + yask_exception e; + stringstream err; + err << "Error: attempt to share storage from grid '" << sp->get_name() << "' of domain-size " << sdom << " with grid '" << get_name() << "' of domain-size " << tdom << " in '" << dname << "' dim.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } // Halo and pad sizes don't have to be the same. @@ -291,20 +319,28 @@ namespace yask { auto thalo = get_halo_size(dname); auto spad = sp->get_pad_size(dname); if (thalo > spad) { - cerr << "Error: attempt to share storage from grid '" << sp->get_name() << + yask_exception e; + stringstream err; + err << "Error: attempt to share storage from grid '" << sp->get_name() << "' of padding-size " << spad << ", which is insufficient for grid '" << get_name() << "' of halo-size " << thalo << " in '" << dname << "' dim.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } // Check folding. if (_vec_lens[i] != sp->_vec_lens[i]) { - cerr << "Error: attempt to share storage from grid '" << sp->get_name() << + yask_exception e; + stringstream err; + err << "Error: attempt to share storage from grid '" << sp->get_name() << "' of fold-length " << sp->_vec_lens[i] << " with grid '" << get_name() << "' of fold-length " << _vec_lens[i] << " in '" << dname << "' dim.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } @@ -321,8 +357,12 @@ namespace yask { // Copy data. release_storage(); if (!share_data(sp.get(), true)) { - cerr << "Error: unexpected failure in data sharing.\n"; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: unexpected failure in data sharing.\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } } @@ -415,9 +455,13 @@ namespace yask { Indices* fixed_indices) const { auto n = get_num_dims(); if (indices.getNumDims() != n) { - cerr << "Error: '" << fn << "' called with " << indices.getNumDims() << + yask_exception e; + stringstream err; + err << "Error: '" << fn << "' called with " << indices.getNumDims() << " indices instead of " << n << ".\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } if (fixed_indices) *fixed_indices = indices; @@ -442,10 +486,14 @@ namespace yask { // Handle outliers. if (!ok) { if (strict_indices) { - cerr << "Error: " << fn << ": index in dim '" << dname << + yask_exception e; + stringstream err; + err << "Error: " << fn << ": index in dim '" << dname << "' is " << idx << ", which is not in [" << first_ok << "..." << last_ok << "].\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } if (fixed_indices) { if (idx < first_ok) @@ -492,9 +540,13 @@ namespace yask { // API get/set. double YkGridBase::get_element(const Indices& indices) const { if (!is_storage_allocated()) { - cerr << "Error: call to 'get_element' with no data allocated for grid '" << + yask_exception e; + stringstream err; + err << "Error: call to 'get_element' with no data allocated for grid '" << get_name() << "'.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } checkIndices(indices, "get_element", true, false); idx_t asi = get_alloc_step_index(indices[Indices::step_posn]); @@ -521,9 +573,13 @@ namespace yask { const Indices& first_indices, const Indices& last_indices) const { if (!is_storage_allocated()) { - cerr << "Error: call to 'get_elements_in_slice' with no data allocated for grid '" << + yask_exception e; + stringstream err; + err << "Error: call to 'get_elements_in_slice' with no data allocated for grid '" << get_name() << "'.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } checkIndices(first_indices, "get_elements_in_slice", true, false); checkIndices(last_indices, "get_elements_in_slice", true, false); diff --git a/src/kernel/lib/realv_grids.hpp b/src/kernel/lib/realv_grids.hpp index e569d20f..2036a557 100644 --- a/src/kernel/lib/realv_grids.hpp +++ b/src/kernel/lib/realv_grids.hpp @@ -97,21 +97,29 @@ namespace yask { auto* tp = dynamic_cast(_ggb); if (!tp) { if (die_on_failure) { - std::cerr << "Error in share_data(): " + yask_exception e; + std::stringstream err; + err << "Error in share_data(): " "target grid not of expected type (internal inconsistency).\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } return false; } auto* sp = dynamic_cast(src->_ggb); if (!sp) { if (die_on_failure) { - std::cerr << "Error in share_data(): source grid "; - src->print_info(std::cerr); - std::cerr << " not of same type as target grid "; - print_info(std::cerr); - std::cerr << ".\n"; - exit_yask(1); + yask_exception e; + std::stringstream err; + err << "Error in share_data(): source grid "; + src->print_info(err); + err << " not of same type as target grid "; + print_info(err); + err << ".\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } return false; } @@ -367,7 +375,7 @@ namespace yask { virtual void set_all_elements_same(double val) =0; virtual double get_element(const Indices& indices) const; - virtual double get_element(const GridIndices& indices) const { + virtual double get_element(const GridIndices& indices) const throw(yask_exception) { const Indices indices2(indices); return get_element(indices2); } @@ -904,9 +912,13 @@ namespace yask { const Indices& first_indices, const Indices& last_indices) const { if (!is_storage_allocated()) { - std::cerr << "Error: call to 'get_vecs_in_slice' with no data allocated for grid '" << + yask_exception e; + std::stringstream err; + err << "Error: call to 'get_vecs_in_slice' with no data allocated for grid '" << get_name() << "'.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } Indices firstv, lastv; checkIndices(first_indices, "get_vecs_in_slice", true, true, &firstv); diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index 63ecd32c..52a80cc9 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -38,22 +38,34 @@ namespace yask { return; if (dim == _step_dim) { if (!step_ok) { - cerr << "Error in " << fn_name << "(): dimension '" << + yask_exception e; + stringstream err; + err << "Error in " << fn_name << "(): dimension '" << dim << "' is the step dimension, which is not allowed.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } else if (_domain_dims.lookup(dim)) { if (!domain_ok) { - cerr << "Error in " << fn_name << "(): dimension '" << + yask_exception e; + stringstream err; + err << "Error in " << fn_name << "(): dimension '" << dim << "' is a domain dimension, which is not allowed.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } else if (!misc_ok) { - cerr << "Error in " << fn_name << "(): dimension '" << + yask_exception e; + stringstream err; + err << "Error in " << fn_name << "(): dimension '" << dim << "' is a misc dimension, which is not allowed.\n"; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } @@ -83,8 +95,12 @@ namespace yask { int provided = 0; MPI_Init_thread(argc, argv, MPI_THREAD_SERIALIZED, &provided); if (provided < MPI_THREAD_SERIALIZED) { - cerr << "error: MPI_THREAD_SERIALIZED not provided.\n"; - exit_yask(1); + yask_exception e; + stringstream err; + err << "error: MPI_THREAD_SERIALIZED not provided.\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } is_init = true; } diff --git a/src/kernel/lib/utils.cpp b/src/kernel/lib/utils.cpp index 3a022d88..10126deb 100644 --- a/src/kernel/lib/utils.cpp +++ b/src/kernel/lib/utils.cpp @@ -54,8 +54,12 @@ namespace yask { #endif if (!p) { - std::cerr << "error: cannot allocate " << makeByteStr(nbytes) << ".\n"; - exit_yask(1); + yask_exception e; + stringstream err; + err << "error: cannot allocate " << makeByteStr(nbytes) << ".\n"; + e.add_message(err.str()); + throw e; + //exit_yask(1); } return static_cast(p); } @@ -143,9 +147,13 @@ namespace yask { #endif if (min_val != rank_val || max_val != rank_val) { - cerr << "error: " << descr << " values range from " << min_val << " to " << + yask_exception e; + stringstream err; + err << "error: " << descr << " values range from " << min_val << " to " << max_val << " across the ranks. They should all be identical." << endl; - exit_yask(1); + e.add_message(err.str()); + throw e; + //exit_yask(1); } } @@ -211,16 +219,24 @@ namespace yask { int& argi) { if (size_t(argi) >= args.size() || args[argi].length() == 0) { - cerr << "Error: no argument for option '" << args[argi - 1] << "'." << endl; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: no argument for option '" << args[argi - 1] << "'." << endl; + e.add_message(err.str()); + throw e; + //exit_yask(1); } const char* nptr = args[argi].c_str(); char* endptr = 0; long long int val = strtoll(nptr, &endptr, 0); if (val == LLONG_MIN || val == LLONG_MAX || *endptr != '\0') { - cerr << "Error: argument for option '" << args[argi - 1] << "' is not an integer." << endl; - exit_yask(1); + yask_exception e; + stringstream err; + err << "Error: argument for option '" << args[argi - 1] << "' is not an integer." << endl; + e.add_message(err.str()); + throw e; + //exit_yask(1); } argi++; diff --git a/src/kernel/tests/yask_kernel_api_exception_test.cpp b/src/kernel/tests/yask_kernel_api_exception_test.cpp new file mode 100644 index 00000000..e5914a3c --- /dev/null +++ b/src/kernel/tests/yask_kernel_api_exception_test.cpp @@ -0,0 +1,229 @@ +/***************************************************************************** + +YASK: Yet Another Stencil Kernel +Copyright (c) 2014-2018, Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +*****************************************************************************/ + +// Test the YASK stencil kernel API for C++. + +#include "yask_kernel_api.hpp" +#include +#include +#include + +using namespace std; +using namespace yask; + +int main() { + + // Counter for exception test + int num_exception = 0; + + // The factory from which all other kernel objects are made. + yk_factory kfac; + + // Initalize MPI, etc. + auto env = kfac.new_env(); + + // Create solution. + auto soln = kfac.new_solution(env); + + // Init global settings. + auto soln_dims = soln->get_domain_dim_names(); + for (auto dim_name : soln_dims) { + + // Set domain size in each dim. + soln->set_rank_domain_size(dim_name, 128); + + // Ensure some minimal padding on all grids. + soln->set_min_pad_size(dim_name, 1); + + // Set block size to 64 in z dim and 32 in other dims. + if (dim_name == "z") + soln->set_block_size(dim_name, 64); + else + soln->set_block_size(dim_name, 32); + } + + // Make a test fixed-size grid. + vector fgrid_sizes; + for (auto dim_name : soln_dims) + fgrid_sizes.push_back(5); + auto fgrid = soln->new_fixed_size_grid("fgrid", soln_dims, fgrid_sizes); + + // Simple rank configuration in 1st dim only. + auto ddim1 = soln_dims[0]; + soln->set_num_ranks(ddim1, env->get_num_ranks()); + + // Exception test + cout << "Exception Test: Call 'run_solution' without calling prepare_solution().\n"; + try { + soln->run_solution(0); + } catch (yask_exception e) { + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } + + // Exception test + cout << "Exception Test: Call 'run_auto_tuner_now' without calling prepare_solution().\n"; + try { + soln->run_auto_tuner_now(false); + } catch (yask_exception e) { + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } + + + // Allocate memory for any grids that do not have storage set. + // Set other data structures needed for stencil application. + soln->prepare_solution(); + + // Print some info about the solution. + auto name = soln->get_name(); + cout << "Stencil-solution '" << name << "':\n"; + cout << " Step dimension: '" << soln->get_step_dim_name() << "'\n"; + cout << " Domain dimensions:"; + set domain_dim_set; + for (auto dname : soln->get_domain_dim_names()) { + cout << " '" << dname << "'"; + domain_dim_set.insert(dname); + } + cout << endl; + + // Print out some info about the grids and init their data. + for (auto grid : soln->get_grids()) { + cout << " " << grid->get_name() << "("; + for (auto dname : grid->get_dim_names()) + cout << " '" << dname << "'"; + cout << " )\n"; + for (auto dname : grid->get_dim_names()) { + if (domain_dim_set.count(dname)) { + cout << " '" << dname << "' domain index range on this rank: " << + grid->get_first_rank_domain_index(dname) << " ... " << + grid->get_last_rank_domain_index(dname) << endl; + cout << " '" << dname << "' allowed index range on this rank: " << + grid->get_first_rank_alloc_index(dname) << " ... " << + grid->get_last_rank_alloc_index(dname) << endl; + } + } + + // First, just init all the elements to the same value. + grid->set_all_elements_same(0.1); + + // Done with fixed-size grids. + if (grid->is_fixed_size()) + continue; + + // Create indices describing a subset of the overall domain. + vector first_indices, last_indices; + for (auto dname : grid->get_dim_names()) { + + // Is this a domain dim? + if (domain_dim_set.count(dname)) { + + // Set indices to creaete a small cube (assuming 3D) + // in center of overall problem. + idx_t psize = soln->get_overall_domain_size(dname); + idx_t first_idx = psize/2 - 10; + idx_t last_idx = psize/2 + 10; + first_indices.push_back(first_idx); + last_indices.push_back(last_idx); + } + + // Step dim? + else if (dname == soln->get_step_dim_name()) { + + // Add indices for timestep zero (0) only. + first_indices.push_back(0); + last_indices.push_back(0); + + } + + // Misc dim? + else { + + // Add indices to set all allowed values. + // (This isn't really meaningful; it's just illustrative.) + first_indices.push_back(grid->get_first_misc_index(dname)); + last_indices.push_back(grid->get_last_misc_index(dname)); + } + } + + // Init the values using the indices created above. + idx_t nset = grid->set_elements_in_slice_same(0.9, first_indices, last_indices); + cout << " " << nset << " element(s) set.\n"; + + // Raw access to this grid. + auto raw_p = grid->get_raw_storage_buffer(); + auto num_elems = grid->get_num_storage_elements(); + cout << " " << grid->get_num_storage_bytes() << + " bytes of raw data at " << raw_p << ": "; + if (soln->get_element_bytes() == 4) + cout << ((float*)raw_p)[0] << ", ..., " << ((float*)raw_p)[num_elems-1] << "\n"; + else + cout << ((double*)raw_p)[0] << ", ..., " << ((double*)raw_p)[num_elems-1] << "\n"; + } + + // Apply the stencil solution to the data. + env->global_barrier(); + cout << "Running the solution for 1 step...\n"; + soln->run_solution(0); + cout << "Running the solution for 10 more steps...\n"; + soln->run_solution(1, 10); + + // TODO: better to have exception test for the methods below + // StencilContext::calc_region + // StencilContext::addGrid + // StencilContext::setupRank + // StencilContext::prepare_solution + // StencilContext::newGrid + // YkGridBase::get_dim_posn + // YkGridBase::resize + // YkGridBase::checkDimType + // YkGridBase::share_storage + // YkGridBase::checkIndices + // YkGridBase::get_element + // YkGridBase::get_elements_in_slice + // YkGridBase::_share_data + // YkGridBase::get_vecs_in_slice + // real_vec_permute2 + // Dims::checkDimType + // KernelEnv::initEnv + // alignedAlloc + // assertEqualityOverRanks + // CommandLineParser::OptionBase::_idx_val + + + // Check whether program handles exceptions or not. + if (num_exception != 2) { + cout << "There is a problem in exception test.\n"; + exit(1); + } + else + cout << "End of YASK kernel API test with exception.\n"; + + return 0; +} diff --git a/src/kernel/yask_main.cpp b/src/kernel/yask_main.cpp index 20d1a017..c0049f6a 100644 --- a/src/kernel/yask_main.cpp +++ b/src/kernel/yask_main.cpp @@ -161,11 +161,15 @@ struct AppSettings : public KernelSettings { } if (args.size()) { - cerr << "Error: extraneous parameter(s):"; + yask_exception e; + stringstream err; + err << "Error: extraneous parameter(s):"; for (auto arg : args) - cerr << " '" << arg << "'"; - cerr << ".\nRun with '-help' option for usage.\n" << flush; - exit_yask(1); + err << " '" << arg << "'"; + err << ".\nRun with '-help' option for usage.\n" << flush; + e.add_message(err.str()); + throw e; + //exit_yask(1); } } @@ -219,199 +223,213 @@ void alloc_steps(yk_solution_ptr soln, const AppSettings& opts) { // Parse command-line args, run kernel, run validation if requested. int main(int argc, char** argv) { - // Stop collecting VTune data. - // Even better to use -start-paused option. - VTUNE_PAUSE; - - // Bootstrap factory from kernel API. - yk_factory kfac; - - // Set up the environment (mostly MPI). - auto kenv = kfac.new_env(); - auto ep = dynamic_pointer_cast(kenv); - - // Problem dimensions. - auto dims = YASK_STENCIL_CONTEXT::new_dims(); - - // Parse cmd-line options. - // TODO: do this through APIs. - auto opts = make_shared(dims, ep); - opts->parse(argc, argv); - - // Object containing data and parameters for stencil eval. - // TODO: do everything through API without cast to StencilContext. - auto ksoln = kfac.new_solution(kenv); - auto context = dynamic_pointer_cast(ksoln); - assert(context.get()); - context->set_settings(opts); - ostream& os = context->set_ostr(); - - // Make sure any MPI/OMP debug data is dumped from all ranks before continuing. - kenv->global_barrier(); - - // Print splash banner and related info. - opts->splash(os, argc, argv); - - // Override alloc if requested. - alloc_steps(ksoln, *opts); - - // Alloc memory, etc. - ksoln->prepare_solution(); - - // Exit if nothing to do. - if (opts->num_trials < 1) { - cerr << "Exiting because no trials are specified." << endl; - exit_yask(1); - } - if (context->bb_num_points < 1) { - cerr << "Exiting because there are no points in the domain." << endl; - exit_yask(1); - } - - // init data in grids and params. - if (opts->doWarmup || !opts->validate) - context->initData(); - - // just a line. - string divLine; - for (int i = 0; i < 60; i++) - divLine += "─"; - divLine += "\n"; - - // Invoke auto-tuner. - if (opts->doPreAutoTune) - ksoln->run_auto_tuner_now(); - - // Enable/disable further auto-tuning. - ksoln->reset_auto_tuner(opts->doAutoTune); - - // warmup caches, threading, etc. - if (opts->doWarmup) { - - idx_t dt = 1; - os << endl << divLine << - "Running " << dt << " step(s) for warm-up...\n" << flush; - ksoln->run_solution(0, dt-1); - - } - kenv->global_barrier(); - - // variables for measuring performance. - double best_elapsed_time=0., best_apps=0., best_dpps=0., best_flops=0.; - - /////// Performance run(s). - auto& step_dim = opts->_dims->_step_dim; - idx_t dt = opts->_rank_sizes[step_dim]; - os << endl << divLine << - "Running " << opts->num_trials << " performance trial(s) of " << - dt << " step(s) each...\n" << flush; - for (idx_t tr = 0; tr < opts->num_trials; tr++) { - os << divLine << flush; - - // init data before each trial for comparison if validating. - if (opts->validate) - context->initDiff(); - - // Warn if tuning. - if (ksoln->is_auto_tuner_enabled()) - os << "auto-tuner is active during this trial, so results may not be representative.\n"; - - // Stabilize. - if (opts->pre_trial_sleep_time > 0) { - os << flush; - sleep(opts->pre_trial_sleep_time); - } - kenv->global_barrier(); - - // Start vtune collection. - VTUNE_RESUME; - - // Actual work. - context->clear_timers(); - context->calc_rank_opt(); - - // Stop vtune collection. + // just a line. + string divLine; + for (int i = 0; i < 60; i++) + divLine += "─"; + divLine += "\n"; + + try { + // Stop collecting VTune data. + // Even better to use -start-paused option. VTUNE_PAUSE; - - // Calc and report perf. - auto stats = context->get_stats(); - - // Remember best. - if (context->domain_pts_ps > best_dpps) { - best_dpps = context->domain_pts_ps; - best_apps = context->writes_ps; - best_flops = context->flops; - best_elapsed_time = stats->get_elapsed_run_secs(); - } - } - os << divLine << - "best-elapsed-time (sec): " << makeNumStr(best_elapsed_time) << endl << - "best-throughput (num-points/sec): " << makeNumStr(best_dpps) << endl << - "best-throughput (est-FLOPS): " << makeNumStr(best_flops) << endl << - "best-throughput (num-writes/sec): " << makeNumStr(best_apps) << endl << - divLine << - "Notes:\n" << - " Num-points is based on overall-problem-size as described above.\n" << - " Num-writes is based on num-writes-required as described above.\n" << - " Est-FLOPS is based on est-FP-ops as described above.\n" << - endl; - - /////// Validation run. - bool ok = true; - if (opts->validate) { - kenv->global_barrier(); - os << endl << divLine << - "Setup for validation...\n"; - - // Make a reference context for comparisons w/new grids. - auto ref_soln = kfac.new_solution(kenv, ksoln); - auto ref_context = dynamic_pointer_cast(ref_soln); - assert(ref_context.get()); - ref_context->name += "-reference"; - ref_context->allow_vec_exchange = false; - alloc_steps(ref_soln, *opts); - ref_soln->prepare_solution(); - - // init to same value used in context. - ref_context->initDiff(); - -#ifdef CHECK_INIT - - // Debug code to determine if data compares immediately after init matches. - os << endl << divLine << - "Reinitializing data for minimal validation...\n" << flush; - context->initDiff(); -#else - - // Ref trial. - os << endl << divLine << - "Running " << dt << " time step(s) for validation...\n" << flush; - ref_context->calc_rank_ref(); -#endif - - // check for equality. - os << "Checking results..." << endl; - idx_t errs = context->compareData(*ref_context); - auto ri = kenv->get_rank_index(); - if( errs == 0 ) { - os << "TEST PASSED on rank " << ri << ".\n" << flush; - } else { - cerr << "TEST FAILED on rank " << ri << ": >= " << errs << " mismatch(es).\n" << flush; - if (REAL_BYTES < 8) - cerr << "This is not uncommon for low-precision FP; try with 8-byte reals." << endl; - ok = false; - } + // Bootstrap factory from kernel API. + yk_factory kfac; + + // Set up the environment (mostly MPI). + auto kenv = kfac.new_env(); + auto ep = dynamic_pointer_cast(kenv); + + // Problem dimensions. + auto dims = YASK_STENCIL_CONTEXT::new_dims(); + + // Parse cmd-line options. + // TODO: do this through APIs. + auto opts = make_shared(dims, ep); + opts->parse(argc, argv); + + // Object containing data and parameters for stencil eval. + // TODO: do everything through API without cast to StencilContext. + auto ksoln = kfac.new_solution(kenv); + auto context = dynamic_pointer_cast(ksoln); + assert(context.get()); + context->set_settings(opts); + ostream& os = context->set_ostr(); + + // Make sure any MPI/OMP debug data is dumped from all ranks before continuing. + kenv->global_barrier(); + + // Print splash banner and related info. + opts->splash(os, argc, argv); + + // Override alloc if requested. + alloc_steps(ksoln, *opts); + + // Alloc memory, etc. + ksoln->prepare_solution(); + + // Exit if nothing to do. + if (opts->num_trials < 1) { + yask_exception e; + stringstream err; + err << "Exiting because no trials are specified." << endl; + e.add_message(err.str()); + throw e; + //exit_yask(1); + } + if (context->bb_num_points < 1) { + yask_exception e; + stringstream err; + err << "Exiting because there are no points in the domain." << endl; + e.add_message(err.str()); + throw e; + //exit_yask(1); + } + + // init data in grids and params. + if (opts->doWarmup || !opts->validate) + context->initData(); + + // Invoke auto-tuner. + if (opts->doPreAutoTune) + ksoln->run_auto_tuner_now(); + + // Enable/disable further auto-tuning. + ksoln->reset_auto_tuner(opts->doAutoTune); + + // warmup caches, threading, etc. + if (opts->doWarmup) { + + idx_t dt = 1; + os << endl << divLine << + "Running " << dt << " step(s) for warm-up...\n" << flush; + ksoln->run_solution(0, dt-1); + + } + kenv->global_barrier(); + + // variables for measuring performance. + double best_elapsed_time=0., best_apps=0., best_dpps=0., best_flops=0.; + + /////// Performance run(s). + auto& step_dim = opts->_dims->_step_dim; + idx_t dt = opts->_rank_sizes[step_dim]; + os << endl << divLine << + "Running " << opts->num_trials << " performance trial(s) of " << + dt << " step(s) each...\n" << flush; + for (idx_t tr = 0; tr < opts->num_trials; tr++) { + os << divLine << flush; + + // init data before each trial for comparison if validating. + if (opts->validate) + context->initDiff(); + + // Warn if tuning. + if (ksoln->is_auto_tuner_enabled()) + os << "auto-tuner is active during this trial, so results may not be representative.\n"; + + // Stabilize. + if (opts->pre_trial_sleep_time > 0) { + os << flush; + sleep(opts->pre_trial_sleep_time); + } + kenv->global_barrier(); + + // Start vtune collection. + VTUNE_RESUME; + + // Actual work. + context->clear_timers(); + context->calc_rank_opt(); + + // Stop vtune collection. + VTUNE_PAUSE; + + // Calc and report perf. + auto stats = context->get_stats(); + + // Remember best. + if (context->domain_pts_ps > best_dpps) { + best_dpps = context->domain_pts_ps; + best_apps = context->writes_ps; + best_flops = context->flops; + best_elapsed_time = stats->get_elapsed_run_secs(); + } + } + + os << divLine << + "best-elapsed-time (sec): " << makeNumStr(best_elapsed_time) << endl << + "best-throughput (num-points/sec): " << makeNumStr(best_dpps) << endl << + "best-throughput (est-FLOPS): " << makeNumStr(best_flops) << endl << + "best-throughput (num-writes/sec): " << makeNumStr(best_apps) << endl << + divLine << + "Notes:\n" << + " Num-points is based on overall-problem-size as described above.\n" << + " Num-writes is based on num-writes-required as described above.\n" << + " Est-FLOPS is based on est-FP-ops as described above.\n" << + endl; + + /////// Validation run. + bool ok = true; + if (opts->validate) { + kenv->global_barrier(); + os << endl << divLine << + "Setup for validation...\n"; + + // Make a reference context for comparisons w/new grids. + auto ref_soln = kfac.new_solution(kenv, ksoln); + auto ref_context = dynamic_pointer_cast(ref_soln); + assert(ref_context.get()); + ref_context->name += "-reference"; + ref_context->allow_vec_exchange = false; + alloc_steps(ref_soln, *opts); + ref_soln->prepare_solution(); + + // init to same value used in context. + ref_context->initDiff(); + + #ifdef CHECK_INIT + + // Debug code to determine if data compares immediately after init matches. + os << endl << divLine << + "Reinitializing data for minimal validation...\n" << flush; + context->initDiff(); + #else + + // Ref trial. + os << endl << divLine << + "Running " << dt << " time step(s) for validation...\n" << flush; + ref_context->calc_rank_ref(); + #endif + + // check for equality. + os << "Checking results..." << endl; + idx_t errs = context->compareData(*ref_context); + auto ri = kenv->get_rank_index(); + if( errs == 0 ) { + os << "TEST PASSED on rank " << ri << ".\n" << flush; + } else { + cerr << "TEST FAILED on rank " << ri << ": >= " << errs << " mismatch(es).\n" << flush; + if (REAL_BYTES < 8) + cerr << "This is not uncommon for low-precision FP; try with 8-byte reals." << endl; + ok = false; + } + } + else + os << "\nRESULTS NOT VERIFIED.\n"; + + kenv->global_barrier(); + if (!ok) + exit_yask(1); + } catch (yask_exception e) { + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + exit_yask(1); } - else - os << "\nRESULTS NOT VERIFIED.\n"; - - kenv->global_barrier(); - if (!ok) - exit_yask(1); - MPI_Finalize(); - os << "YASK DONE." << endl << divLine << flush; + MPI_Finalize(); + cout << "YASK DONE." << endl << divLine << flush; return 0; } From d8fbb36b1b7a1f5a42c6daade56295f948020443 Mon Sep 17 00:00:00 2001 From: Joonmoo Huh Date: Wed, 24 Jan 2018 15:24:18 -0700 Subject: [PATCH 2/7] Add exception handling to API calls that could throw exception potentially. Closes #56. --- include/yask_common_api.hpp | 6 +- include/yask_compiler_api.hpp | 46 +++++++------- include/yask_kernel_api.hpp | 113 +++++++++++++++++---------------- src/common/common_utils.cpp | 2 +- src/common/output.cpp | 6 +- src/compiler/lib/Expr.cpp | 20 +++--- src/compiler/lib/Expr.hpp | 8 +-- src/compiler/lib/Grid.cpp | 2 +- src/compiler/lib/Grid.hpp | 4 +- src/compiler/lib/Soln.cpp | 6 +- src/compiler/lib/Soln.hpp | 12 ++-- src/kernel/lib/context.cpp | 12 ++-- src/kernel/lib/context.hpp | 44 ++++++------- src/kernel/lib/factory.cpp | 4 +- src/kernel/lib/realv_grids.cpp | 22 +++---- src/kernel/lib/realv_grids.hpp | 44 ++++++------- src/kernel/lib/settings.cpp | 2 +- 17 files changed, 177 insertions(+), 176 deletions(-) diff --git a/include/yask_common_api.hpp b/include/yask_common_api.hpp index 96eed5a8..db7d4146 100644 --- a/include/yask_common_api.hpp +++ b/include/yask_common_api.hpp @@ -112,7 +112,7 @@ namespace yask { @returns Pointer to new output object. */ virtual yask_string_output_ptr - new_string_output() const; + new_string_output() const throw(yask_exception); /// Create a stdout output object. /** @@ -120,7 +120,7 @@ namespace yask { @returns Pointer to new output object. */ virtual yask_stdout_output_ptr - new_stdout_output() const; + new_stdout_output() const throw(yask_exception); /// Create a null output object. /** @@ -128,7 +128,7 @@ namespace yask { @returns Pointer to new output object. */ virtual yask_null_output_ptr - new_null_output() const; + new_null_output() const throw(yask_exception); }; /// Base interface for output. diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 52aac47e..c66ed546 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -120,7 +120,7 @@ namespace yask { */ virtual yc_solution_ptr new_solution(const std::string& name /**< [in] Name of the solution; - must be a valid C++ identifier. */ ) const; + must be a valid C++ identifier. */ ) const throw(yask_exception); }; /// Stencil solution. @@ -174,7 +174,7 @@ namespace yask { identifier and unique across grids. */, const std::vector& dims /**< [in] Dimensions of the grid. - Each dimension is identified by an associated index. */ ) =0; + Each dimension is identified by an associated index. */ ) throw(yask_exception) =0; #ifndef SWIG /// Create an n-dimensional grid variable in the solution. @@ -191,7 +191,7 @@ namespace yask { across grids. */, const std::initializer_list& dims /**< [in] Dimensions of the grid. - Each dimension is identified by an associated index. */ ) =0; + Each dimension is identified by an associated index. */ ) throw(yask_exception) =0; #endif /// Get all the grids in the solution. @@ -207,7 +207,7 @@ namespace yask { /// Get the specified grid. /** @returns Pointer to the specified grid or null pointer if it does not exist. */ virtual yc_grid_ptr - get_grid(const std::string& name /**< [in] Name of the grid. */ ) =0; + get_grid(const std::string& name /**< [in] Name of the grid. */ ) throw(yask_exception) =0; /// Get the number of equations in the solution. /** Equations are added when equation_nodes are created via new_equation_node(). @@ -219,7 +219,7 @@ namespace yask { /** @returns Pointer to equation_node of nth equation. */ virtual yc_equation_node_ptr get_equation(int n /**< [in] Index of equation between zero (0) - and get_num_equations()-1. */ ) =0; + and get_num_equations()-1. */ ) throw(yask_exception) =0; /// Set the vectorization length in given dimension. /** For YASK-code generation, the product of the fold lengths should @@ -240,7 +240,7 @@ namespace yask { set_fold_len(const yc_index_node_ptr dim /**< [in] Dimension of fold, e.g., "x". This must be an index created by new_domain_index(). */, - int len /**< [in] Length of vectorization in `dim` */ ) =0; + int len /**< [in] Length of vectorization in `dim` */ ) throw(yask_exception) =0; /// Reset all vector-folding settings. /** All fold lengths will return to the default of one (1). */ @@ -268,7 +268,7 @@ namespace yask { set_cluster_mult(const yc_index_node_ptr dim /**< [in] Direction of unroll, e.g., "y". This must be an index created by new_domain_index(). */, - int mult /**< [in] Number of vectors in `dim` */ ) =0; + int mult /**< [in] Number of vectors in `dim` */ ) throw(yask_exception) =0; /// Reset all vector-clustering settings. /** All cluster multipliers will return to the default of one (1). */ @@ -326,7 +326,7 @@ namespace yask { /** @returns String containing name of dimension created via new_grid(). */ virtual const std::string& get_dim_name(int n /**< [in] Index of dimension between zero (0) - and get_num_dims()-1. */ ) const =0; + and get_num_dims()-1. */ ) const throw(yask_exception) =0; /// Get all the dimensions in this grid. /** @@ -364,7 +364,7 @@ namespace yask { @note This version is not available (or needed) in SWIG-based APIs, e.g., Python. @returns Pointer to AST node used to read or write from point in grid. */ virtual yc_grid_point_node_ptr - new_relative_grid_point(const std::initializer_list& dim_offsets) = 0; + new_relative_grid_point(const std::initializer_list& dim_offsets) throw(yask_exception) = 0; #endif }; @@ -383,7 +383,7 @@ namespace yask { */ virtual yc_index_node_ptr new_step_index(const std::string& name - /**< [in] Step dimension name. */ ); + /**< [in] Step dimension name. */ ) throw(yask_exception); /// Create a domain-index node. /** @@ -395,7 +395,7 @@ namespace yask { */ virtual yc_index_node_ptr new_domain_index(const std::string& name - /**< [in] Domain index name. */ ); + /**< [in] Domain index name. */ ) throw(yask_exception); /// Create a new miscellaneous index. /** @@ -405,7 +405,7 @@ namespace yask { */ virtual yc_index_node_ptr new_misc_index(const std::string& name - /**< [in] Index name. */ ); + /**< [in] Index name. */ ) throw(yask_exception); /// Create an equation node. /** Indicates grid point on LHS is equivalent to expression on @@ -416,19 +416,19 @@ namespace yask { @returns Pointer to new node. */ virtual yc_equation_node_ptr new_equation_node(yc_grid_point_node_ptr lhs /**< [in] Grid-point before EQUALS operator. */, - yc_number_node_ptr rhs /**< [in] Expression after EQUALS operator. */ ); + yc_number_node_ptr rhs /**< [in] Expression after EQUALS operator. */ ) throw(yask_exception); /// Create a constant numerical value node. /** This is unary negation. Use new_subtraction_node() for binary '-'. @returns Pointer to new node. */ virtual yc_const_number_node_ptr - new_const_number_node(double val /**< [in] Value to store in node. */ ); + new_const_number_node(double val /**< [in] Value to store in node. */ ) throw(yask_exception); /// Create a numerical negation operator node. /** @returns Pointer to new node. */ virtual yc_negate_node_ptr - new_negate_node(yc_number_node_ptr rhs /**< [in] Expression after '-' sign. */ ); + new_negate_node(yc_number_node_ptr rhs /**< [in] Expression after '-' sign. */ ) throw(yask_exception); /// Create an addition node. /** Nodes must be created with at least two operands, and more can @@ -436,7 +436,7 @@ namespace yask { @returns Pointer to new node. */ virtual yc_add_node_ptr new_add_node(yc_number_node_ptr lhs /**< [in] Expression before '+' sign. */, - yc_number_node_ptr rhs /**< [in] Expression after '+' sign. */ ); + yc_number_node_ptr rhs /**< [in] Expression after '+' sign. */ ) throw(yask_exception); /// Create a multiplication node. /** Nodes must be created with at least two operands, and more can @@ -444,7 +444,7 @@ namespace yask { @returns Pointer to new node. */ virtual yc_multiply_node_ptr new_multiply_node(yc_number_node_ptr lhs /**< [in] Expression before '*' sign. */, - yc_number_node_ptr rhs /**< [in] Expression after '*' sign. */ ); + yc_number_node_ptr rhs /**< [in] Expression after '*' sign. */ ) throw(yask_exception); /// Create a subtraction node. /** This is binary subtraction. @@ -452,13 +452,13 @@ namespace yask { @returns Pointer to new node. */ virtual yc_subtract_node_ptr new_subtract_node(yc_number_node_ptr lhs /**< [in] Expression before '-' sign. */, - yc_number_node_ptr rhs /**< [in] Expression after '-' sign. */ ); + yc_number_node_ptr rhs /**< [in] Expression after '-' sign. */ ) throw(yask_exception); /// Create a division node. /** @returns Pointer to new node. */ virtual yc_divide_node_ptr new_divide_node(yc_number_node_ptr lhs /**< [in] Expression before '/' sign. */, - yc_number_node_ptr rhs /**< [in] Expression after '/' sign. */ ); + yc_number_node_ptr rhs /**< [in] Expression after '/' sign. */ ) throw(yask_exception); }; /// Base class for all AST nodes. @@ -471,12 +471,12 @@ namespace yask { /** Formats the expression starting at this node. @returns String containing a single-line human-readable version of the expression. */ - virtual std::string format_simple() const =0; + virtual std::string format_simple() const throw(yask_exception) =0; /// Count the size of the AST. /** @returns Number of nodes in this tree, including this node and all its descendants. */ - virtual int get_num_nodes() const =0; + virtual int get_num_nodes() const throw(yask_exception) =0; }; /// Equation node. @@ -570,11 +570,11 @@ namespace yask { /** @returns Pointer to node at given position or null pointer if out of bounds. */ virtual yc_number_node_ptr get_operand(int i /**< [in] Index between zero (0) - and get_num_operands()-1. */ ) =0; + and get_num_operands()-1. */ ) throw(yask_exception) =0; /// Add an operand. virtual void - add_operand(yc_number_node_ptr node /**< [in] Top node of AST to add. */ ) =0; + add_operand(yc_number_node_ptr node /**< [in] Top node of AST to add. */ ) throw(yask_exception) =0; }; /// An addition node. diff --git a/include/yask_kernel_api.hpp b/include/yask_kernel_api.hpp index 2a1b1780..dd35d2f5 100644 --- a/include/yask_kernel_api.hpp +++ b/include/yask_kernel_api.hpp @@ -85,7 +85,7 @@ namespace yask { @returns Pointer to new env object. */ virtual yk_env_ptr - new_env() const; + new_env() const throw(yask_exception); /// Create a stencil solution. /** @@ -94,7 +94,7 @@ namespace yask { @returns Pointer to new solution object. */ virtual yk_solution_ptr - new_solution(yk_env_ptr env /**< [in] Pointer to env info. */) const; + new_solution(yk_env_ptr env /**< [in] Pointer to env info. */) const throw(yask_exception); /// Create a stencil solution by copying the settings from another. /** @@ -108,7 +108,7 @@ namespace yask { new_solution(yk_env_ptr env /**< [in] Pointer to env info. */, const yk_solution_ptr source /**< [in] Pointer to existing \ref yk_solution from which - the settings will be copied. */ ) const; + the settings will be copied. */ ) const throw(yask_exception); }; /// Kernel environment. @@ -221,7 +221,7 @@ namespace yask { set_rank_domain_size(const std::string& dim /**< [in] Name of dimension to set. Must be one of the names from get_domain_dim_names(). */, - idx_t size /**< [in] Elements in the domain in this `dim`. */ ) =0; + idx_t size /**< [in] Elements in the domain in this `dim`. */ ) throw(yask_exception) =0; /// Get the domain size for this rank. /** @@ -230,7 +230,7 @@ namespace yask { virtual idx_t get_rank_domain_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */) const =0; + the names from get_domain_dim_names(). */) const throw(yask_exception) =0; /// Set the minimum amount of grid padding for all grids. /** @@ -261,7 +261,7 @@ namespace yask { be one of the names from get_domain_dim_names(). */, idx_t size /**< [in] Elements in this `dim` applied - to both sides of the domain. */ ) =0; + to both sides of the domain. */ ) throw(yask_exception) =0; /// Get the minimum amount of grid padding for all grids. /** @@ -270,7 +270,7 @@ namespace yask { virtual idx_t get_min_pad_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */) const =0; + the names from get_domain_dim_names(). */) const throw(yask_exception) =0; /// Set the block size in the given dimension. /** @@ -290,7 +290,7 @@ namespace yask { set_block_size(const std::string& dim /**< [in] Name of dimension to set. Must be one of the names from get_domain_dim_names(). */, - idx_t size /**< [in] Elements in a block in this `dim`. */ ) =0; + idx_t size /**< [in] Elements in a block in this `dim`. */ ) throw(yask_exception) =0; /// Get the block size. /** @@ -301,7 +301,7 @@ namespace yask { virtual idx_t get_block_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */) const =0; + the names from get_domain_dim_names(). */) const throw(yask_exception) =0; /// Set performance parameters from an option string. /** @@ -316,7 +316,7 @@ namespace yask { */ virtual std::string apply_command_line_options(const std::string& args - /**< [in] String of arguments to parse. */ ) =0; + /**< [in] String of arguments to parse. */ ) throw(yask_exception) =0; /// Set the number of MPI ranks in the given dimension. /** @@ -335,7 +335,7 @@ namespace yask { set_num_ranks(const std::string& dim /**< [in] Name of dimension to set. Must be one of the names from get_domain_dim_names(). */, - idx_t num /**< [in] Number of ranks in `dim`. */ ) =0; + idx_t num /**< [in] Number of ranks in `dim`. */ ) throw(yask_exception) =0; /// Get the number of MPI ranks in the given dimension. /** @@ -344,7 +344,7 @@ namespace yask { virtual idx_t get_num_ranks(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */) const =0; + the names from get_domain_dim_names(). */) const throw(yask_exception) =0; /// Get the rank index in the specified dimension. /** @@ -355,7 +355,7 @@ namespace yask { virtual idx_t get_rank_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */ ) const =0; + the names from get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Get the number of grids in the solution. /** @@ -372,7 +372,7 @@ namespace yask { @returns Pointer to the specified grid or null pointer if it does not exist. */ virtual yk_grid_ptr - get_grid(const std::string& name /**< [in] Name of the grid. */ ) =0; + get_grid(const std::string& name /**< [in] Name of the grid. */ ) throw(yask_exception) =0; /// Get all the grids. /** @@ -421,7 +421,7 @@ namespace yask { const std::vector& dims /**< [in] List of names of all dimensions. Names must be valid C++ identifiers and - not repeated within this grid. */ ) =0; + not repeated within this grid. */ ) throw(yask_exception) =0; #ifndef SWIG /// **[Advanced]** Add a new grid to the solution. @@ -438,7 +438,7 @@ namespace yask { const std::initializer_list& dims /**< [in] List of names of all dimensions. Names must be valid C++ identifiers and - not repeated within this grid. */ ) =0; + not repeated within this grid. */ ) throw(yask_exception) =0; #endif /// **[Advanced]** Add a new grid to the solution with a specified size. @@ -479,7 +479,7 @@ namespace yask { not repeated within this grid. */, const std::vector& dim_sizes /**< [in] Initial allocation in each dimension. - Must be exatly one size for each dimension. */ ) =0; + Must be exatly one size for each dimension. */ ) throw(yask_exception) =0; #ifndef SWIG /// **[Advanced]** Add a new grid to the solution with a specified size. @@ -499,7 +499,7 @@ namespace yask { not repeated within this grid. */, const std::initializer_list& dim_sizes /**< [in] Initial allocation in each dimension. - Must be exatly one size for each dimension. */ ) =0; + Must be exatly one size for each dimension. */ ) throw(yask_exception) =0; #endif /// Prepare the solution for stencil application. @@ -512,7 +512,7 @@ namespace yask { Must be called before applying any stencils. */ virtual void - prepare_solution() =0; + prepare_solution() throw(yask_exception) =0; /// Get the first index of the sub-domain in this rank in the specified dimension. /** @@ -529,7 +529,7 @@ namespace yask { virtual idx_t get_first_rank_domain_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */ ) const =0; + the names from get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Get the last index of the sub-domain in this rank the specified dimension. /** @@ -547,7 +547,7 @@ namespace yask { virtual idx_t get_last_rank_domain_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */ ) const =0; + the names from get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Get the overall problem size in the specified dimension. /** @@ -562,7 +562,7 @@ namespace yask { virtual idx_t get_overall_domain_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */ ) const =0; + the names from get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Run the stencil solution for the specified steps. /** @@ -632,7 +632,7 @@ namespace yask { If _false_, disable the auto-tuner from running. */, bool verbose = false /**< [in] If _true_, print progress information to the debug object - set via set_debug_output(). */ ) =0; + set via set_debug_output(). */ ) throw(yask_exception) =0; /// Determine whether the auto-tuner is enabled on this rank. /** @@ -675,7 +675,7 @@ namespace yask { */ virtual void share_grid_storage(yk_solution_ptr source - /**< [in] Solution from which grid storage will be shared. */) =0; + /**< [in] Solution from which grid storage will be shared. */) throw(yask_exception) =0; /// Get performance statistics associated with preceding calls to run_solution(). /** @@ -684,7 +684,7 @@ namespace yask { @returns Pointer to statistics object. */ virtual yk_stats_ptr - get_stats() =0; + get_stats() throw(yask_exception) =0; /// Finish using a solution. /** @@ -693,7 +693,7 @@ namespace yask { shared by another shared pointer. */ virtual void - end_solution() =0; + end_solution() throw(yask_exception) =0; }; /// Statistics from calls to run_solution(). @@ -704,6 +704,7 @@ namespace yask { */ class yk_stats { public: + virtual ~yk_stats() {} /// Get the number of elements in the overall domain. /** @@ -892,7 +893,7 @@ namespace yask { virtual idx_t get_rank_domain_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */) const =0; + the names from yk_solution::get_domain_dim_names(). */) const throw(yask_exception) =0; /// Get the first index of the sub-domain in this rank in the specified dimension. /** @@ -902,7 +903,7 @@ namespace yask { virtual idx_t get_first_rank_domain_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Get the last index of the sub-domain in this rank in the specified dimension. /** @@ -913,7 +914,7 @@ namespace yask { virtual idx_t get_last_rank_domain_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Get the halo size in the specified dimension. /** @@ -924,7 +925,7 @@ namespace yask { get_halo_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// **[Advanced]** Set the halo size in the specified dimension. /** @@ -943,7 +944,7 @@ namespace yask { Must be one of the names from yk_solution::get_domain_dim_names(). */, idx_t size - /**< [in] Number of elements in the halo. */ ) =0; + /**< [in] Number of elements in the halo. */ ) throw(yask_exception) =0; /// Get the first index of the halo in this rank in the specified dimension. /** @@ -954,7 +955,7 @@ namespace yask { virtual idx_t get_first_rank_halo_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Get the last index of the halo in this rank in the specified dimension. /** @@ -965,7 +966,7 @@ namespace yask { virtual idx_t get_last_rank_halo_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Get the padding in the specified dimension. /** @@ -983,7 +984,7 @@ namespace yask { get_pad_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Get the extra padding in the specified dimension. /** @@ -996,7 +997,7 @@ namespace yask { get_extra_pad_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Set the padding in the specified dimension. /** @@ -1026,7 +1027,7 @@ namespace yask { Must be one of the names from yk_solution::get_domain_dim_names(). */, idx_t size - /**< [in] Minimum number of elements to allocate beyond the domain size. */ ) =0; + /**< [in] Minimum number of elements to allocate beyond the domain size. */ ) throw(yask_exception) =0; /// Get the storage allocation in the specified dimension. /** @@ -1038,7 +1039,7 @@ namespace yask { */ virtual idx_t get_alloc_size(const std::string& dim - /**< [in] Name of dimension to get. */ ) const =0; + /**< [in] Name of dimension to get. */ ) const throw(yask_exception) =0; /// **[Advanced]** Set the number of elements to allocate in the specified dimension. /** @@ -1056,7 +1057,7 @@ namespace yask { /**< [in] Name of dimension to set. Must *not* be one of the names from yk_solution::get_domain_dim_names(). */, - idx_t size /**< [in] Number of elements to allocate. */ ) =0; + idx_t size /**< [in] Number of elements to allocate. */ ) throw(yask_exception) =0; /// **[Advanced]** Get the first accessible index in this grid in this rank in the specified dimension. /** @@ -1071,7 +1072,7 @@ namespace yask { get_first_rank_alloc_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// **[Advanced]** Get the last accessible index in this grid in this rank in the specified dimension. /** @@ -1086,7 +1087,7 @@ namespace yask { get_last_rank_alloc_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; /// Get the first index of a specified miscellaneous dimension. /** @@ -1095,7 +1096,7 @@ namespace yask { virtual idx_t get_first_misc_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_misc_dim_names(). */ ) const =0; + the names from yk_solution::get_misc_dim_names(). */ ) const throw(yask_exception) =0; /// Set the first index of a specified miscellaneous dimension. /** @@ -1109,7 +1110,7 @@ namespace yask { /**< [in] Name of dimension to get. Must be one of the names from yk_solution::get_misc_dim_names(). */, idx_t idx /**< [in] New value for first index. - May be negative. */ ) =0; + May be negative. */ ) throw(yask_exception) =0; /// Get the last index of a specified miscellaneous dimension. /** @@ -1118,7 +1119,7 @@ namespace yask { virtual idx_t get_last_misc_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_misc_dim_names(). */ ) const =0; + the names from yk_solution::get_misc_dim_names(). */ ) const throw(yask_exception) =0; /// Get the value of one grid element. /** @@ -1127,11 +1128,11 @@ namespace yask { Index values must fall within the allocated space as returned by get_first_rank_alloc_index() and get_last_rank_alloc_index() for each dimension. - @returns value in grid at given multi-dimensional location. + @returns value in grid at given multi-dimensional location. throw(yask_exception) */ virtual double get_element(const std::vector& indices - /**< [in] List of indices, one for each grid dimension. */ ) const =0; + /**< [in] List of indices, one for each grid dimension. */ ) const throw(yask_exception) =0; #ifndef SWIG /// Get the value of one grid element. @@ -1149,7 +1150,7 @@ namespace yask { */ virtual double get_element(const std::initializer_list& indices - /**< [in] List of indices, one for each grid dimension. */ ) const =0; + /**< [in] List of indices, one for each grid dimension. */ ) const throw(yask_exception) =0; #endif /// Get grid elements within specified subset of the grid. @@ -1175,7 +1176,7 @@ namespace yask { const std::vector& first_indices /**< [in] List of initial indices, one for each grid dimension. */, const std::vector& last_indices - /**< [in] List of final indices, one for each grid dimension. */ ) const =0; + /**< [in] List of final indices, one for each grid dimension. */ ) const throw(yask_exception) =0; /// Set the value of one grid element. /** @@ -1197,7 +1198,7 @@ namespace yask { bool strict_indices = false /**< [in] If true, indices must be within domain or padding. If false, indices outside of domain and padding result - in no change to grid. */ ) =0; + in no change to grid. */ ) throw(yask_exception) =0; #ifndef SWIG /// Set the value of one grid element. @@ -1222,7 +1223,7 @@ namespace yask { bool strict_indices = false /**< [in] If true, indices must be within domain or padding. If false, indices outside of domain and padding result - in no change to grid. */ ) =0; + in no change to grid. */ ) throw(yask_exception) =0; #endif /// Initialize all grid elements to the same value. @@ -1236,7 +1237,7 @@ namespace yask { this will have no effect. */ virtual void - set_all_elements_same(double val /**< [in] All elements will be set to this. */ ) =0; + set_all_elements_same(double val /**< [in] All elements will be set to this. */ ) throw(yask_exception) =0; /// Initialize grid elements within specified subset of the grid to the same value. /** @@ -1260,7 +1261,7 @@ namespace yask { bool strict_indices = false /**< [in] If true, indices must be within domain or padding. If false, only elements within the allocation of this grid - will be set, and elements outside will be ignored. */ ) =0; + will be set, and elements outside will be ignored. */ ) throw(yask_exception) =0; /// Set grid elements within specified subset of the grid. /** @@ -1289,7 +1290,7 @@ namespace yask { const std::vector& first_indices /**< [in] List of initial indices, one for each grid dimension. */, const std::vector& last_indices - /**< [in] List of final indices, one for each grid dimension. */ ) =0; + /**< [in] List of final indices, one for each grid dimension. */ ) throw(yask_exception) =0; /// **[Advanced]** Explicitly allocate data-storage memory for this grid. /** @@ -1299,7 +1300,7 @@ namespace yask { See allocation options in the "Detailed Description" for \ref yk_grid. */ virtual void - alloc_storage() =0; + alloc_storage() throw(yask_exception) =0; /// **[Advanced]** Explicitly release any allocated data-storage for this grid. /** @@ -1309,7 +1310,7 @@ namespace yask { be retained by the remaining grids. */ virtual void - release_storage() =0; + release_storage() throw(yask_exception) =0; /// Determine whether storage has been allocated. /** @@ -1351,7 +1352,7 @@ namespace yask { `other` or `false` otherwise. */ virtual bool - is_storage_layout_identical(const yk_grid_ptr other) const =0; + is_storage_layout_identical(const yk_grid_ptr other) const throw(yask_exception) =0; /// **[Advanced]** Use existing data-storage from specified grid. /** @@ -1381,7 +1382,7 @@ namespace yask { */ virtual void share_storage(yk_grid_ptr source - /**< [in] Grid from which storage will be shared. */) =0; + /**< [in] Grid from which storage will be shared. */) throw(yask_exception) =0; /// **[Advanced]** Get pointer to raw data storage buffer. /** diff --git a/src/common/common_utils.cpp b/src/common/common_utils.cpp index 882c46f5..171e6e5c 100644 --- a/src/common/common_utils.cpp +++ b/src/common/common_utils.cpp @@ -41,7 +41,7 @@ namespace yask { // for numbers above 9 (at least up to 99). // Format: "major.minor.patch". - const string version = "2.01.09"; + const string version = "2.01.10"; string yask_get_version_string() { return version; diff --git a/src/common/output.cpp b/src/common/output.cpp index 13ef928c..c83431fe 100644 --- a/src/common/output.cpp +++ b/src/common/output.cpp @@ -125,19 +125,19 @@ namespace yask { return p; } yask_string_output_ptr - yask_output_factory::new_string_output() const { + yask_output_factory::new_string_output() const throw(yask_exception){ auto p = make_shared(); assert(p.get()); return p; } yask_stdout_output_ptr - yask_output_factory::new_stdout_output() const { + yask_output_factory::new_stdout_output() const throw(yask_exception){ auto p = make_shared(); assert(p.get()); return p; } yask_null_output_ptr - yask_output_factory::new_null_output() const { + yask_output_factory::new_null_output() const throw(yask_exception){ auto p = make_shared(); assert(p.get()); return p; diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index 077e325e..430a7ba9 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -42,21 +42,21 @@ namespace yask { //node_factory API methods. yc_index_node_ptr - yc_node_factory::new_step_index(const std::string& name) { + yc_node_factory::new_step_index(const std::string& name) throw(yask_exception) { return make_shared(name, STEP_INDEX); } yc_index_node_ptr - yc_node_factory::new_domain_index(const std::string& name) { + yc_node_factory::new_domain_index(const std::string& name) throw(yask_exception) { return make_shared(name, DOMAIN_INDEX); } yc_index_node_ptr - yc_node_factory::new_misc_index(const std::string& name) { + yc_node_factory::new_misc_index(const std::string& name) throw(yask_exception) { return make_shared(name, MISC_INDEX); } yc_equation_node_ptr yc_node_factory::new_equation_node(yc_grid_point_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_number_node_ptr rhs) throw(yask_exception) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -64,18 +64,18 @@ namespace yask { return operator EQUALS_OPER(lp, rp); } yc_const_number_node_ptr - yc_node_factory::new_const_number_node(double val) { + yc_node_factory::new_const_number_node(double val) throw(yask_exception) { return make_shared(val); } yc_negate_node_ptr - yc_node_factory::new_negate_node(yc_number_node_ptr rhs) { + yc_node_factory::new_negate_node(yc_number_node_ptr rhs) throw(yask_exception) { auto p = dynamic_pointer_cast(rhs); assert(p); return make_shared(p); } yc_add_node_ptr yc_node_factory::new_add_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_number_node_ptr rhs) throw(yask_exception) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -84,7 +84,7 @@ namespace yask { } yc_multiply_node_ptr yc_node_factory::new_multiply_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_number_node_ptr rhs) throw(yask_exception) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -93,7 +93,7 @@ namespace yask { } yc_subtract_node_ptr yc_node_factory::new_subtract_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_number_node_ptr rhs) throw(yask_exception) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -102,7 +102,7 @@ namespace yask { } yc_divide_node_ptr yc_node_factory::new_divide_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_number_node_ptr rhs) throw(yask_exception) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index a87da144..48727e6f 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -124,10 +124,10 @@ namespace yask { } // APIs. - virtual string format_simple() const { + virtual string format_simple() const throw(yask_exception) { return makeStr(); } - virtual int get_num_nodes() const { + virtual int get_num_nodes() const throw(yask_exception) { return getNumNodes(); } }; @@ -631,14 +631,14 @@ namespace yask { virtual int get_num_operands() { return _ops.size(); } - virtual yc_number_node_ptr get_operand(int i) { + virtual yc_number_node_ptr get_operand(int i) throw(yask_exception) { if (i >= 0 && size_t(i) < _ops.size()) return _ops.at(size_t(i)); else return nullptr; } - virtual void add_operand(yc_number_node_ptr node) { + virtual void add_operand(yc_number_node_ptr node) throw(yask_exception) { auto p = dynamic_pointer_cast(node); assert(p); appendOp(p); diff --git a/src/compiler/lib/Grid.cpp b/src/compiler/lib/Grid.cpp index e3314cc5..ebba8a4a 100644 --- a/src/compiler/lib/Grid.cpp +++ b/src/compiler/lib/Grid.cpp @@ -95,7 +95,7 @@ namespace yask { std::string yc_factory::get_version_string() { return yask_get_version_string(); } - yc_solution_ptr yc_factory::new_solution(const std::string& name) const { + yc_solution_ptr yc_factory::new_solution(const std::string& name) const throw(yask_exception) { return make_shared(name); } diff --git a/src/compiler/lib/Grid.hpp b/src/compiler/lib/Grid.hpp index f5b95ebe..3c7e27d5 100644 --- a/src/compiler/lib/Grid.hpp +++ b/src/compiler/lib/Grid.hpp @@ -224,7 +224,7 @@ namespace yask { virtual int get_num_dims() const { return int(_dims.size()); } - virtual const string& get_dim_name(int n) const { + virtual const string& get_dim_name(int n) const throw(yask_exception) { assert(n >= 0); assert(n < get_num_dims()); auto dp = _dims.at(n); @@ -235,7 +235,7 @@ namespace yask { virtual yc_grid_point_node_ptr new_relative_grid_point(std::vector dim_offsets) throw(yask_exception); virtual yc_grid_point_node_ptr - new_relative_grid_point(const std::initializer_list& dim_offsets) { + new_relative_grid_point(const std::initializer_list& dim_offsets) throw(yask_exception) { std::vector dim_ofs_vec(dim_offsets); return new_relative_grid_point(dim_ofs_vec); } diff --git a/src/compiler/lib/Soln.cpp b/src/compiler/lib/Soln.cpp index 6d6b1ef4..5d26f09a 100644 --- a/src/compiler/lib/Soln.cpp +++ b/src/compiler/lib/Soln.cpp @@ -34,7 +34,7 @@ namespace yask { // Stencil-solution APIs. yc_grid_ptr StencilSolution::new_grid(const std::string& name, - const std::vector& dims) { + const std::vector& dims) throw(yask_exception) { // Make new grid and add to solution. // TODO: fix this mem leak--make smart ptr. @@ -54,12 +54,12 @@ namespace yask { // Stencil-solution APIs. void StencilSolution::set_fold_len(const yc_index_node_ptr dim, - int len) { + int len) throw(yask_exception) { auto& fold = _settings._foldOptions; fold.addDimBack(dim->get_name(), len); } void StencilSolution::set_cluster_mult(const yc_index_node_ptr dim, - int mult) { + int mult) throw(yask_exception) { auto& cluster = _settings._clusterOptions; cluster.addDimBack(dim->get_name(), mult); } diff --git a/src/compiler/lib/Soln.hpp b/src/compiler/lib/Soln.hpp index 422cb351..c4a232b7 100644 --- a/src/compiler/lib/Soln.hpp +++ b/src/compiler/lib/Soln.hpp @@ -123,16 +123,16 @@ namespace yask { } virtual yc_grid_ptr new_grid(const std::string& name, - const std::vector& dims); + const std::vector& dims) throw(yask_exception); virtual yc_grid_ptr new_grid(const std::string& name, - const std::initializer_list& dims) { + const std::initializer_list& dims) throw(yask_exception) { std::vector dim_vec(dims); return new_grid(name, dim_vec); } virtual int get_num_grids() const { return int(_grids.size()); } - virtual yc_grid_ptr get_grid(const std::string& name) { + virtual yc_grid_ptr get_grid(const std::string& name) throw(yask_exception) { for (int i = 0; i < get_num_grids(); i++) if (_grids.at(i)->getName() == name) return _grids.at(i); @@ -148,7 +148,7 @@ namespace yask { virtual int get_num_equations() const { return _eqs.getNumEqs(); } - virtual yc_equation_node_ptr get_equation(int n) { + virtual yc_equation_node_ptr get_equation(int n) throw(yask_exception) { assert(n >= 0 && n < get_num_equations()); return _eqs.getEqs().at(n); } @@ -160,9 +160,9 @@ namespace yask { else fold.addDimBack(dim, len); } - virtual void set_fold_len(const yc_index_node_ptr, int len); + virtual void set_fold_len(const yc_index_node_ptr, int len) throw(yask_exception); virtual void clear_folding() { _settings._foldOptions.clear(); } - virtual void set_cluster_mult(const yc_index_node_ptr, int mult); + virtual void set_cluster_mult(const yc_index_node_ptr, int mult) throw(yask_exception); virtual void clear_clustering() { _settings._clusterOptions.clear(); } virtual void set_element_bytes(int nbytes) { _settings._elem_bytes = nbytes; } virtual int get_element_bytes() const { return _settings._elem_bytes; } diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index 894fd214..72d26f99 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -32,7 +32,7 @@ namespace yask { // See yask_kernel_api.hpp. #define GET_SOLN_API(api_name, expr, step_ok, domain_ok, misc_ok) \ - idx_t StencilContext::api_name(const string& dim) const { \ + idx_t StencilContext::api_name(const string& dim) const throw(yask_exception) { \ checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ return expr; \ } @@ -47,7 +47,7 @@ namespace yask { #undef GET_SOLN_API #define SET_SOLN_API(api_name, expr, step_ok, domain_ok, misc_ok) \ - void StencilContext::api_name(const string& dim, idx_t n) { \ + void StencilContext::api_name(const string& dim, idx_t n) throw(yask_exception) { \ checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ expr; \ update_grids(); \ @@ -58,7 +58,7 @@ namespace yask { SET_SOLN_API(set_num_ranks, _opts->_num_ranks[dim] = n, false, true, false) #undef SET_SOLN_API - void StencilContext::share_grid_storage(yk_solution_ptr source) { + void StencilContext::share_grid_storage(yk_solution_ptr source) throw(yask_exception) { auto sp = dynamic_pointer_cast(source); assert(sp); @@ -72,7 +72,7 @@ namespace yask { } } - string StencilContext::apply_command_line_options(const string& args) { + string StencilContext::apply_command_line_options(const string& args) throw(yask_exception) { // Create a parser and add base options to it. CommandLineParser parser; @@ -1746,7 +1746,7 @@ namespace yask { } /// Get statistics associated with preceding calls to run_solution(). - yk_stats_ptr StencilContext::get_stats() { + yk_stats_ptr StencilContext::get_stats() throw(yask_exception) { ostream& os = get_ostr(); // Calc and report perf. @@ -1793,7 +1793,7 @@ namespace yask { } // Dealloc grids, etc. - void StencilContext::end_solution() { + void StencilContext::end_solution() throw(yask_exception) { // Release any MPI data. mpiData.clear(); diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index 6dc44538..0c35cb4c 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -364,10 +364,10 @@ namespace yask { Resets all timers and step counters. @returns Pointer to statistics object. */ - virtual yk_stats_ptr get_stats(); + virtual yk_stats_ptr get_stats() throw(yask_exception); // Dealloc grids, etc. - virtual void end_solution(); + virtual void end_solution() throw(yask_exception); // Set grid sizes and offsets. // This should be called anytime a setting or offset is changed. @@ -540,7 +540,7 @@ namespace yask { return int(gridPtrs.size()); } - virtual yk_grid_ptr get_grid(const std::string& name) { + virtual yk_grid_ptr get_grid(const std::string& name) throw(yask_exception) { auto i = gridMap.find(name); if (i != gridMap.end()) return i->second; @@ -554,12 +554,12 @@ namespace yask { } virtual yk_grid_ptr new_grid(const std::string& name, - const GridDimNames& dims) { + const GridDimNames& dims) throw(yask_exception) { return newGrid(name, dims, NULL); } virtual yk_grid_ptr new_grid(const std::string& name, - const std::initializer_list& dims) { + const std::initializer_list& dims) throw(yask_exception) { GridDimNames dims2(dims); return new_grid(name, dims2); } @@ -572,7 +572,7 @@ namespace yask { virtual yk_grid_ptr new_fixed_size_grid(const std::string& name, const std::initializer_list& dims, - const std::initializer_list& dim_sizes) { + const std::initializer_list& dim_sizes) throw(yask_exception) { GridDimNames dims2(dims); GridDimSizes sizes2(dim_sizes); return new_fixed_size_grid(name, dims2, sizes2); @@ -597,34 +597,34 @@ namespace yask { return dims; } - virtual idx_t get_first_rank_domain_index(const std::string& dim) const; - virtual idx_t get_last_rank_domain_index(const std::string& dim) const; - virtual idx_t get_overall_domain_size(const std::string& dim) const; + virtual idx_t get_first_rank_domain_index(const std::string& dim) const throw(yask_exception); + virtual idx_t get_last_rank_domain_index(const std::string& dim) const throw(yask_exception); + virtual idx_t get_overall_domain_size(const std::string& dim) const throw(yask_exception); virtual void run_solution(idx_t first_step_index, idx_t last_step_index) throw(yask_exception); virtual void run_solution(idx_t step_index) throw(yask_exception) { run_solution(step_index, step_index); } - virtual void share_grid_storage(yk_solution_ptr source); + virtual void share_grid_storage(yk_solution_ptr source) throw(yask_exception); // APIs that access settings. virtual void set_rank_domain_size(const std::string& dim, - idx_t size); + idx_t size) throw(yask_exception); virtual void set_min_pad_size(const std::string& dim, - idx_t size); + idx_t size) throw(yask_exception); virtual void set_block_size(const std::string& dim, - idx_t size); + idx_t size) throw(yask_exception); virtual void set_num_ranks(const std::string& dim, - idx_t size); - virtual idx_t get_rank_domain_size(const std::string& dim) const; - virtual idx_t get_min_pad_size(const std::string& dim) const; - virtual idx_t get_block_size(const std::string& dim) const; - virtual idx_t get_num_ranks(const std::string& dim) const; - virtual idx_t get_rank_index(const std::string& dim) const; - virtual std::string apply_command_line_options(const std::string& args); - - virtual void reset_auto_tuner(bool enable, bool verbose = false) { + idx_t size) throw(yask_exception); + virtual idx_t get_rank_domain_size(const std::string& dim) const throw(yask_exception); + virtual idx_t get_min_pad_size(const std::string& dim) const throw(yask_exception); + virtual idx_t get_block_size(const std::string& dim) const throw(yask_exception); + virtual idx_t get_num_ranks(const std::string& dim) const throw(yask_exception); + virtual idx_t get_rank_index(const std::string& dim) const throw(yask_exception); + virtual std::string apply_command_line_options(const std::string& args) throw(yask_exception); + + virtual void reset_auto_tuner(bool enable, bool verbose = false) throw(yask_exception) { _at.clear(!enable, verbose); } virtual void run_auto_tuner_now(bool verbose = true) throw(yask_exception); diff --git a/src/kernel/lib/factory.cpp b/src/kernel/lib/factory.cpp index e7394ae2..deab67f7 100644 --- a/src/kernel/lib/factory.cpp +++ b/src/kernel/lib/factory.cpp @@ -34,7 +34,7 @@ namespace yask { return yask_get_version_string(); } yk_solution_ptr yk_factory::new_solution(yk_env_ptr env, - const yk_solution_ptr source) const { + const yk_solution_ptr source) const throw(yask_exception) { auto ep = dynamic_pointer_cast(env); assert(ep); auto dp = YASK_STENCIL_CONTEXT::new_dims(); @@ -62,7 +62,7 @@ namespace yask { return sp; } - yk_solution_ptr yk_factory::new_solution(yk_env_ptr env) const { + yk_solution_ptr yk_factory::new_solution(yk_env_ptr env) const throw(yask_exception) { return new_solution(env, nullptr); } diff --git a/src/kernel/lib/realv_grids.cpp b/src/kernel/lib/realv_grids.cpp index b309a174..aba1d76f 100644 --- a/src/kernel/lib/realv_grids.cpp +++ b/src/kernel/lib/realv_grids.cpp @@ -32,12 +32,12 @@ namespace yask { // APIs to get info from vars. #define GET_GRID_API(api_name, expr, step_ok, domain_ok, misc_ok) \ - idx_t YkGridBase::api_name(const string& dim) const { \ + idx_t YkGridBase::api_name(const string& dim) const throw(yask_exception) { \ checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ int posn = get_dim_posn(dim, true, #api_name); \ return expr; \ } \ - idx_t YkGridBase::api_name(int posn) const { \ + idx_t YkGridBase::api_name(int posn) const throw(yask_exception) { \ return expr; \ } GET_GRID_API(get_rank_domain_size, _domains[posn], false, true, false) @@ -61,12 +61,12 @@ namespace yask { // APIs to set vars. #define COMMA , #define SET_GRID_API(api_name, expr, step_ok, domain_ok, misc_ok) \ - void YkGridBase::api_name(const string& dim, idx_t n) { \ + void YkGridBase::api_name(const string& dim, idx_t n) throw(yask_exception) { \ checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ int posn = get_dim_posn(dim, true, #api_name); \ expr; \ } \ - void YkGridBase::api_name(int posn, idx_t n) { \ + void YkGridBase::api_name(int posn, idx_t n) throw(yask_exception) { \ int dim = posn; \ expr; \ } @@ -220,7 +220,7 @@ namespace yask { _dims->checkDimType(dim, fn_name, step_ok, domain_ok, misc_ok); } - bool YkGridBase::is_storage_layout_identical(const yk_grid_ptr other) const { + bool YkGridBase::is_storage_layout_identical(const yk_grid_ptr other) const throw(yask_exception) { auto op = dynamic_pointer_cast(other); assert(op); @@ -249,7 +249,7 @@ namespace yask { return true; } - void YkGridBase::share_storage(yk_grid_ptr source) { + void YkGridBase::share_storage(yk_grid_ptr source) throw(yask_exception) { auto sp = dynamic_pointer_cast(source); assert(sp); @@ -538,7 +538,7 @@ namespace yask { } // API get/set. - double YkGridBase::get_element(const Indices& indices) const { + double YkGridBase::get_element(const Indices& indices) const throw(yask_exception) { if (!is_storage_allocated()) { yask_exception e; stringstream err; @@ -555,7 +555,7 @@ namespace yask { } idx_t YkGridBase::set_element(double val, const Indices& indices, - bool strict_indices) { + bool strict_indices) throw(yask_exception) { idx_t nup = 0; if (get_raw_storage_buffer() && checkIndices(indices, "set_element", strict_indices, false)) { @@ -571,7 +571,7 @@ namespace yask { idx_t YkGridBase::get_elements_in_slice(void* buffer_ptr, const Indices& first_indices, - const Indices& last_indices) const { + const Indices& last_indices) const throw(yask_exception) { if (!is_storage_allocated()) { yask_exception e; stringstream err; @@ -604,7 +604,7 @@ namespace yask { idx_t YkGridBase::set_elements_in_slice_same(double val, const Indices& first_indices, const Indices& last_indices, - bool strict_indices) { + bool strict_indices) throw(yask_exception) { if (!is_storage_allocated()) return 0; @@ -637,7 +637,7 @@ namespace yask { } idx_t YkGridBase::set_elements_in_slice(const void* buffer_ptr, const Indices& first_indices, - const Indices& last_indices) { + const Indices& last_indices) throw(yask_exception) { if (!is_storage_allocated()) return 0; checkIndices(first_indices, "set_elements_in_slice", true, false); diff --git a/src/kernel/lib/realv_grids.hpp b/src/kernel/lib/realv_grids.hpp index 2036a557..432d4db4 100644 --- a/src/kernel/lib/realv_grids.hpp +++ b/src/kernel/lib/realv_grids.hpp @@ -332,11 +332,11 @@ namespace yask { } #define GET_GRID_API(api_name) \ - virtual idx_t api_name(const std::string& dim) const; \ - virtual idx_t api_name(int posn) const; + virtual idx_t api_name(const std::string& dim) const throw(yask_exception); \ + virtual idx_t api_name(int posn) const throw(yask_exception); #define SET_GRID_API(api_name) \ - virtual void api_name(const std::string& dim, idx_t n); \ - virtual void api_name(int posn, idx_t n); + virtual void api_name(const std::string& dim, idx_t n) throw(yask_exception); \ + virtual void api_name(int posn, idx_t n) throw(yask_exception); // Settings that should never be exposed as APIs because // they can break the usage model. @@ -373,70 +373,70 @@ namespace yask { #undef GET_GRID_API #undef SET_GRID_API - virtual void set_all_elements_same(double val) =0; - virtual double get_element(const Indices& indices) const; + virtual void set_all_elements_same(double val) throw(yask_exception) =0; + virtual double get_element(const Indices& indices) const throw(yask_exception); virtual double get_element(const GridIndices& indices) const throw(yask_exception) { const Indices indices2(indices); return get_element(indices2); } - virtual double get_element(const std::initializer_list& indices) const { + virtual double get_element(const std::initializer_list& indices) const throw(yask_exception) { const Indices indices2(indices); return get_element(indices2); } virtual idx_t get_elements_in_slice(void* buffer_ptr, const Indices& first_indices, - const Indices& last_indices) const; + const Indices& last_indices) const throw(yask_exception); virtual idx_t get_elements_in_slice(void* buffer_ptr, const GridIndices& first_indices, - const GridIndices& last_indices) const { + const GridIndices& last_indices) const throw(yask_exception) { const Indices first(first_indices); const Indices last(last_indices); return get_elements_in_slice(buffer_ptr, first, last); } virtual idx_t set_element(double val, const Indices& indices, - bool strict_indices = false); + bool strict_indices = false) throw(yask_exception); virtual idx_t set_element(double val, const GridIndices& indices, - bool strict_indices = false) { + bool strict_indices = false) throw(yask_exception) { const Indices indices2(indices); return set_element(val, indices2, strict_indices); } virtual idx_t set_element(double val, const std::initializer_list& indices, - bool strict_indices = false) { + bool strict_indices = false) throw(yask_exception) { const Indices indices2(indices); return set_element(val, indices2, strict_indices); } virtual idx_t set_elements_in_slice_same(double val, const Indices& first_indices, const Indices& last_indices, - bool strict_indices); + bool strict_indices) throw(yask_exception); virtual idx_t set_elements_in_slice_same(double val, const GridIndices& first_indices, const GridIndices& last_indices, - bool strict_indices) { + bool strict_indices) throw(yask_exception) { const Indices first(first_indices); const Indices last(last_indices); return set_elements_in_slice_same(val, first, last, strict_indices); } virtual idx_t set_elements_in_slice(const void* buffer_ptr, const Indices& first_indices, - const Indices& last_indices); + const Indices& last_indices) throw(yask_exception); virtual idx_t set_elements_in_slice(const void* buffer_ptr, const GridIndices& first_indices, - const GridIndices& last_indices) { + const GridIndices& last_indices) throw(yask_exception) { const Indices first(first_indices); const Indices last(last_indices); return set_elements_in_slice(buffer_ptr, first, last); } - virtual void alloc_storage() { + virtual void alloc_storage() throw(yask_exception) { _ggb->default_alloc(); } - virtual void release_storage() { + virtual void release_storage() throw(yask_exception) { _ggb->release_storage(); } - virtual void share_storage(yk_grid_ptr source); + virtual void share_storage(yk_grid_ptr source) throw(yask_exception); virtual bool is_storage_allocated() const { return _ggb->get_storage() != 0; } @@ -446,7 +446,7 @@ namespace yask { virtual idx_t get_num_storage_elements() const { return _allocs.product(); } - virtual bool is_storage_layout_identical(const yk_grid_ptr other) const; + virtual bool is_storage_layout_identical(const yk_grid_ptr other) const throw(yask_exception); virtual void* get_raw_storage_buffer() { return _ggb->get_storage(); } @@ -492,7 +492,7 @@ namespace yask { } // Init data. - virtual void set_all_elements_same(double seed) { + virtual void set_all_elements_same(double seed) throw(yask_exception) { _data.set_elems_same(seed); set_dirty_all(true); } @@ -639,7 +639,7 @@ namespace yask { } // Init data. - virtual void set_all_elements_same(double seed) { + virtual void set_all_elements_same(double seed) throw(yask_exception) { real_vec_t seedv = seed; // bcast. _data.set_elems_same(seedv); set_dirty_all(true); diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index 52a80cc9..03f8a7c6 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -71,7 +71,7 @@ namespace yask { // APIs. // See yask_kernel_api.hpp. - yk_env_ptr yk_factory::new_env() const { + yk_env_ptr yk_factory::new_env() const throw(yask_exception) { auto ep = make_shared(); assert(ep); ep->initEnv(0, 0); From bdef78e4b2d6aa859da5ba6483c5f437c24dffa1 Mon Sep 17 00:00:00 2001 From: Joonmoo Huh Date: Wed, 24 Jan 2018 16:16:21 -0700 Subject: [PATCH 3/7] Add missing python test files. --- bin/yask_compiler_api_exception_test.py | 130 +++++++++ bin/yask_kernel_api_exception_test.py | 352 ++++++++++++++++++++++++ 2 files changed, 482 insertions(+) create mode 100755 bin/yask_compiler_api_exception_test.py create mode 100755 bin/yask_kernel_api_exception_test.py diff --git a/bin/yask_compiler_api_exception_test.py b/bin/yask_compiler_api_exception_test.py new file mode 100755 index 00000000..1fb1d817 --- /dev/null +++ b/bin/yask_compiler_api_exception_test.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python + +############################################################################## +## YASK: Yet Another Stencil Kernel +## Copyright (c) 2014-2018, Intel Corporation +## +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to +## deal in the Software without restriction, including without limitation the +## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +## sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## * The above copyright notice and this permission notice shall be included in +## all copies or substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +## IN THE SOFTWARE. +############################################################################## + +## Test the YASK stencil compiler API for Python. + +import yask_compiler + +if __name__ == "__main__": + + # Counter for exception test + num_exception = 0; + + # Compiler 'bootstrap' factories. + cfac = yask_compiler.yc_factory() + ofac = yask_compiler.yask_output_factory() + nfac = yask_compiler.yc_node_factory() + + # Create a new stencil solution. + soln = cfac.new_solution("api_py_test") + do = ofac.new_string_output() + soln.set_debug_output(do) + + # Define the problem dimensions. + t = nfac.new_step_index("t"); + x = nfac.new_domain_index("x"); + y = nfac.new_domain_index("y"); + z = nfac.new_domain_index("z"); + + # Create a grid var. + g1 = soln.new_grid("test_grid", [t, x, y, z]) + + # Create an expression for the new value. + # This will average some of the neighboring points around the + # current stencil application point in the current timestep. + n0 = g1.new_relative_grid_point([0, 0, 0, 0]) # center-point at this timestep. + + # Exception test + print("Exception Test: Call 'new_relative_grid_point' with wrong argument.") + try: + n1 = nfac.new_add_node(n0, g1.new_relative_grid_point([0, -1, 0, 0, 1])) # left. + except yask_compiler.yask_exception, e: + print ("YASK throws an exception.") + print e.get_message() + print ("Exception Test: Catch exception correctly.") + num_exception = num_exception + 1 + + n1 = nfac.new_add_node(n0, g1.new_relative_grid_point([0, -1, 0, 0])) # left. + n1 = nfac.new_add_node(n1, g1.new_relative_grid_point([0, 1, 0, 0])) # right. + n1 = nfac.new_add_node(n1, g1.new_relative_grid_point([0, 0, -1, 0])) # above. + n1 = nfac.new_add_node(n1, g1.new_relative_grid_point([0, 0, 1, 0])) # below. + n1 = nfac.new_add_node(n1, g1.new_relative_grid_point([0, 0, 0, -1])) # in front. + n1 = nfac.new_add_node(n1, g1.new_relative_grid_point([0, 0, 0, 1])) # behind. + n2 = nfac.new_divide_node(n1, nfac.new_const_number_node(7)) # div by 7. + + # Create an equation to define the value at the next timestep. + n3 = g1.new_relative_grid_point([1, 0, 0, 0]) # center-point at next timestep. + n4 = nfac.new_equation_node(n3, n2) # equate to expr n2. + print("Equation before formatting: " + n4.format_simple()) + print("Solution '" + soln.get_name() + "' contains " + + str(soln.get_num_grids()) + " grid(s), and " + + str(soln.get_num_equations()) + " equation(s).") + for grid in soln.get_grids() : + print("Grid " + grid.get_name() + + " has the following dim(s): " + + repr(grid.get_dim_names())); + + # Number of bytes in each FP value. + soln.set_element_bytes(4) + + # Exception test + print("Exception Test: Call 'new_file_output' with read-only file name.") + try: + dot_file = ofac.new_file_output("yc-api-test-with-exception-py-readonly") + except yask_compiler.yask_exception, e: + print ("YASK throws an exception.") + print e.get_message() + print ("Exception Test: Catch exception correctly.") + num_exception = num_exception + 1 + + # Generate DOT output. + dot_file = ofac.new_file_output("yc-api-test-with-exception-py.dot") + soln.format("dot", dot_file) + print("DOT-format written to '" + dot_file.get_filename() + "'.") + + # Generate YASK output. + yask_file = ofac.new_file_output("yc-api-test-with-exception-py.hpp") + soln.format("avx", yask_file) + print("YASK-format written to '" + yask_file.get_filename() + "'.") + + # Exception test + try: + soln.format("wrong_format", dot_file) + except yask_compiler.yask_exception, e: + print ("YASK throws an exception.") + print e.get_message() + print ("Exception Test: Catch exception correctly.") + num_exception = num_exception + 1 + + print("Equation after formatting: " + soln.get_equation(0).format_simple()) + + print("Debug output captured:\n" + do.get_string()) + + # Check whether program handles exceptions or not. + if num_exception != 3: + print("There is a problem in exception test.") + exit(1) + else: + print("End of YASK compiler API test.") diff --git a/bin/yask_kernel_api_exception_test.py b/bin/yask_kernel_api_exception_test.py new file mode 100755 index 00000000..0098238f --- /dev/null +++ b/bin/yask_kernel_api_exception_test.py @@ -0,0 +1,352 @@ +#!/usr/bin/env python + +############################################################################## +## YASK: Yet Another Stencil Kernel +## Copyright (c) 2014-2018, Intel Corporation +## +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to +## deal in the Software without restriction, including without limitation the +## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +## sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## * The above copyright notice and this permission notice shall be included in +## all copies or substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +## IN THE SOFTWARE. +############################################################################## + +## Test the YASK stencil kernel API for Python. + +import numpy as np +import ctypes as ct +import argparse +import yask_kernel + +# Read data from grid using NumPy ndarray. +def read_grid(grid, timestep) : + + # Ignore with fixed-sized grids. + if grid.is_fixed_size(): + return + + print("Reading grid '" + grid.get_name() + "' at time " + repr(timestep) + "...") + + # Create indices for YASK and shape for NumPy. + first_indices = [] + last_indices = [] + shape = [] + nelems = 1 + for dname in grid.get_dim_names() : + + if dname == soln.get_step_dim_name() : + + # Read one timestep only. + # So, we don't need to add a time axis in 'shape'. + first_indices += [timestep] + last_indices += [timestep] + + # Domain dim? + elif dname in soln.get_domain_dim_names() : + + # Full domain in this rank. + first_idx = soln.get_first_rank_domain_index(dname) + last_idx = soln.get_last_rank_domain_index(dname) + + # Read one point in the halo, too. + first_idx -= 1 + last_idx += 1 + + first_indices += [first_idx] + last_indices += [last_idx] + shape += [last_idx - first_idx + 1] + nelems *= last_idx - first_idx + 1 + + # Misc dim? + else : + + # Read first index only. + first_indices += [grid.get_first_misc_index(dname)] + last_indices += [grid.get_first_misc_index(dname)] + + # Create a NumPy ndarray to hold the extracted data. + ndarray1 = np.empty(shape, dtype, 'C'); + + print("Reading " + repr(nelems) + " element(s)...") + nread = grid.get_elements_in_slice(ndarray1.data, first_indices, last_indices) + print(ndarray1) + + # Raw access to this grid. + if soln.get_element_bytes() == 4 : + ptype = ct.POINTER(ct.c_float) + else : + ptype = ct.POINTER(ct.c_double) + raw_ptr = grid.get_raw_storage_buffer() + fp_ptr = ct.cast(int(raw_ptr), ptype) + num_elems = grid.get_num_storage_elements() + print("Raw data: " + repr(fp_ptr[0]) + ", ..., " + repr(fp_ptr[num_elems-1])) + #ndarray2 = np.fromiter(fp_ptr, dtype, num_elems); print(ndarray2) + +# Init grid using NumPy ndarray. +def init_grid(grid, timestep) : + print("Initializing grid '" + grid.get_name() + "' at time " + repr(timestep) + "...") + + # Create indices for YASK, shape & point for NumPy. + first_indices = [] + last_indices = [] + shape = [] + point = () + nelems = 1 + for dname in grid.get_dim_names() : + + if dname == soln.get_step_dim_name() : + + # Write one timestep only. + # So, we don't need to add a time axis in 'shape'. + first_indices += [timestep] + last_indices += [timestep] + + # Domain dim? + elif dname in soln.get_domain_dim_names() : + + # Full domain in this rank. + first_idx = soln.get_first_rank_domain_index(dname) + last_idx = soln.get_last_rank_domain_index(dname) + + # Write one point in the halo, too. + first_idx -= 1 + last_idx += 1 + + first_indices += [first_idx] + last_indices += [last_idx] + shape += [last_idx - first_idx + 1] + nelems *= last_idx - first_idx + 1 + + # Since the array covers one layer of points in the halo + # starting at 0,..,0, 1,..,1 is the first point in the + # computable domain. + point += (1,) + + # Misc dim? + else : + + # Write first index only. + first_indices += [grid.get_first_misc_index(dname)] + last_indices += [grid.get_first_misc_index(dname)] + + # Create a NumPy ndarray to hold the data. + ndarray = np.zeros(shape, dtype, 'C'); + + # Set one point to a non-zero value. + ndarray[point] = 21.0; + print(ndarray) + + print("Writing " + repr(nelems) + " element(s)...") + nset = grid.set_elements_in_slice(ndarray.data, first_indices, last_indices) + print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) + +# Main script. +if __name__ == "__main__": + + # Counter for exception test + num_exception = 0; + + # The factories from which all other kernel objects are made. + kfac = yask_kernel.yk_factory() + ofac = yask_kernel.yask_output_factory() + + # Initalize MPI, etc. + env = kfac.new_env() + + # Create solution. + soln = kfac.new_solution(env) + debug_output = ofac.new_string_output() + soln.set_debug_output(debug_output) + name = soln.get_name() + + # NB: At this point, the grids' meta-data exists, but the grids have no + # data allocated. We need to set the size of the domain before + # allocating data. + + # Determine the datatype. + if soln.get_element_bytes() == 4 : + dtype = np.float32 + else : + dtype = np.float64 + + # Init global settings. + soln_dims = soln.get_domain_dim_names() + + for dim_name in soln_dims : + + # Set domain size in each dim. + soln.set_rank_domain_size(dim_name, 128) + + # Ensure some minimal padding on all grids. + soln.set_min_pad_size(dim_name, 1) + + # Set block size to 64 in z dim and 32 in other dims. + # (Not necessarily useful, just as an example.) + if dim_name == "z" : + soln.set_block_size(dim_name, 64) + else : + soln.set_block_size(dim_name, 32) + + # Make a test fixed-size grid. + fgrid_sizes = () + for dim_name in soln_dims : + fgrid_sizes += (5,) + fgrid = soln.new_fixed_size_grid("fgrid", soln_dims, fgrid_sizes) + + # Simple rank configuration in 1st dim only. + # In production runs, the ranks would be distributed along + # all domain dimensions. + ddim1 = soln_dims[0] # name of 1st dim. + soln.set_num_ranks(ddim1, env.get_num_ranks()) # num ranks in this dim. + + # Exception test + print("Exception Test: Call 'run_solution' without calling prepare_solution().") + try: + soln.run_solution(0) + except yask_kernel.yask_exception, e: + print ("YASK throws an exception.") + print e.get_message() + print ("Exception Test: Catch exception correctly.") + num_exception = num_exception + 1 + + # Exception test + print("Exception Test: Call 'run_auto-tuner_now' without calling prepare_solution().") + try: + soln.run_auto_tuner_now(False) + except yask_kernel.yask_exception, e: + print ("YASK throws an exception.") + print e.get_message() + print ("Exception Test: Catch exception correctly.") + num_exception = num_exception + 1 + + # Allocate memory for any grids that do not have storage set. + # Set other data structures needed for stencil application. + soln.prepare_solution() + + # Print some info about the solution. + print("Stencil-solution '" + name + "':") + print(" Step dimension: " + repr(soln.get_step_dim_name())) + print(" Domain dimensions: " + repr(soln.get_domain_dim_names())) + print(" Grids:") + for grid in soln.get_grids() : + print(" " + grid.get_name() + repr(grid.get_dim_names())) + for dname in grid.get_dim_names() : + if dname in soln.get_domain_dim_names() : + print(" '" + dname + "' allowed index range in this rank: " + + repr(grid.get_first_rank_alloc_index(dname)) + " ... " + + repr(grid.get_last_rank_alloc_index(dname))) + elif dname in soln.get_misc_dim_names() : + print(" '" + dname + "' allowed index range: " + + repr(grid.get_first_misc_index(dname)) + " ... " + + repr(grid.get_last_misc_index(dname))) + + # Init the grids. + for grid in soln.get_grids() : + + # Init all values including padding. + grid.set_all_elements_same(-9.0) + + # Done with fixed-sized grids. + if grid.is_fixed_size(): + continue + + # Init timestep 0 using NumPy. + # This will set one point in each rank. + init_grid(grid, 0) + read_grid(grid, 0) + + # Simple one-index example. + # Note that index relative to overall problem domain, + # so it will only appear in one rank. + one_index = 100 + one_indices = [] + + # Create indices to bound a subset of domain: + # Index 0 in time, and a small cube in center + # of overall problem. + # Note that indices are relative to overall problem domain, + # so the cube may be in one rank or it may be spread over + # more than one. + cube_radius = 20 + first_indices = [] + last_indices = [] + + for dname in grid.get_dim_names() : + + # Step dim? + if dname == soln.get_step_dim_name() : + + # Add index for timestep zero (0) only. + one_indices += [0] + first_indices += [0] + last_indices += [0] + + # Domain dim? + elif dname in soln.get_domain_dim_names() : + + # Simple index for one point. + one_indices += [one_index] + + # Midpoint of overall problem in this dim. + midpt = soln.get_overall_domain_size(dname) // 2; + + # Create indices a small amount before and after the midpoint. + first_indices += [midpt - cube_radius] + last_indices += [midpt + cube_radius] + + # Misc dim? + else : + + # Add indices to set all allowed values. + # (This isn't really meaningful; it's just illustrative.) + one_indices += [grid.get_first_misc_index(dname)] + first_indices += [grid.get_first_misc_index(dname)] + last_indices += [grid.get_last_misc_index(dname)] + + # Init value at one point. + nset = grid.set_element(15.0, one_indices) + print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) + + # Init the values within the small cube. + nset = grid.set_elements_in_slice_same(0.5, first_indices, last_indices) + print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) + + # Print the initial contents of the grid at timesteps 0 and 1. + read_grid(grid, 0) + read_grid(grid, 1) + + # Apply the stencil solution to the data. + env.global_barrier() + print("Running the solution for 1 step...") + soln.run_solution(0) + + # Print result at timestep 1. + for grid in soln.get_grids() : + read_grid(grid, 1) + + print("Running the solution for 10 more steps...") + soln.run_solution(1, 10) + + # Print final result at timestep 11. + for grid in soln.get_grids() : + read_grid(grid, 11) + + print("Debug output captured:\n" + debug_output.get_string()) + + if num_exception != 2: + print("There is a problem in exception test.") + exit(1) + else: + print("End of YASK kernel API test.") From 25ec89098293009493be2f56685cdc99f45676ef Mon Sep 17 00:00:00 2001 From: Joonmoo Huh Date: Thu, 25 Jan 2018 10:47:13 -0700 Subject: [PATCH 4/7] Update python test files to compatible with python3 --- bin/yask_compiler_api_exception_test.py | 12 ++++++------ bin/yask_kernel_api_exception_test.py | 8 ++++---- src/compiler/Makefile | 2 +- src/kernel/Makefile | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bin/yask_compiler_api_exception_test.py b/bin/yask_compiler_api_exception_test.py index 1fb1d817..b14fa0de 100755 --- a/bin/yask_compiler_api_exception_test.py +++ b/bin/yask_compiler_api_exception_test.py @@ -60,9 +60,9 @@ print("Exception Test: Call 'new_relative_grid_point' with wrong argument.") try: n1 = nfac.new_add_node(n0, g1.new_relative_grid_point([0, -1, 0, 0, 1])) # left. - except yask_compiler.yask_exception, e: + except yask_compiler.yask_exception as e: print ("YASK throws an exception.") - print e.get_message() + print (e.get_message()) print ("Exception Test: Catch exception correctly.") num_exception = num_exception + 1 @@ -93,9 +93,9 @@ print("Exception Test: Call 'new_file_output' with read-only file name.") try: dot_file = ofac.new_file_output("yc-api-test-with-exception-py-readonly") - except yask_compiler.yask_exception, e: + except yask_compiler.yask_exception as e: print ("YASK throws an exception.") - print e.get_message() + print (e.get_message()) print ("Exception Test: Catch exception correctly.") num_exception = num_exception + 1 @@ -112,9 +112,9 @@ # Exception test try: soln.format("wrong_format", dot_file) - except yask_compiler.yask_exception, e: + except yask_compiler.yask_exception as e: print ("YASK throws an exception.") - print e.get_message() + print (e.get_message()) print ("Exception Test: Catch exception correctly.") num_exception = num_exception + 1 diff --git a/bin/yask_kernel_api_exception_test.py b/bin/yask_kernel_api_exception_test.py index 0098238f..c29dfb3b 100755 --- a/bin/yask_kernel_api_exception_test.py +++ b/bin/yask_kernel_api_exception_test.py @@ -215,9 +215,9 @@ def init_grid(grid, timestep) : print("Exception Test: Call 'run_solution' without calling prepare_solution().") try: soln.run_solution(0) - except yask_kernel.yask_exception, e: + except yask_kernel.yask_exception as e: print ("YASK throws an exception.") - print e.get_message() + print (e.get_message()) print ("Exception Test: Catch exception correctly.") num_exception = num_exception + 1 @@ -225,9 +225,9 @@ def init_grid(grid, timestep) : print("Exception Test: Call 'run_auto-tuner_now' without calling prepare_solution().") try: soln.run_auto_tuner_now(False) - except yask_kernel.yask_exception, e: + except yask_kernel.yask_exception as e: print ("YASK throws an exception.") - print e.get_message() + print (e.get_message()) print ("Exception Test: Catch exception correctly.") num_exception = num_exception + 1 diff --git a/src/compiler/Makefile b/src/compiler/Makefile index cfcfa973..85d75d59 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -93,7 +93,7 @@ SWIG := swig # NB: constructing string inside print() to work for python 2 or 3. PYINC := $(addprefix -I,$(shell $(PYTHON) -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc() + " " + distutils.sysconfig.get_python_inc(plat_specific=1))')) -RUN_PYTHON := env PYTHONPATH=$(LIB_DIR):$(YASK_DIR) $(PYTHON) +RUN_PYTHON := env PYTHONPATH=$(LIB_DIR):$(YASK_DIR):$(PYTHONPATH) $(PYTHON) ######## Primary targets & rules diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 3e9ecbce..e07d7242 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -432,7 +432,7 @@ PERL := perl # NB: constructing string inside print() to work for python 2 or 3. PYINC := $(addprefix -I,$(shell $(PYTHON) -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc() + " " + distutils.sysconfig.get_python_inc(plat_specific=1))')) -RUN_PYTHON := $(RUN_PREFIX) env PYTHONPATH=$(LIB_DIR):$(YASK_DIR) $(PYTHON) +RUN_PYTHON := $(RUN_PREFIX) env PYTHONPATH=$(LIB_DIR):$(YASK_DIR):$(PYTHONPATH) $(PYTHON) # Set MACROS based on individual makefile vars. # MACROS and EXTRA_MACROS will be written to a header file. From d37082a3bdeff017a4396f2680e8c0c9aa45e705 Mon Sep 17 00:00:00 2001 From: Joonmoo Huh Date: Tue, 30 Jan 2018 10:44:59 -0700 Subject: [PATCH 5/7] Update exception handling to API calls in better way. --- bin/yask_compiler_api_exception_test.py | 14 +- bin/yask_kernel_api_exception_test.py | 14 +- include/yask_common_api.hpp | 19 ++- include/yask_compiler_api.hpp | 50 +++--- include/yask_kernel_api.hpp | 118 +++++++------- src/common/common_utils.cpp | 8 +- src/common/output.cpp | 17 +-- src/compiler/Makefile | 4 +- src/compiler/lib/Eqs.cpp | 63 ++------ src/compiler/lib/Expr.cpp | 29 ++-- src/compiler/lib/Expr.hpp | 44 ++---- src/compiler/lib/Grid.cpp | 61 ++------ src/compiler/lib/Grid.hpp | 6 +- src/compiler/lib/Parse.hpp | 7 +- src/compiler/lib/Soln.cpp | 17 +-- src/compiler/lib/Soln.hpp | 14 +- src/compiler/lib/YaskKernel.cpp | 9 +- src/compiler/swig/yask_compiler_api.i | 11 +- .../yask_compiler_api_exception_test.cpp | 38 ++--- src/kernel/Makefile | 4 +- src/kernel/lib/context.cpp | 110 +++---------- src/kernel/lib/context.hpp | 54 +++---- src/kernel/lib/factory.cpp | 4 +- src/kernel/lib/new_grid.cpp | 36 +---- src/kernel/lib/realv_grids.cpp | 144 +++++------------- src/kernel/lib/realv_grids.hpp | 50 +++--- src/kernel/lib/settings.cpp | 29 +--- src/kernel/lib/utils.cpp | 30 +--- src/kernel/swig/yask_kernel_api.i | 11 +- .../tests/yask_kernel_api_exception_test.cpp | 26 ++-- 30 files changed, 381 insertions(+), 660 deletions(-) diff --git a/bin/yask_compiler_api_exception_test.py b/bin/yask_compiler_api_exception_test.py index b14fa0de..de604289 100755 --- a/bin/yask_compiler_api_exception_test.py +++ b/bin/yask_compiler_api_exception_test.py @@ -60,9 +60,9 @@ print("Exception Test: Call 'new_relative_grid_point' with wrong argument.") try: n1 = nfac.new_add_node(n0, g1.new_relative_grid_point([0, -1, 0, 0, 1])) # left. - except yask_compiler.yask_exception as e: + except RuntimeError as e: print ("YASK throws an exception.") - print (e.get_message()) + print (format(e)) print ("Exception Test: Catch exception correctly.") num_exception = num_exception + 1 @@ -93,9 +93,9 @@ print("Exception Test: Call 'new_file_output' with read-only file name.") try: dot_file = ofac.new_file_output("yc-api-test-with-exception-py-readonly") - except yask_compiler.yask_exception as e: + except RuntimeError as e: print ("YASK throws an exception.") - print (e.get_message()) + print (format(e)) print ("Exception Test: Catch exception correctly.") num_exception = num_exception + 1 @@ -112,9 +112,9 @@ # Exception test try: soln.format("wrong_format", dot_file) - except yask_compiler.yask_exception as e: + except RuntimeError as e: print ("YASK throws an exception.") - print (e.get_message()) + print (format(e)) print ("Exception Test: Catch exception correctly.") num_exception = num_exception + 1 @@ -127,4 +127,4 @@ print("There is a problem in exception test.") exit(1) else: - print("End of YASK compiler API test.") + print("End of YASK compiler API test with exception.") diff --git a/bin/yask_kernel_api_exception_test.py b/bin/yask_kernel_api_exception_test.py index c29dfb3b..ac97aa69 100755 --- a/bin/yask_kernel_api_exception_test.py +++ b/bin/yask_kernel_api_exception_test.py @@ -215,21 +215,21 @@ def init_grid(grid, timestep) : print("Exception Test: Call 'run_solution' without calling prepare_solution().") try: soln.run_solution(0) - except yask_kernel.yask_exception as e: + except RuntimeError as e: print ("YASK throws an exception.") - print (e.get_message()) + print (format(e)) print ("Exception Test: Catch exception correctly.") - num_exception = num_exception + 1 + num_exception = num_exception + 1 # Exception test print("Exception Test: Call 'run_auto-tuner_now' without calling prepare_solution().") try: soln.run_auto_tuner_now(False) - except yask_kernel.yask_exception as e: + except RuntimeError as e: print ("YASK throws an exception.") - print (e.get_message()) + print (format(e)) print ("Exception Test: Catch exception correctly.") - num_exception = num_exception + 1 + num_exception = num_exception + 1 # Allocate memory for any grids that do not have storage set. # Set other data structures needed for stencil application. @@ -349,4 +349,4 @@ def init_grid(grid, timestep) : print("There is a problem in exception test.") exit(1) else: - print("End of YASK kernel API test.") + print("End of YASK kernel API test with exception.") diff --git a/include/yask_common_api.hpp b/include/yask_common_api.hpp index db7d4146..c4ca0b2a 100644 --- a/include/yask_common_api.hpp +++ b/include/yask_common_api.hpp @@ -87,9 +87,17 @@ namespace yask { /// Get additional message. /** @returns additional message as string */ - std::string get_message(); + const char* get_message(); }; + /// MACRO for throw yask_exception +#define THROW_YASK_EXCEPTION(message) \ + yask_exception e; \ + stringstream err; \ + err << message; \ + e.add_message(err.str()); \ + throw e; \ + /// Factory to create output objects. class yask_output_factory { public: @@ -104,7 +112,7 @@ namespace yask { virtual yask_file_output_ptr new_file_output(const std::string& file_name /**< [in] Name of file to open. - Any existing file will be truncated. */ ) const throw(yask_exception); + Any existing file will be truncated. */ ) const; /// Create a string output object. /** @@ -112,7 +120,7 @@ namespace yask { @returns Pointer to new output object. */ virtual yask_string_output_ptr - new_string_output() const throw(yask_exception); + new_string_output() const; /// Create a stdout output object. /** @@ -120,7 +128,7 @@ namespace yask { @returns Pointer to new output object. */ virtual yask_stdout_output_ptr - new_stdout_output() const throw(yask_exception); + new_stdout_output() const; /// Create a null output object. /** @@ -128,7 +136,7 @@ namespace yask { @returns Pointer to new output object. */ virtual yask_null_output_ptr - new_null_output() const throw(yask_exception); + new_null_output() const; }; /// Base interface for output. @@ -180,7 +188,6 @@ namespace yask { public: virtual ~yask_null_output() {} }; - } // namespace yask. diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index c66ed546..0108e3fa 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -120,7 +120,7 @@ namespace yask { */ virtual yc_solution_ptr new_solution(const std::string& name /**< [in] Name of the solution; - must be a valid C++ identifier. */ ) const throw(yask_exception); + must be a valid C++ identifier. */ ) const; }; /// Stencil solution. @@ -174,7 +174,7 @@ namespace yask { identifier and unique across grids. */, const std::vector& dims /**< [in] Dimensions of the grid. - Each dimension is identified by an associated index. */ ) throw(yask_exception) =0; + Each dimension is identified by an associated index. */ ) =0; #ifndef SWIG /// Create an n-dimensional grid variable in the solution. @@ -191,7 +191,7 @@ namespace yask { across grids. */, const std::initializer_list& dims /**< [in] Dimensions of the grid. - Each dimension is identified by an associated index. */ ) throw(yask_exception) =0; + Each dimension is identified by an associated index. */ ) =0; #endif /// Get all the grids in the solution. @@ -207,7 +207,7 @@ namespace yask { /// Get the specified grid. /** @returns Pointer to the specified grid or null pointer if it does not exist. */ virtual yc_grid_ptr - get_grid(const std::string& name /**< [in] Name of the grid. */ ) throw(yask_exception) =0; + get_grid(const std::string& name /**< [in] Name of the grid. */ ) =0; /// Get the number of equations in the solution. /** Equations are added when equation_nodes are created via new_equation_node(). @@ -219,7 +219,7 @@ namespace yask { /** @returns Pointer to equation_node of nth equation. */ virtual yc_equation_node_ptr get_equation(int n /**< [in] Index of equation between zero (0) - and get_num_equations()-1. */ ) throw(yask_exception) =0; + and get_num_equations()-1. */ ) =0; /// Set the vectorization length in given dimension. /** For YASK-code generation, the product of the fold lengths should @@ -240,7 +240,7 @@ namespace yask { set_fold_len(const yc_index_node_ptr dim /**< [in] Dimension of fold, e.g., "x". This must be an index created by new_domain_index(). */, - int len /**< [in] Length of vectorization in `dim` */ ) throw(yask_exception) =0; + int len /**< [in] Length of vectorization in `dim` */ ) =0; /// Reset all vector-folding settings. /** All fold lengths will return to the default of one (1). */ @@ -268,7 +268,7 @@ namespace yask { set_cluster_mult(const yc_index_node_ptr dim /**< [in] Direction of unroll, e.g., "y". This must be an index created by new_domain_index(). */, - int mult /**< [in] Number of vectors in `dim` */ ) throw(yask_exception) =0; + int mult /**< [in] Number of vectors in `dim` */ ) =0; /// Reset all vector-clustering settings. /** All cluster multipliers will return to the default of one (1). */ @@ -300,7 +300,7 @@ namespace yask { /**< [in] Name of type from above table. */, yask_output_ptr output /**< [out] Pointer to object to receive formatted output. - See \ref yask_output_factory. */) throw(yask_exception) =0; + See \ref yask_output_factory. */) =0; }; /// A compile-time grid. @@ -326,7 +326,7 @@ namespace yask { /** @returns String containing name of dimension created via new_grid(). */ virtual const std::string& get_dim_name(int n /**< [in] Index of dimension between zero (0) - and get_num_dims()-1. */ ) const throw(yask_exception) =0; + and get_num_dims()-1. */ ) const =0; /// Get all the dimensions in this grid. /** @@ -350,7 +350,7 @@ namespace yask { @returns Pointer to AST node used to read from or write to point in grid. */ virtual yc_grid_point_node_ptr new_relative_grid_point(std::vector dim_offsets - /**< [in] offset from evaluation index in each dim. */ ) throw(yask_exception) =0; + /**< [in] offset from evaluation index in each dim. */ ) =0; #ifndef SWIG /// Create a reference to a point in a grid. @@ -364,7 +364,7 @@ namespace yask { @note This version is not available (or needed) in SWIG-based APIs, e.g., Python. @returns Pointer to AST node used to read or write from point in grid. */ virtual yc_grid_point_node_ptr - new_relative_grid_point(const std::initializer_list& dim_offsets) throw(yask_exception) = 0; + new_relative_grid_point(const std::initializer_list& dim_offsets) = 0; #endif }; @@ -383,7 +383,7 @@ namespace yask { */ virtual yc_index_node_ptr new_step_index(const std::string& name - /**< [in] Step dimension name. */ ) throw(yask_exception); + /**< [in] Step dimension name. */ ); /// Create a domain-index node. /** @@ -395,7 +395,7 @@ namespace yask { */ virtual yc_index_node_ptr new_domain_index(const std::string& name - /**< [in] Domain index name. */ ) throw(yask_exception); + /**< [in] Domain index name. */ ); /// Create a new miscellaneous index. /** @@ -405,7 +405,7 @@ namespace yask { */ virtual yc_index_node_ptr new_misc_index(const std::string& name - /**< [in] Index name. */ ) throw(yask_exception); + /**< [in] Index name. */ ); /// Create an equation node. /** Indicates grid point on LHS is equivalent to expression on @@ -416,19 +416,19 @@ namespace yask { @returns Pointer to new node. */ virtual yc_equation_node_ptr new_equation_node(yc_grid_point_node_ptr lhs /**< [in] Grid-point before EQUALS operator. */, - yc_number_node_ptr rhs /**< [in] Expression after EQUALS operator. */ ) throw(yask_exception); + yc_number_node_ptr rhs /**< [in] Expression after EQUALS operator. */ ); /// Create a constant numerical value node. /** This is unary negation. Use new_subtraction_node() for binary '-'. @returns Pointer to new node. */ virtual yc_const_number_node_ptr - new_const_number_node(double val /**< [in] Value to store in node. */ ) throw(yask_exception); + new_const_number_node(double val /**< [in] Value to store in node. */ ); /// Create a numerical negation operator node. /** @returns Pointer to new node. */ virtual yc_negate_node_ptr - new_negate_node(yc_number_node_ptr rhs /**< [in] Expression after '-' sign. */ ) throw(yask_exception); + new_negate_node(yc_number_node_ptr rhs /**< [in] Expression after '-' sign. */ ); /// Create an addition node. /** Nodes must be created with at least two operands, and more can @@ -436,7 +436,7 @@ namespace yask { @returns Pointer to new node. */ virtual yc_add_node_ptr new_add_node(yc_number_node_ptr lhs /**< [in] Expression before '+' sign. */, - yc_number_node_ptr rhs /**< [in] Expression after '+' sign. */ ) throw(yask_exception); + yc_number_node_ptr rhs /**< [in] Expression after '+' sign. */ ); /// Create a multiplication node. /** Nodes must be created with at least two operands, and more can @@ -444,7 +444,7 @@ namespace yask { @returns Pointer to new node. */ virtual yc_multiply_node_ptr new_multiply_node(yc_number_node_ptr lhs /**< [in] Expression before '*' sign. */, - yc_number_node_ptr rhs /**< [in] Expression after '*' sign. */ ) throw(yask_exception); + yc_number_node_ptr rhs /**< [in] Expression after '*' sign. */ ); /// Create a subtraction node. /** This is binary subtraction. @@ -452,13 +452,13 @@ namespace yask { @returns Pointer to new node. */ virtual yc_subtract_node_ptr new_subtract_node(yc_number_node_ptr lhs /**< [in] Expression before '-' sign. */, - yc_number_node_ptr rhs /**< [in] Expression after '-' sign. */ ) throw(yask_exception); + yc_number_node_ptr rhs /**< [in] Expression after '-' sign. */ ); /// Create a division node. /** @returns Pointer to new node. */ virtual yc_divide_node_ptr new_divide_node(yc_number_node_ptr lhs /**< [in] Expression before '/' sign. */, - yc_number_node_ptr rhs /**< [in] Expression after '/' sign. */ ) throw(yask_exception); + yc_number_node_ptr rhs /**< [in] Expression after '/' sign. */ ); }; /// Base class for all AST nodes. @@ -471,12 +471,12 @@ namespace yask { /** Formats the expression starting at this node. @returns String containing a single-line human-readable version of the expression. */ - virtual std::string format_simple() const throw(yask_exception) =0; + virtual std::string format_simple() const =0; /// Count the size of the AST. /** @returns Number of nodes in this tree, including this node and all its descendants. */ - virtual int get_num_nodes() const throw(yask_exception) =0; + virtual int get_num_nodes() const =0; }; /// Equation node. @@ -570,11 +570,11 @@ namespace yask { /** @returns Pointer to node at given position or null pointer if out of bounds. */ virtual yc_number_node_ptr get_operand(int i /**< [in] Index between zero (0) - and get_num_operands()-1. */ ) throw(yask_exception) =0; + and get_num_operands()-1. */ ) =0; /// Add an operand. virtual void - add_operand(yc_number_node_ptr node /**< [in] Top node of AST to add. */ ) throw(yask_exception) =0; + add_operand(yc_number_node_ptr node /**< [in] Top node of AST to add. */ ) =0; }; /// An addition node. diff --git a/include/yask_kernel_api.hpp b/include/yask_kernel_api.hpp index dd35d2f5..08e3552c 100644 --- a/include/yask_kernel_api.hpp +++ b/include/yask_kernel_api.hpp @@ -85,7 +85,7 @@ namespace yask { @returns Pointer to new env object. */ virtual yk_env_ptr - new_env() const throw(yask_exception); + new_env() const; /// Create a stencil solution. /** @@ -94,7 +94,7 @@ namespace yask { @returns Pointer to new solution object. */ virtual yk_solution_ptr - new_solution(yk_env_ptr env /**< [in] Pointer to env info. */) const throw(yask_exception); + new_solution(yk_env_ptr env /**< [in] Pointer to env info. */) const; /// Create a stencil solution by copying the settings from another. /** @@ -108,7 +108,7 @@ namespace yask { new_solution(yk_env_ptr env /**< [in] Pointer to env info. */, const yk_solution_ptr source /**< [in] Pointer to existing \ref yk_solution from which - the settings will be copied. */ ) const throw(yask_exception); + the settings will be copied. */ ) const; }; /// Kernel environment. @@ -221,7 +221,7 @@ namespace yask { set_rank_domain_size(const std::string& dim /**< [in] Name of dimension to set. Must be one of the names from get_domain_dim_names(). */, - idx_t size /**< [in] Elements in the domain in this `dim`. */ ) throw(yask_exception) =0; + idx_t size /**< [in] Elements in the domain in this `dim`. */ ) =0; /// Get the domain size for this rank. /** @@ -230,7 +230,7 @@ namespace yask { virtual idx_t get_rank_domain_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */) const throw(yask_exception) =0; + the names from get_domain_dim_names(). */) const =0; /// Set the minimum amount of grid padding for all grids. /** @@ -261,7 +261,7 @@ namespace yask { be one of the names from get_domain_dim_names(). */, idx_t size /**< [in] Elements in this `dim` applied - to both sides of the domain. */ ) throw(yask_exception) =0; + to both sides of the domain. */ ) =0; /// Get the minimum amount of grid padding for all grids. /** @@ -270,7 +270,7 @@ namespace yask { virtual idx_t get_min_pad_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */) const throw(yask_exception) =0; + the names from get_domain_dim_names(). */) const =0; /// Set the block size in the given dimension. /** @@ -290,7 +290,7 @@ namespace yask { set_block_size(const std::string& dim /**< [in] Name of dimension to set. Must be one of the names from get_domain_dim_names(). */, - idx_t size /**< [in] Elements in a block in this `dim`. */ ) throw(yask_exception) =0; + idx_t size /**< [in] Elements in a block in this `dim`. */ ) =0; /// Get the block size. /** @@ -301,7 +301,7 @@ namespace yask { virtual idx_t get_block_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */) const throw(yask_exception) =0; + the names from get_domain_dim_names(). */) const =0; /// Set performance parameters from an option string. /** @@ -316,7 +316,7 @@ namespace yask { */ virtual std::string apply_command_line_options(const std::string& args - /**< [in] String of arguments to parse. */ ) throw(yask_exception) =0; + /**< [in] String of arguments to parse. */ ) =0; /// Set the number of MPI ranks in the given dimension. /** @@ -335,7 +335,7 @@ namespace yask { set_num_ranks(const std::string& dim /**< [in] Name of dimension to set. Must be one of the names from get_domain_dim_names(). */, - idx_t num /**< [in] Number of ranks in `dim`. */ ) throw(yask_exception) =0; + idx_t num /**< [in] Number of ranks in `dim`. */ ) =0; /// Get the number of MPI ranks in the given dimension. /** @@ -344,7 +344,7 @@ namespace yask { virtual idx_t get_num_ranks(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */) const throw(yask_exception) =0; + the names from get_domain_dim_names(). */) const =0; /// Get the rank index in the specified dimension. /** @@ -355,7 +355,7 @@ namespace yask { virtual idx_t get_rank_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from get_domain_dim_names(). */ ) const =0; /// Get the number of grids in the solution. /** @@ -372,7 +372,7 @@ namespace yask { @returns Pointer to the specified grid or null pointer if it does not exist. */ virtual yk_grid_ptr - get_grid(const std::string& name /**< [in] Name of the grid. */ ) throw(yask_exception) =0; + get_grid(const std::string& name /**< [in] Name of the grid. */ ) =0; /// Get all the grids. /** @@ -421,7 +421,7 @@ namespace yask { const std::vector& dims /**< [in] List of names of all dimensions. Names must be valid C++ identifiers and - not repeated within this grid. */ ) throw(yask_exception) =0; + not repeated within this grid. */ ) =0; #ifndef SWIG /// **[Advanced]** Add a new grid to the solution. @@ -438,7 +438,7 @@ namespace yask { const std::initializer_list& dims /**< [in] List of names of all dimensions. Names must be valid C++ identifiers and - not repeated within this grid. */ ) throw(yask_exception) =0; + not repeated within this grid. */ ) =0; #endif /// **[Advanced]** Add a new grid to the solution with a specified size. @@ -479,7 +479,7 @@ namespace yask { not repeated within this grid. */, const std::vector& dim_sizes /**< [in] Initial allocation in each dimension. - Must be exatly one size for each dimension. */ ) throw(yask_exception) =0; + Must be exatly one size for each dimension. */ ) =0; #ifndef SWIG /// **[Advanced]** Add a new grid to the solution with a specified size. @@ -499,7 +499,7 @@ namespace yask { not repeated within this grid. */, const std::initializer_list& dim_sizes /**< [in] Initial allocation in each dimension. - Must be exatly one size for each dimension. */ ) throw(yask_exception) =0; + Must be exatly one size for each dimension. */ ) =0; #endif /// Prepare the solution for stencil application. @@ -512,7 +512,7 @@ namespace yask { Must be called before applying any stencils. */ virtual void - prepare_solution() throw(yask_exception) =0; + prepare_solution() =0; /// Get the first index of the sub-domain in this rank in the specified dimension. /** @@ -529,7 +529,7 @@ namespace yask { virtual idx_t get_first_rank_domain_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from get_domain_dim_names(). */ ) const =0; /// Get the last index of the sub-domain in this rank the specified dimension. /** @@ -547,7 +547,7 @@ namespace yask { virtual idx_t get_last_rank_domain_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from get_domain_dim_names(). */ ) const =0; /// Get the overall problem size in the specified dimension. /** @@ -562,7 +562,7 @@ namespace yask { virtual idx_t get_overall_domain_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from get_domain_dim_names(). */ ) const =0; /// Run the stencil solution for the specified steps. /** @@ -599,7 +599,7 @@ namespace yask { */ virtual void run_solution(idx_t first_step_index /**< [in] First index in the step dimension */, - idx_t last_step_index /**< [in] Last index in the step dimension */ ) throw(yask_exception) =0; + idx_t last_step_index /**< [in] Last index in the step dimension */ ) =0; /// Run the stencil solution for the specified step. /** @@ -612,7 +612,7 @@ namespace yask { wave-front tiling. */ virtual void - run_solution(idx_t step_index /**< [in] Index in the step dimension */ ) throw(yask_exception) =0; + run_solution(idx_t step_index /**< [in] Index in the step dimension */ ) =0; /// **[Advanced]** Restart or disable the auto-tuner on this rank. /** @@ -632,7 +632,7 @@ namespace yask { If _false_, disable the auto-tuner from running. */, bool verbose = false /**< [in] If _true_, print progress information to the debug object - set via set_debug_output(). */ ) throw(yask_exception) =0; + set via set_debug_output(). */ ) =0; /// Determine whether the auto-tuner is enabled on this rank. /** @@ -665,7 +665,7 @@ namespace yask { virtual void run_auto_tuner_now(bool verbose = true /**< [in] If _true_, print progress information to the debug object - set via set_debug_output(). */ ) throw(yask_exception) =0; + set via set_debug_output(). */ ) =0; /// **[Advanced]** Use data-storage from existing grids in specified solution. /** @@ -675,7 +675,7 @@ namespace yask { */ virtual void share_grid_storage(yk_solution_ptr source - /**< [in] Solution from which grid storage will be shared. */) throw(yask_exception) =0; + /**< [in] Solution from which grid storage will be shared. */) =0; /// Get performance statistics associated with preceding calls to run_solution(). /** @@ -684,7 +684,7 @@ namespace yask { @returns Pointer to statistics object. */ virtual yk_stats_ptr - get_stats() throw(yask_exception) =0; + get_stats() =0; /// Finish using a solution. /** @@ -693,7 +693,7 @@ namespace yask { shared by another shared pointer. */ virtual void - end_solution() throw(yask_exception) =0; + end_solution() =0; }; /// Statistics from calls to run_solution(). @@ -893,7 +893,7 @@ namespace yask { virtual idx_t get_rank_domain_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */) const =0; /// Get the first index of the sub-domain in this rank in the specified dimension. /** @@ -903,7 +903,7 @@ namespace yask { virtual idx_t get_first_rank_domain_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */ ) const =0; /// Get the last index of the sub-domain in this rank in the specified dimension. /** @@ -914,7 +914,7 @@ namespace yask { virtual idx_t get_last_rank_domain_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */ ) const =0; /// Get the halo size in the specified dimension. /** @@ -925,7 +925,7 @@ namespace yask { get_halo_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */ ) const =0; /// **[Advanced]** Set the halo size in the specified dimension. /** @@ -944,7 +944,7 @@ namespace yask { Must be one of the names from yk_solution::get_domain_dim_names(). */, idx_t size - /**< [in] Number of elements in the halo. */ ) throw(yask_exception) =0; + /**< [in] Number of elements in the halo. */ ) =0; /// Get the first index of the halo in this rank in the specified dimension. /** @@ -955,7 +955,7 @@ namespace yask { virtual idx_t get_first_rank_halo_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */ ) const =0; /// Get the last index of the halo in this rank in the specified dimension. /** @@ -966,7 +966,7 @@ namespace yask { virtual idx_t get_last_rank_halo_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */ ) const =0; /// Get the padding in the specified dimension. /** @@ -984,7 +984,7 @@ namespace yask { get_pad_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */ ) const =0; /// Get the extra padding in the specified dimension. /** @@ -997,7 +997,7 @@ namespace yask { get_extra_pad_size(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */ ) const =0; /// Set the padding in the specified dimension. /** @@ -1027,7 +1027,7 @@ namespace yask { Must be one of the names from yk_solution::get_domain_dim_names(). */, idx_t size - /**< [in] Minimum number of elements to allocate beyond the domain size. */ ) throw(yask_exception) =0; + /**< [in] Minimum number of elements to allocate beyond the domain size. */ ) =0; /// Get the storage allocation in the specified dimension. /** @@ -1039,7 +1039,7 @@ namespace yask { */ virtual idx_t get_alloc_size(const std::string& dim - /**< [in] Name of dimension to get. */ ) const throw(yask_exception) =0; + /**< [in] Name of dimension to get. */ ) const =0; /// **[Advanced]** Set the number of elements to allocate in the specified dimension. /** @@ -1057,7 +1057,7 @@ namespace yask { /**< [in] Name of dimension to set. Must *not* be one of the names from yk_solution::get_domain_dim_names(). */, - idx_t size /**< [in] Number of elements to allocate. */ ) throw(yask_exception) =0; + idx_t size /**< [in] Number of elements to allocate. */ ) =0; /// **[Advanced]** Get the first accessible index in this grid in this rank in the specified dimension. /** @@ -1072,7 +1072,7 @@ namespace yask { get_first_rank_alloc_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */ ) const =0; /// **[Advanced]** Get the last accessible index in this grid in this rank in the specified dimension. /** @@ -1087,7 +1087,7 @@ namespace yask { get_last_rank_alloc_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_domain_dim_names(). */ ) const =0; /// Get the first index of a specified miscellaneous dimension. /** @@ -1096,7 +1096,7 @@ namespace yask { virtual idx_t get_first_misc_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_misc_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_misc_dim_names(). */ ) const =0; /// Set the first index of a specified miscellaneous dimension. /** @@ -1110,7 +1110,7 @@ namespace yask { /**< [in] Name of dimension to get. Must be one of the names from yk_solution::get_misc_dim_names(). */, idx_t idx /**< [in] New value for first index. - May be negative. */ ) throw(yask_exception) =0; + May be negative. */ ) =0; /// Get the last index of a specified miscellaneous dimension. /** @@ -1119,7 +1119,7 @@ namespace yask { virtual idx_t get_last_misc_index(const std::string& dim /**< [in] Name of dimension to get. Must be one of - the names from yk_solution::get_misc_dim_names(). */ ) const throw(yask_exception) =0; + the names from yk_solution::get_misc_dim_names(). */ ) const =0; /// Get the value of one grid element. /** @@ -1128,11 +1128,11 @@ namespace yask { Index values must fall within the allocated space as returned by get_first_rank_alloc_index() and get_last_rank_alloc_index() for each dimension. - @returns value in grid at given multi-dimensional location. throw(yask_exception) + @returns value in grid at given multi-dimensional location. */ virtual double get_element(const std::vector& indices - /**< [in] List of indices, one for each grid dimension. */ ) const throw(yask_exception) =0; + /**< [in] List of indices, one for each grid dimension. */ ) const =0; #ifndef SWIG /// Get the value of one grid element. @@ -1150,7 +1150,7 @@ namespace yask { */ virtual double get_element(const std::initializer_list& indices - /**< [in] List of indices, one for each grid dimension. */ ) const throw(yask_exception) =0; + /**< [in] List of indices, one for each grid dimension. */ ) const =0; #endif /// Get grid elements within specified subset of the grid. @@ -1176,7 +1176,7 @@ namespace yask { const std::vector& first_indices /**< [in] List of initial indices, one for each grid dimension. */, const std::vector& last_indices - /**< [in] List of final indices, one for each grid dimension. */ ) const throw(yask_exception) =0; + /**< [in] List of final indices, one for each grid dimension. */ ) const =0; /// Set the value of one grid element. /** @@ -1198,7 +1198,7 @@ namespace yask { bool strict_indices = false /**< [in] If true, indices must be within domain or padding. If false, indices outside of domain and padding result - in no change to grid. */ ) throw(yask_exception) =0; + in no change to grid. */ ) =0; #ifndef SWIG /// Set the value of one grid element. @@ -1223,7 +1223,7 @@ namespace yask { bool strict_indices = false /**< [in] If true, indices must be within domain or padding. If false, indices outside of domain and padding result - in no change to grid. */ ) throw(yask_exception) =0; + in no change to grid. */ ) =0; #endif /// Initialize all grid elements to the same value. @@ -1237,7 +1237,7 @@ namespace yask { this will have no effect. */ virtual void - set_all_elements_same(double val /**< [in] All elements will be set to this. */ ) throw(yask_exception) =0; + set_all_elements_same(double val /**< [in] All elements will be set to this. */ ) =0; /// Initialize grid elements within specified subset of the grid to the same value. /** @@ -1261,7 +1261,7 @@ namespace yask { bool strict_indices = false /**< [in] If true, indices must be within domain or padding. If false, only elements within the allocation of this grid - will be set, and elements outside will be ignored. */ ) throw(yask_exception) =0; + will be set, and elements outside will be ignored. */ ) =0; /// Set grid elements within specified subset of the grid. /** @@ -1290,7 +1290,7 @@ namespace yask { const std::vector& first_indices /**< [in] List of initial indices, one for each grid dimension. */, const std::vector& last_indices - /**< [in] List of final indices, one for each grid dimension. */ ) throw(yask_exception) =0; + /**< [in] List of final indices, one for each grid dimension. */ ) =0; /// **[Advanced]** Explicitly allocate data-storage memory for this grid. /** @@ -1300,7 +1300,7 @@ namespace yask { See allocation options in the "Detailed Description" for \ref yk_grid. */ virtual void - alloc_storage() throw(yask_exception) =0; + alloc_storage() =0; /// **[Advanced]** Explicitly release any allocated data-storage for this grid. /** @@ -1310,7 +1310,7 @@ namespace yask { be retained by the remaining grids. */ virtual void - release_storage() throw(yask_exception) =0; + release_storage() =0; /// Determine whether storage has been allocated. /** @@ -1352,7 +1352,7 @@ namespace yask { `other` or `false` otherwise. */ virtual bool - is_storage_layout_identical(const yk_grid_ptr other) const throw(yask_exception) =0; + is_storage_layout_identical(const yk_grid_ptr other) const =0; /// **[Advanced]** Use existing data-storage from specified grid. /** @@ -1382,7 +1382,7 @@ namespace yask { */ virtual void share_storage(yk_grid_ptr source - /**< [in] Grid from which storage will be shared. */) throw(yask_exception) =0; + /**< [in] Grid from which storage will be shared. */) =0; /// **[Advanced]** Get pointer to raw data storage buffer. /** diff --git a/src/common/common_utils.cpp b/src/common/common_utils.cpp index 171e6e5c..22a91ccf 100644 --- a/src/common/common_utils.cpp +++ b/src/common/common_utils.cpp @@ -49,14 +49,14 @@ namespace yask { // See yask_common_api.hpp for documentation. const char* yask_exception::what() noexcept { - return msg.c_str(); + return "yask::yask_exception\n"; } void yask_exception::add_message(string arg_msg) { - msg.append(arg_msg); + msg.append(arg_msg); } - string yask_exception::get_message() { - return msg; + const char* yask_exception::get_message() { + return msg.c_str(); } } diff --git a/src/common/output.cpp b/src/common/output.cpp index c83431fe..98a3c61f 100644 --- a/src/common/output.cpp +++ b/src/common/output.cpp @@ -66,13 +66,8 @@ namespace yask { _fname = file_name; _ofs.open(file_name, ofstream::out | ofstream::trunc); if (!_ofs.is_open()) { - yask_exception e; - stringstream err; - err << "Error: cannot open '" << file_name << - "' for output.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: cannot open '" << file_name << + "' for output.\n"); } } @@ -118,26 +113,26 @@ namespace yask { // See yask_common_api.hpp for documentation. yask_file_output_ptr - yask_output_factory::new_file_output(const string& file_name) const throw(yask_exception) { + yask_output_factory::new_file_output(const string& file_name) const { auto p = make_shared(); assert(p.get()); p->open(file_name); return p; } yask_string_output_ptr - yask_output_factory::new_string_output() const throw(yask_exception){ + yask_output_factory::new_string_output() const{ auto p = make_shared(); assert(p.get()); return p; } yask_stdout_output_ptr - yask_output_factory::new_stdout_output() const throw(yask_exception){ + yask_output_factory::new_stdout_output() const{ auto p = make_shared(); assert(p.get()); return p; } yask_null_output_ptr - yask_output_factory::new_null_output() const throw(yask_exception){ + yask_output_factory::new_null_output() const{ auto p = make_shared(); assert(p.get()); return p; diff --git a/src/compiler/Makefile b/src/compiler/Makefile index 85d75d59..e422d8dd 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -135,9 +135,7 @@ $(YC_SWIG_DIR)/yask_compiler_api_wrap.cpp: $(YC_SWIG_DIR)/yask*.i $(INC_DIR)/*.h $(SWIG) -version $(SWIG) -v -DYC_MODULE=$(YC_MODULE) -cppext cpp \ -I$(INC_DIR) -I$(COMM_DIR) -I$(COMM_DIR)/swig \ - -c++ -python -outdir $(YASK_DIR) $< -# TODO: '-builtin' flag prevents to handle exception correctly, so disable for now -# -c++ -python -outdir $(YASK_DIR) -builtin $< + -c++ -python -outdir $(YASK_DIR) -builtin $< $(YC_SWIG_DIR)/yask_compiler_api_wrap.o: $(YC_SWIG_DIR)/yask_compiler_api_wrap.cpp $(YC_CXX) $(YC_CXXFLAGS) $(PYINC) -fPIC -c -o $@ $< diff --git a/src/compiler/lib/Eqs.cpp b/src/compiler/lib/Eqs.cpp index e6f08b68..75b05e11 100644 --- a/src/compiler/lib/Eqs.cpp +++ b/src/compiler/lib/Eqs.cpp @@ -244,14 +244,9 @@ namespace yask { // LHS of an equation must use step dim w/a simple offset. auto* si1p = i1->getArgOffsets().lookup(stepDim); if (!si1p || abs(*si1p) != 1) { - yask_exception e; - stringstream err; - err << "Error: equation " << eq1->makeQuotedStr() << + THROW_YASK_EXCEPTION("Error: equation " << eq1->makeQuotedStr() << " does not use offset +/- 1 from step-dimension index var '" << - stepDim << "' on LHS.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + stepDim << "' on LHS.\n"); } assert(si1p); si1 = *si1p; @@ -259,14 +254,9 @@ namespace yask { // Step direction already set? if (dims._stepDir) { if (dims._stepDir != si1) { - yask_exception e; - stringstream err; - err << "Error: equation " << eq1->makeQuotedStr() << + THROW_YASK_EXCEPTION("Error: equation " << eq1->makeQuotedStr() << " LHS has offset " << si1 << " from step-dimesion index var, " - "which is different than a previous equation with offset " << dims._stepDir << ".\n"; - e.add_message(err.str()); - throw e; - //exit(1); + "which is different than a previous equation with offset " << dims._stepDir << ".\n"); } } else dims._stepDir = si1; @@ -274,14 +264,9 @@ namespace yask { // LHS of an equation must be vectorizable. // TODO: relax this restriction. if (i1->getVecType() != GridPoint::VEC_FULL) { - yask_exception e; - stringstream err; - err << "Error: equation " << eq1->makeQuotedStr() << + THROW_YASK_EXCEPTION("Error: equation " << eq1->makeQuotedStr() << " is not fully vectorizable on LHS because not all folded" - " dimensions are accessed via simple offsets from their respective indices.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + " dimensions are accessed via simple offsets from their respective indices.\n"); } } @@ -296,14 +281,9 @@ namespace yask { // Must be in proper relation to LHS. if ((si1 > 0 && rsi1 > si1) || (si1 < 0 && rsi1 < si1)) { - yask_exception e; - stringstream err; - err << "Error: equation " << eq1->makeQuotedStr() << + THROW_YASK_EXCEPTION("Error: equation " << eq1->makeQuotedStr() << " RHS has offset " << rsi1 << " from step-dimesion index var, " - "which is incompatible with LHS offset " << si1 << ".\n"; - e.add_message(err.str()); - throw e; - //exit(1); + "which is incompatible with LHS offset " << si1 << ".\n"); } // TODO: should make some dependency checks when rsi1 == si1. @@ -333,15 +313,10 @@ namespace yask { // cannot update the exact same point. if (!same_eq && same_cond && pt_vis.do_sets_intersect(op1, op2)) { - yask_exception e; - stringstream err; - err << "Error: two equations with condition " << + THROW_YASK_EXCEPTION("Error: two equations with condition " << cond1->makeQuotedStr() << " update the same point: " << eq1->makeQuotedStr() << " and " << - eq2->makeQuotedStr() << endl; - e.add_message(err.str()); - throw e; - //exit(1); + eq2->makeQuotedStr() << ".\n"); } // eq2 dep on eq1 => some output of eq1 is an input to eq2. @@ -354,14 +329,9 @@ namespace yask { if (same_eq) { // Exit with error. - yask_exception e; - stringstream err; - err << "Error: illegal dependency between LHS and RHS of equation " << + THROW_YASK_EXCEPTION("Error: illegal dependency between LHS and RHS of equation " << eq1->makeQuotedStr() << - " within offsets in range " << pts.makeDimValStr(" * ") << ".\n"; - e.add_message(err.str()); - throw e; - //exit(1); + " within offsets in range " << pts.makeDimValStr(" * ") << ".\n"); } // Save dependency. @@ -750,14 +720,9 @@ namespace yask { // Must swap on certain deps. if (egi.isDepOn(certain_dep, egj)) { if (egj.isDepOn(certain_dep, egi)) { - yask_exception e; - stringstream err; - err << "Error: circular dependency between eq-groups " << + THROW_YASK_EXCEPTION("Error: circular dependency between eq-groups " << egi.getDescription() << " and " << - egj.getDescription() << endl; - e.add_message(err.str()); - throw e; - //exit(1); + egj.getDescription() << "\n."); } do_swap = true; } diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index 430a7ba9..fdf4be4a 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -42,21 +42,21 @@ namespace yask { //node_factory API methods. yc_index_node_ptr - yc_node_factory::new_step_index(const std::string& name) throw(yask_exception) { + yc_node_factory::new_step_index(const std::string& name) { return make_shared(name, STEP_INDEX); } yc_index_node_ptr - yc_node_factory::new_domain_index(const std::string& name) throw(yask_exception) { + yc_node_factory::new_domain_index(const std::string& name) { return make_shared(name, DOMAIN_INDEX); } yc_index_node_ptr - yc_node_factory::new_misc_index(const std::string& name) throw(yask_exception) { + yc_node_factory::new_misc_index(const std::string& name) { return make_shared(name, MISC_INDEX); } yc_equation_node_ptr yc_node_factory::new_equation_node(yc_grid_point_node_ptr lhs, - yc_number_node_ptr rhs) throw(yask_exception) { + yc_number_node_ptr rhs) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -64,18 +64,18 @@ namespace yask { return operator EQUALS_OPER(lp, rp); } yc_const_number_node_ptr - yc_node_factory::new_const_number_node(double val) throw(yask_exception) { + yc_node_factory::new_const_number_node(double val) { return make_shared(val); } yc_negate_node_ptr - yc_node_factory::new_negate_node(yc_number_node_ptr rhs) throw(yask_exception) { + yc_node_factory::new_negate_node(yc_number_node_ptr rhs) { auto p = dynamic_pointer_cast(rhs); assert(p); return make_shared(p); } yc_add_node_ptr yc_node_factory::new_add_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) throw(yask_exception) { + yc_number_node_ptr rhs) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -84,7 +84,7 @@ namespace yask { } yc_multiply_node_ptr yc_node_factory::new_multiply_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) throw(yask_exception) { + yc_number_node_ptr rhs) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -93,7 +93,7 @@ namespace yask { } yc_subtract_node_ptr yc_node_factory::new_subtract_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) throw(yask_exception) { + yc_number_node_ptr rhs) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -102,7 +102,7 @@ namespace yask { } yc_divide_node_ptr yc_node_factory::new_divide_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) throw(yask_exception) { + yc_number_node_ptr rhs) { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -389,14 +389,9 @@ namespace yask { // Check for correct number of args. size_t nd = grid->getDims().size(); if (nd != args.size()) { - yask_exception e; - stringstream err; - err << "Error: attempt to create a grid point in " << + THROW_YASK_EXCEPTION("Error: attempt to create a grid point in " << nd << "-D grid '" << getGridName() << "' with " << - args.size() << " indices.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + args.size() << " indices.\n"); } // Eval each arg. diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index 48727e6f..1d0aece3 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -124,10 +124,10 @@ namespace yask { } // APIs. - virtual string format_simple() const throw(yask_exception) { + virtual string format_simple() const { return makeStr(); } - virtual int get_num_nodes() const throw(yask_exception) { + virtual int get_num_nodes() const { return getNumNodes(); } }; @@ -136,13 +136,8 @@ namespace yask { template shared_ptr castExpr(ExprPtr ep, const string& descrip) { auto tp = dynamic_pointer_cast(ep); if (!tp) { - yask_exception e; - stringstream err; - err << "Error: expression '" << ep->makeStr() << "' is not a " << - descrip << "." << endl; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: expression '" << ep->makeStr() << "' is not a " << + descrip << "." << endl); } return tp; } @@ -172,13 +167,8 @@ namespace yask { // Get the current value. // Exit with error if not known. virtual double getNumVal() const { - yask_exception e; - stringstream err; - err << "Error: cannot evaluate '" << makeStr() << - "' for a known numerical value.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: cannot evaluate '" << makeStr() << + "' for a known numerical value.\n"); } // Get the value as an integer. @@ -187,13 +177,8 @@ namespace yask { double val = getNumVal(); int ival = int(val); if (val != double(ival)) { - yask_exception e; - stringstream err; - err << "Error: '" << makeStr() << - "' does not evaluate to an integer.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: '" << makeStr() << + "' does not evaluate to an integer.\n"); } return ival; } @@ -297,13 +282,8 @@ namespace yask { // Get the current value. // Exit with error if not known. virtual bool getBoolVal() const { - yask_exception e; - stringstream err; - err << "Error: cannot evaluate '" << makeStr() << - "' for a known boolean value.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: cannot evaluate '" << makeStr() << + "' for a known boolean value.\n"); } // Create a deep copy of this expression. @@ -631,14 +611,14 @@ namespace yask { virtual int get_num_operands() { return _ops.size(); } - virtual yc_number_node_ptr get_operand(int i) throw(yask_exception) { + virtual yc_number_node_ptr get_operand(int i) { if (i >= 0 && size_t(i) < _ops.size()) return _ops.at(size_t(i)); else return nullptr; } - virtual void add_operand(yc_number_node_ptr node) throw(yask_exception) { + virtual void add_operand(yc_number_node_ptr node) { auto p = dynamic_pointer_cast(node); assert(p); appendOp(p); diff --git a/src/compiler/lib/Grid.cpp b/src/compiler/lib/Grid.cpp index ebba8a4a..8ca84550 100644 --- a/src/compiler/lib/Grid.cpp +++ b/src/compiler/lib/Grid.cpp @@ -37,18 +37,13 @@ namespace yask { // grid APIs. yc_grid_point_node_ptr - Grid::new_relative_grid_point(std::vector dim_offsets) throw(yask_exception) { + Grid::new_relative_grid_point(std::vector dim_offsets) { // Check for correct number of indices. if (_dims.size() != dim_offsets.size()) { - yask_exception e; - stringstream err; - err << "Error: attempt to create a relative grid point in " << + THROW_YASK_EXCEPTION("Error: attempt to create a relative grid point in " << _dims.size() << "D grid '" << _name << "' with " << - dim_offsets.size() << " indices.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + dim_offsets.size() << " indices.\n"); } // Check dim types. @@ -57,15 +52,10 @@ namespace yask { for (size_t i = 0; i < _dims.size(); i++) { auto dim = _dims.at(i); if (dim->getType() == MISC_INDEX) { - yask_exception e; - stringstream err; - err << "Error: attempt to create a relative grid point in " << + THROW_YASK_EXCEPTION("Error: attempt to create a relative grid point in " << _dims.size() << "D grid '" << _name << "' containing non-step or non-domain dim '" << - dim->getName() << "'.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + dim->getName() << "'.\n"); } auto ie = dim->clone(); args.push_back(ie); @@ -95,7 +85,7 @@ namespace yask { std::string yc_factory::get_version_string() { return yask_get_version_string(); } - yc_solution_ptr yc_factory::new_solution(const std::string& name) const throw(yask_exception) { + yc_solution_ptr yc_factory::new_solution(const std::string& name) const { return make_shared(name); } @@ -302,13 +292,8 @@ namespace yask { case STEP_INDEX: if (_stepDim.length() && _stepDim != dname) { - yask_exception e; - stringstream err; - err << "Error: step dimensions '" << _stepDim << - "' and '" << dname << "' found; only one allowed.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: step dimensions '" << _stepDim << + "' and '" << dname << "' found; only one allowed.\n"); } _stepDim = dname; _stencilDims.addDimFront(dname, 0); // must be first! @@ -327,30 +312,15 @@ namespace yask { break; default: - yask_exception e; - stringstream err; - err << "Error: unexpected dim type " << type << ".\n"; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: unexpected dim type " << type << ".\n"); } } } if (_stepDim.length() == 0) { - yask_exception e; - stringstream err; - err << "Error: no step dimension defined.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: no step dimension defined.\n"); } if (!_domainDims.getNumDims()) { - yask_exception e; - stringstream err; - err << "Error: no domain dimensions defined.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: no domain dimensions defined.\n"); } // Use last domain dim as inner one. @@ -445,13 +415,8 @@ namespace yask { // Checks for unaligned loads. if (settings._allowUnalignedLoads) { if (_foldGT1.size() > 1) { - yask_exception e; - stringstream err; - err << "Error: attempt to allow unaligned loads when there are " << - _foldGT1.size() << " dimensions in the vector-fold that are > 1." << endl; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: attempt to allow unaligned loads when there are " << + _foldGT1.size() << " dimensions in the vector-fold that are > 1." << endl); } else if (_foldGT1.size() > 0) cerr << "Notice: memory layout MUST have unit-stride in " << diff --git a/src/compiler/lib/Grid.hpp b/src/compiler/lib/Grid.hpp index 3c7e27d5..dd42b658 100644 --- a/src/compiler/lib/Grid.hpp +++ b/src/compiler/lib/Grid.hpp @@ -224,7 +224,7 @@ namespace yask { virtual int get_num_dims() const { return int(_dims.size()); } - virtual const string& get_dim_name(int n) const throw(yask_exception) { + virtual const string& get_dim_name(int n) const { assert(n >= 0); assert(n < get_num_dims()); auto dp = _dims.at(n); @@ -233,9 +233,9 @@ namespace yask { } virtual std::vector get_dim_names() const; virtual yc_grid_point_node_ptr - new_relative_grid_point(std::vector dim_offsets) throw(yask_exception); + new_relative_grid_point(std::vector dim_offsets); virtual yc_grid_point_node_ptr - new_relative_grid_point(const std::initializer_list& dim_offsets) throw(yask_exception) { + new_relative_grid_point(const std::initializer_list& dim_offsets) { std::vector dim_ofs_vec(dim_offsets); return new_relative_grid_point(dim_ofs_vec); } diff --git a/src/compiler/lib/Parse.hpp b/src/compiler/lib/Parse.hpp index d44e2eba..60dbdff4 100644 --- a/src/compiler/lib/Parse.hpp +++ b/src/compiler/lib/Parse.hpp @@ -74,12 +74,7 @@ namespace yask { // split by equal sign. size_t ep = pStr.find("="); if (ep == string::npos) { - yask_exception e; - stringstream err; - cerr << "Error: no equal sign in '" << pStr << "'." << endl; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: no equal sign in '" << pStr << "'." << endl); } string key = pStr.substr(0, ep); string value = pStr.substr(ep+1); diff --git a/src/compiler/lib/Soln.cpp b/src/compiler/lib/Soln.cpp index 5d26f09a..19a1c2d0 100644 --- a/src/compiler/lib/Soln.cpp +++ b/src/compiler/lib/Soln.cpp @@ -34,7 +34,7 @@ namespace yask { // Stencil-solution APIs. yc_grid_ptr StencilSolution::new_grid(const std::string& name, - const std::vector& dims) throw(yask_exception) { + const std::vector& dims) { // Make new grid and add to solution. // TODO: fix this mem leak--make smart ptr. @@ -54,12 +54,12 @@ namespace yask { // Stencil-solution APIs. void StencilSolution::set_fold_len(const yc_index_node_ptr dim, - int len) throw(yask_exception) { + int len) { auto& fold = _settings._foldOptions; fold.addDimBack(dim->get_name(), len); } void StencilSolution::set_cluster_mult(const yc_index_node_ptr dim, - int mult) throw(yask_exception) { + int mult) { auto& cluster = _settings._clusterOptions; cluster.addDimBack(dim->get_name(), mult); } @@ -119,7 +119,7 @@ namespace yask { // Format in given format-type. void StencilSolution::format(const string& format_type, - yask_output_ptr output) throw(yask_exception) { + yask_output_ptr output) { // Look for format match. // Most args to the printers just set references to data. @@ -142,13 +142,8 @@ namespace yask { else if (format_type == "pov-ray") // undocumented. printer = new POVRayPrinter(*this, _clusterEqGroups); else { - yask_exception e; - stringstream err; - err << "Error: format-type '" << format_type << - "' is not recognized." << endl; - e.add_message(err.str()); - throw e; - //exit(1); + THROW_YASK_EXCEPTION("Error: format-type '" << format_type << + "' is not recognized." << endl); } assert(printer); int vlen = printer->num_vec_elems(); diff --git a/src/compiler/lib/Soln.hpp b/src/compiler/lib/Soln.hpp index c4a232b7..76d7fd4f 100644 --- a/src/compiler/lib/Soln.hpp +++ b/src/compiler/lib/Soln.hpp @@ -123,16 +123,16 @@ namespace yask { } virtual yc_grid_ptr new_grid(const std::string& name, - const std::vector& dims) throw(yask_exception); + const std::vector& dims); virtual yc_grid_ptr new_grid(const std::string& name, - const std::initializer_list& dims) throw(yask_exception) { + const std::initializer_list& dims) { std::vector dim_vec(dims); return new_grid(name, dim_vec); } virtual int get_num_grids() const { return int(_grids.size()); } - virtual yc_grid_ptr get_grid(const std::string& name) throw(yask_exception) { + virtual yc_grid_ptr get_grid(const std::string& name) { for (int i = 0; i < get_num_grids(); i++) if (_grids.at(i)->getName() == name) return _grids.at(i); @@ -148,7 +148,7 @@ namespace yask { virtual int get_num_equations() const { return _eqs.getNumEqs(); } - virtual yc_equation_node_ptr get_equation(int n) throw(yask_exception) { + virtual yc_equation_node_ptr get_equation(int n) { assert(n >= 0 && n < get_num_equations()); return _eqs.getEqs().at(n); } @@ -160,14 +160,14 @@ namespace yask { else fold.addDimBack(dim, len); } - virtual void set_fold_len(const yc_index_node_ptr, int len) throw(yask_exception); + virtual void set_fold_len(const yc_index_node_ptr, int len); virtual void clear_folding() { _settings._foldOptions.clear(); } - virtual void set_cluster_mult(const yc_index_node_ptr, int mult) throw(yask_exception); + virtual void set_cluster_mult(const yc_index_node_ptr, int mult); virtual void clear_clustering() { _settings._clusterOptions.clear(); } virtual void set_element_bytes(int nbytes) { _settings._elem_bytes = nbytes; } virtual int get_element_bytes() const { return _settings._elem_bytes; } virtual void format(const std::string& format_type, - yask_output_ptr output) throw(yask_exception) ; + yask_output_ptr output) ; }; // A stencil solution that does not define any grids. diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index b175e015..cc4e874a 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -230,14 +230,9 @@ namespace yask { if (dtype == STEP_INDEX) { assert(dname == _dims->_stepDim); if (dn > 0) { - yask_exception e; - stringstream err; - err << "Error: cannot create grid '" << grid << + THROW_YASK_EXCEPTION("Error: cannot create grid '" << grid << "' with dimensions '" << gdims.makeDimStr() << - "' because '" << dname << "' must be first dimension.\n"; - e.add_message(err.str()); - throw e; - //exit(1); + "' because '" << dname << "' must be first dimension.\n"); } if (folded) { step_posn = dn + 1; diff --git a/src/compiler/swig/yask_compiler_api.i b/src/compiler/swig/yask_compiler_api.i index 7ec0a433..a5d1f0e5 100644 --- a/src/compiler/swig/yask_compiler_api.i +++ b/src/compiler/swig/yask_compiler_api.i @@ -64,6 +64,15 @@ IN THE SOFTWARE. %template(vector_str) std::vector; %template(vector_index_ptr) std::vector>; %template(vector_grid) std::vector; - + +%exception { + try { + $action + } catch (yask::yask_exception &e) { + PyErr_SetString(PyExc_RuntimeError, const_cast(e.get_message())); + SWIG_fail; + } +} + %include "yask_common_api.hpp" %include "yask_compiler_api.hpp" diff --git a/src/compiler/tests/yask_compiler_api_exception_test.cpp b/src/compiler/tests/yask_compiler_api_exception_test.cpp index 5444d948..d0d0ac1f 100644 --- a/src/compiler/tests/yask_compiler_api_exception_test.cpp +++ b/src/compiler/tests/yask_compiler_api_exception_test.cpp @@ -66,13 +66,13 @@ int main() { // Exception test cout << "Exception Test: Call 'new_relative_grid_point' with wrong argument.\n"; try { - auto n3 = g1->new_relative_grid_point({0, +1, 0, -2, 1}); + auto n3 = g1->new_relative_grid_point({0, +1, 0, -2, 1}); } catch (yask_exception e) { - cout << "YASK throws an exception.\n"; - cout << e.get_message(); - cout << "Exception Test: Catch exception correctly.\n"; - num_exception++; - } + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } auto n3 = g1->new_relative_grid_point({0, +1, 0, -2}); cout << n3->format_simple() << endl; @@ -103,13 +103,13 @@ int main() { // Exception test cout << "Exception Test: Call 'new_file_output' with read-only file name.\n"; try { - auto dot_file = ofac.new_file_output("yc-api-test-with-exception-cxx-readonly"); + auto dot_file = ofac.new_file_output("yc-api-test-with-exception-cxx-readonly"); } catch (yask_exception e) { - cout << "YASK throws an exception.\n"; - cout << e.get_message(); - cout << "Exception Test: Catch exception correctly.\n"; - num_exception++; - } + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } // Generate DOT output. auto dot_file = ofac.new_file_output("yc-api-test-with-exception-cxx.dot"); @@ -124,13 +124,13 @@ int main() { // Exception test cout << "Exception Test: Call 'format' with wrong format.\n"; try { - soln->format("wrong_format", dot_file); + soln->format("wrong_format", dot_file); } catch (yask_exception e) { - cout << "YASK throws an exception.\n"; - cout << e.get_message(); - cout << "Exception Test: Catch exception correctly.\n"; - num_exception++; - } + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } // TODO: better to have exception test for the methods below // Eqs::findDeps (<-EqGroups::makeEqGroups<-StencilSolution::analyze_solution<-StencilSolution::format()) @@ -148,7 +148,7 @@ int main() { exit(1); } else - cout << "End of YASK compiler API test with exception.\n"; + cout << "End of YASK compiler API test with exception.\n"; return 0; } diff --git a/src/kernel/Makefile b/src/kernel/Makefile index e07d7242..79b5af23 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -622,9 +622,7 @@ $(YK_SWIG_DIR)/yask_kernel_api_wrap.cpp: $(YK_SWIG_DIR)/yask*.i $(INC_DIR)/*.hpp $(SWIG) -version $(SWIG) -v -DYK_MODULE=$(YK_MODULE) -cppext cpp \ -I$(INC_DIR) -I$(COMM_DIR) -I$(COMM_DIR)/swig \ - -c++ -python -outdir $(YASK_DIR) $< -# TODO: '-builtin' flag prevents to handle exception correctly, so disable for now -# -c++ -python -outdir $(YASK_DIR) -builtin $< + -c++ -python -outdir $(YASK_DIR) -builtin $< $(YK_SWIG_DIR)/yask_kernel_api_wrap.o: $(YK_SWIG_DIR)/yask_kernel_api_wrap.cpp $(YK_CXX) $(YK_CXXFLAGS) $(PYINC) -fPIC -c -o $@ $< diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index 72d26f99..c672a73f 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -32,7 +32,7 @@ namespace yask { // See yask_kernel_api.hpp. #define GET_SOLN_API(api_name, expr, step_ok, domain_ok, misc_ok) \ - idx_t StencilContext::api_name(const string& dim) const throw(yask_exception) { \ + idx_t StencilContext::api_name(const string& dim) const { \ checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ return expr; \ } @@ -47,7 +47,7 @@ namespace yask { #undef GET_SOLN_API #define SET_SOLN_API(api_name, expr, step_ok, domain_ok, misc_ok) \ - void StencilContext::api_name(const string& dim, idx_t n) throw(yask_exception) { \ + void StencilContext::api_name(const string& dim, idx_t n) { \ checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ expr; \ update_grids(); \ @@ -58,7 +58,7 @@ namespace yask { SET_SOLN_API(set_num_ranks, _opts->_num_ranks[dim] = n, false, true, false) #undef SET_SOLN_API - void StencilContext::share_grid_storage(yk_solution_ptr source) throw(yask_exception) { + void StencilContext::share_grid_storage(yk_solution_ptr source) { auto sp = dynamic_pointer_cast(source); assert(sp); @@ -72,7 +72,7 @@ namespace yask { } } - string StencilContext::apply_command_line_options(const string& args) throw(yask_exception) { + string StencilContext::apply_command_line_options(const string& args) { // Create a parser and add base options to it. CommandLineParser parser; @@ -208,7 +208,7 @@ namespace yask { // Eval stencil group(s) over grid(s) using optimized code. void StencilContext::run_solution(idx_t first_step_index, - idx_t last_step_index) throw(yask_exception) + idx_t last_step_index) { run_time.start(); @@ -233,12 +233,7 @@ namespace yask { TRACE_MSG("run_solution: " << begin.makeDimValStr() << " ... (end before) " << end.makeDimValStr() << " by " << step.makeDimValStr()); if (!bb_valid) { - yask_exception e; - stringstream err; - err << "Error: run_solution() called without calling prepare_solution() first.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: run_solution() called without calling prepare_solution() first.\n"); } if (bb_size < 1) { TRACE_MSG("nothing to do in solution"); @@ -349,22 +344,12 @@ namespace yask { // TODO: enable reverse time w/wave-fronts. if (step_t < 0) { - yask_exception e; - stringstream err; - err << "Error: reverse time with wave-fronts not yet supported.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: reverse time with wave-fronts not yet supported.\n"); } // TODO: enable halo exchange for wave-fronts. if (_env->num_ranks > 1) { - yask_exception e; - stringstream err; - err << "Error: halo exchange with wave-fronts not yet supported.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: halo exchange with wave-fronts not yet supported.\n"); } // Eval all stencil groups. @@ -440,12 +425,7 @@ namespace yask { // Not yet supporting temporal blocking. if (_opts->_block_sizes[step_dim] != 1) { - yask_exception e; - stringstream err; - err << "Error: temporal blocking not yet supported." << endl; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: temporal blocking not yet supported." << endl); } // Steps within a region are based on block sizes. @@ -783,14 +763,9 @@ namespace yask { } // Apply auto-tuning to some of the settings. - void StencilContext::run_auto_tuner_now(bool verbose) throw(yask_exception) { + void StencilContext::run_auto_tuner_now(bool verbose) { if (!bb_valid) { - yask_exception e; - stringstream err; - err << "Error: tune_settings() called without calling prepare_solution() first.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: tune_settings() called without calling prepare_solution() first.\n"); } ostream& os = get_ostr(); os << "Auto-tuning...\n" << flush; @@ -844,12 +819,7 @@ namespace yask { void StencilContext::addGrid(YkGridPtr gp, bool is_output) { auto& gname = gp->get_name(); if (gridMap.count(gname)) { - yask_exception e; - stringstream err; - err << "Error: grid '" << gname << "' already exists.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: grid '" << gname << "' already exists.\n"); } // Add to list and map. @@ -876,14 +846,9 @@ namespace yask { // Check ranks. idx_t req_ranks = _opts->_num_ranks.product(); if (req_ranks != _env->num_ranks) { - yask_exception e; - stringstream err; - err << "error: " << req_ranks << " rank(s) requested (" << + THROW_YASK_EXCEPTION("error: " << req_ranks << " rank(s) requested (" << _opts->_num_ranks.makeDimValStr(" * ") << "), but " << - _env->num_ranks << " rank(s) are active." << endl; - e.add_message(err.str()); - throw e; - //exit_yask(1); + _env->num_ranks << " rank(s) are active." << endl); } assertEqualityOverRanks(_opts->_rank_sizes[step_dim], _env->comm, "num steps"); @@ -948,25 +913,15 @@ namespace yask { // Myself. if (rn == me) { if (mandist != 0) { - yask_exception e; - stringstream err; - err << "Internal error: distance to own rank == " << mandist << endl; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Internal error: distance to own rank == " << mandist << endl); } } // Someone else. else { if (mandist == 0) { - yask_exception e; - stringstream err; - err << "Error: ranks " << me << - " and " << rn << " at same coordinates." << endl; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: ranks " << me << + " and " << rn << " at same coordinates." << endl); } } @@ -1005,18 +960,13 @@ namespace yask { auto rnsz = rsizes[rn][dj]; if (mysz != rnsz) { auto& dnamej = _opts->_rank_indices.getDimName(dj); - yask_exception e; - stringstream err; - err << "Error: rank " << rn << " and " << me << + THROW_YASK_EXCEPTION("Error: rank " << rn << " and " << me << " are both at rank-index " << coords[me][di] << " in the '" << dname << "' dimension , but their rank-domain sizes are " << rnsz << " and " << mysz << " (resp.) in the '" << dj << - "' dimension, making them unaligned.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + "' dimension, making them unaligned.\n"); } } } @@ -1075,14 +1025,9 @@ namespace yask { // Is domain size at least as large as halo in direction // with multiple ranks? if (_opts->_num_ranks[dname] > 1 && rnsz < max_halos[di]) { - yask_exception e; - stringstream err; - err << "Error: rank-domain size of " << rnsz << " in '" << + THROW_YASK_EXCEPTION("Error: rank-domain size of " << rnsz << " in '" << dname << "' in rank " << rn << - " is less than largest halo size of " << max_halos[di] << endl; - e.add_message(err.str()); - throw e; - //exit_yask(1); + " is less than largest halo size of " << max_halos[di] << endl); } } @@ -1512,7 +1457,7 @@ namespace yask { // Allocate grids and MPI bufs. // Initialize some data structures. - void StencilContext::prepare_solution() throw(yask_exception) { + void StencilContext::prepare_solution() { // Don't continue until all ranks are this far. _env->global_barrier(); @@ -1583,12 +1528,7 @@ namespace yask { // TODO: enable multi-rank wave-front tiling. auto& step_dim = _dims->_step_dim; if (_opts->_region_sizes[step_dim] > 1 && _env->num_ranks > 1) { - yask_exception e; - stringstream err; - err << "MPI communication is not currently enabled with wave-front tiling." << endl; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("MPI communication is not currently enabled with wave-front tiling." << endl); } os << endl; @@ -1746,7 +1686,7 @@ namespace yask { } /// Get statistics associated with preceding calls to run_solution(). - yk_stats_ptr StencilContext::get_stats() throw(yask_exception) { + yk_stats_ptr StencilContext::get_stats() { ostream& os = get_ostr(); // Calc and report perf. @@ -1793,7 +1733,7 @@ namespace yask { } // Dealloc grids, etc. - void StencilContext::end_solution() throw(yask_exception) { + void StencilContext::end_solution() { // Release any MPI data. mpiData.clear(); diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index 0c35cb4c..53424b9a 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -356,7 +356,7 @@ namespace yask { // Calculate rank position in problem. // Initialize some other data structures. // Print lots of stats. - virtual void prepare_solution() throw(yask_exception); + virtual void prepare_solution(); /// Get statistics associated with preceding calls to run_solution(). @@ -364,10 +364,10 @@ namespace yask { Resets all timers and step counters. @returns Pointer to statistics object. */ - virtual yk_stats_ptr get_stats() throw(yask_exception); + virtual yk_stats_ptr get_stats(); // Dealloc grids, etc. - virtual void end_solution() throw(yask_exception); + virtual void end_solution(); // Set grid sizes and offsets. // This should be called anytime a setting or offset is changed. @@ -540,7 +540,7 @@ namespace yask { return int(gridPtrs.size()); } - virtual yk_grid_ptr get_grid(const std::string& name) throw(yask_exception) { + virtual yk_grid_ptr get_grid(const std::string& name) { auto i = gridMap.find(name); if (i != gridMap.end()) return i->second; @@ -554,25 +554,25 @@ namespace yask { } virtual yk_grid_ptr new_grid(const std::string& name, - const GridDimNames& dims) throw(yask_exception) { + const GridDimNames& dims) { return newGrid(name, dims, NULL); } virtual yk_grid_ptr new_grid(const std::string& name, - const std::initializer_list& dims) throw(yask_exception) { + const std::initializer_list& dims) { GridDimNames dims2(dims); return new_grid(name, dims2); } virtual yk_grid_ptr new_fixed_size_grid(const std::string& name, const GridDimNames& dims, - const GridDimSizes& dim_sizes) throw(yask_exception) { + const GridDimSizes& dim_sizes) { return newGrid(name, dims, &dim_sizes); } virtual yk_grid_ptr new_fixed_size_grid(const std::string& name, const std::initializer_list& dims, - const std::initializer_list& dim_sizes) throw(yask_exception) { + const std::initializer_list& dim_sizes) { GridDimNames dims2(dims); GridDimSizes sizes2(dim_sizes); return new_fixed_size_grid(name, dims2, sizes2); @@ -597,37 +597,37 @@ namespace yask { return dims; } - virtual idx_t get_first_rank_domain_index(const std::string& dim) const throw(yask_exception); - virtual idx_t get_last_rank_domain_index(const std::string& dim) const throw(yask_exception); - virtual idx_t get_overall_domain_size(const std::string& dim) const throw(yask_exception); + virtual idx_t get_first_rank_domain_index(const std::string& dim) const; + virtual idx_t get_last_rank_domain_index(const std::string& dim) const; + virtual idx_t get_overall_domain_size(const std::string& dim) const; virtual void run_solution(idx_t first_step_index, - idx_t last_step_index) throw(yask_exception); - virtual void run_solution(idx_t step_index) throw(yask_exception) { + idx_t last_step_index); + virtual void run_solution(idx_t step_index) { run_solution(step_index, step_index); } - virtual void share_grid_storage(yk_solution_ptr source) throw(yask_exception); + virtual void share_grid_storage(yk_solution_ptr source); // APIs that access settings. virtual void set_rank_domain_size(const std::string& dim, - idx_t size) throw(yask_exception); + idx_t size); virtual void set_min_pad_size(const std::string& dim, - idx_t size) throw(yask_exception); + idx_t size); virtual void set_block_size(const std::string& dim, - idx_t size) throw(yask_exception); + idx_t size); virtual void set_num_ranks(const std::string& dim, - idx_t size) throw(yask_exception); - virtual idx_t get_rank_domain_size(const std::string& dim) const throw(yask_exception); - virtual idx_t get_min_pad_size(const std::string& dim) const throw(yask_exception); - virtual idx_t get_block_size(const std::string& dim) const throw(yask_exception); - virtual idx_t get_num_ranks(const std::string& dim) const throw(yask_exception); - virtual idx_t get_rank_index(const std::string& dim) const throw(yask_exception); - virtual std::string apply_command_line_options(const std::string& args) throw(yask_exception); - - virtual void reset_auto_tuner(bool enable, bool verbose = false) throw(yask_exception) { + idx_t size); + virtual idx_t get_rank_domain_size(const std::string& dim) const; + virtual idx_t get_min_pad_size(const std::string& dim) const; + virtual idx_t get_block_size(const std::string& dim) const; + virtual idx_t get_num_ranks(const std::string& dim) const; + virtual idx_t get_rank_index(const std::string& dim) const; + virtual std::string apply_command_line_options(const std::string& args); + + virtual void reset_auto_tuner(bool enable, bool verbose = false) { _at.clear(!enable, verbose); } - virtual void run_auto_tuner_now(bool verbose = true) throw(yask_exception); + virtual void run_auto_tuner_now(bool verbose = true); virtual bool is_auto_tuner_enabled() { return !_at.is_done(); } diff --git a/src/kernel/lib/factory.cpp b/src/kernel/lib/factory.cpp index deab67f7..e7394ae2 100644 --- a/src/kernel/lib/factory.cpp +++ b/src/kernel/lib/factory.cpp @@ -34,7 +34,7 @@ namespace yask { return yask_get_version_string(); } yk_solution_ptr yk_factory::new_solution(yk_env_ptr env, - const yk_solution_ptr source) const throw(yask_exception) { + const yk_solution_ptr source) const { auto ep = dynamic_pointer_cast(env); assert(ep); auto dp = YASK_STENCIL_CONTEXT::new_dims(); @@ -62,7 +62,7 @@ namespace yask { return sp; } - yk_solution_ptr yk_factory::new_solution(yk_env_ptr env) const throw(yask_exception) { + yk_solution_ptr yk_factory::new_solution(yk_env_ptr env) const { return new_solution(env, nullptr); } diff --git a/src/kernel/lib/new_grid.cpp b/src/kernel/lib/new_grid.cpp index d5ae32a6..37b3299d 100644 --- a/src/kernel/lib/new_grid.cpp +++ b/src/kernel/lib/new_grid.cpp @@ -37,14 +37,9 @@ namespace yask { bool got_sizes = sizes != NULL; if (got_sizes) { if (dims.size() != sizes->size()) { - yask_exception e; - stringstream err; - err << "Error: attempt to create grid '" << name << "' with " << + THROW_YASK_EXCEPTION("Error: attempt to create grid '" << name << "' with " << dims.size() << " dimension names but " << sizes->size() << - " dimension sizes.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + " dimension sizes.\n"); } } @@ -63,27 +58,17 @@ namespace yask { // Already used? if (seenDims.count(dims[i])) { - yask_exception e; - stringstream err; - err << "Error: cannot create grid '" << name << - "': dimension '" << dims[i] << "' used more than once.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: cannot create grid '" << name << + "': dimension '" << dims[i] << "' used more than once.\n"); } // Step dim? if (dims[i] == _dims->_step_dim) { step_posn = i; if (i > 0) { - yask_exception e; - stringstream err; - err << "Error: cannot create grid '" << name << + THROW_YASK_EXCEPTION("Error: cannot create grid '" << name << "' because step dimension '" << dims[i] << - "' must be first dimension.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + "' must be first dimension.\n"); } } } @@ -97,14 +82,9 @@ namespace yask { #include "yask_grid_code.hpp" if (!gp) { - yask_exception e; - stringstream err; - err << "Error in new_grid: cannot create grid '" << name << + THROW_YASK_EXCEPTION("Error in new_grid: cannot create grid '" << name << "' with " << ndims << " dimensions; only up to " << MAX_DIMS << - " dimensions supported.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + " dimensions supported.\n"); } } diff --git a/src/kernel/lib/realv_grids.cpp b/src/kernel/lib/realv_grids.cpp index aba1d76f..6cbc1aab 100644 --- a/src/kernel/lib/realv_grids.cpp +++ b/src/kernel/lib/realv_grids.cpp @@ -32,12 +32,12 @@ namespace yask { // APIs to get info from vars. #define GET_GRID_API(api_name, expr, step_ok, domain_ok, misc_ok) \ - idx_t YkGridBase::api_name(const string& dim) const throw(yask_exception) { \ + idx_t YkGridBase::api_name(const string& dim) const { \ checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ int posn = get_dim_posn(dim, true, #api_name); \ return expr; \ } \ - idx_t YkGridBase::api_name(int posn) const throw(yask_exception) { \ + idx_t YkGridBase::api_name(int posn) const { \ return expr; \ } GET_GRID_API(get_rank_domain_size, _domains[posn], false, true, false) @@ -61,12 +61,12 @@ namespace yask { // APIs to set vars. #define COMMA , #define SET_GRID_API(api_name, expr, step_ok, domain_ok, misc_ok) \ - void YkGridBase::api_name(const string& dim, idx_t n) throw(yask_exception) { \ + void YkGridBase::api_name(const string& dim, idx_t n) { \ checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ int posn = get_dim_posn(dim, true, #api_name); \ expr; \ } \ - void YkGridBase::api_name(int posn, idx_t n) throw(yask_exception) { \ + void YkGridBase::api_name(int posn, idx_t n) { \ int dim = posn; \ expr; \ } @@ -128,15 +128,10 @@ namespace yask { auto& dims = _ggb->get_dims(); int posn = dims.lookup_posn(dim); if (posn < 0 && die_on_failure) { - yask_exception e; - stringstream err; - err << "Error: " << die_msg << ": dimension '" << + THROW_YASK_EXCEPTION("Error: " << die_msg << ": dimension '" << dim << "' not found in "; print_info(cerr); - err << ".\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + err << ".\n"); } return posn; } @@ -163,16 +158,11 @@ namespace yask { // Attempt to change alloc with existing storage? if (p && old_allocs != new_allocs) { - yask_exception e; - stringstream err; - err << "Error: attempt to change allocation size of grid '" << + THROW_YASK_EXCEPTION("Error: attempt to change allocation size of grid '" << get_name() << "' from " << makeIndexString(old_allocs, " * ") << " to " << makeIndexString(new_allocs, " * ") << - " after storage has been allocated.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + " after storage has been allocated.\n"); } // Do the resize. @@ -207,20 +197,15 @@ namespace yask { bool domain_ok, bool misc_ok) const { if (!is_dim_used(dim)) { - yask_exception e; - stringstream err; - err << "Error in " << fn_name << "(): dimension '" << + THROW_YASK_EXCEPTION("Error in " << fn_name << "(): dimension '" << dim << "' not found in "; print_info(cerr); - err << ".\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + err << ".\n"); } _dims->checkDimType(dim, fn_name, step_ok, domain_ok, misc_ok); } - bool YkGridBase::is_storage_layout_identical(const yk_grid_ptr other) const throw(yask_exception) { + bool YkGridBase::is_storage_layout_identical(const yk_grid_ptr other) const { auto op = dynamic_pointer_cast(other); assert(op); @@ -249,17 +234,12 @@ namespace yask { return true; } - void YkGridBase::share_storage(yk_grid_ptr source) throw(yask_exception) { + void YkGridBase::share_storage(yk_grid_ptr source) { auto sp = dynamic_pointer_cast(source); assert(sp); if (!sp->get_raw_storage_buffer()) { - yask_exception e; - stringstream err; - err << "Error: share_storage() called without source storage allocated.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: share_storage() called without source storage allocated.\n"); } // NB: requirements to successful share_storage() is not as strict as @@ -270,16 +250,11 @@ namespace yask { // Same dims? if (sp->get_num_dims() != get_num_dims() || sp->get_dim_name(i) != dname) { - yask_exception e; - stringstream err; - err << "Error: share_storage() called with incompatible grids: "; + THROW_YASK_EXCEPTION("Error: share_storage() called with incompatible grids: "; print_info(cerr); err << "; and "; sp->print_info(cerr); - err << ".\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + err << ".\n"); } // Not a domain dim? @@ -288,14 +263,9 @@ namespace yask { auto tas = get_alloc_size(dname); auto sas = sp->get_alloc_size(dname); if (tas != sas) { - yask_exception e; - stringstream err; - err << "Error: attempt to share storage from grid '" << sp->get_name() << + THROW_YASK_EXCEPTION("Error: attempt to share storage from grid '" << sp->get_name() << "' of alloc-size " << sas << " with grid '" << get_name() << - "' of alloc-size " << tas << " in '" << dname << "' dim.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + "' of alloc-size " << tas << " in '" << dname << "' dim.\n"); } } @@ -304,14 +274,9 @@ namespace yask { auto tdom = get_rank_domain_size(dname); auto sdom = sp->get_rank_domain_size(dname); if (tdom != sdom) { - yask_exception e; - stringstream err; - err << "Error: attempt to share storage from grid '" << sp->get_name() << + THROW_YASK_EXCEPTION("Error: attempt to share storage from grid '" << sp->get_name() << "' of domain-size " << sdom << " with grid '" << get_name() << - "' of domain-size " << tdom << " in '" << dname << "' dim.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + "' of domain-size " << tdom << " in '" << dname << "' dim.\n"); } // Halo and pad sizes don't have to be the same. @@ -319,28 +284,18 @@ namespace yask { auto thalo = get_halo_size(dname); auto spad = sp->get_pad_size(dname); if (thalo > spad) { - yask_exception e; - stringstream err; - err << "Error: attempt to share storage from grid '" << sp->get_name() << + THROW_YASK_EXCEPTION("Error: attempt to share storage from grid '" << sp->get_name() << "' of padding-size " << spad << ", which is insufficient for grid '" << get_name() << - "' of halo-size " << thalo << " in '" << dname << "' dim.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + "' of halo-size " << thalo << " in '" << dname << "' dim.\n"); } } // Check folding. if (_vec_lens[i] != sp->_vec_lens[i]) { - yask_exception e; - stringstream err; - err << "Error: attempt to share storage from grid '" << sp->get_name() << + THROW_YASK_EXCEPTION("Error: attempt to share storage from grid '" << sp->get_name() << "' of fold-length " << sp->_vec_lens[i] << " with grid '" << get_name() << - "' of fold-length " << _vec_lens[i] << " in '" << dname << "' dim.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + "' of fold-length " << _vec_lens[i] << " in '" << dname << "' dim.\n"); } } @@ -357,12 +312,7 @@ namespace yask { // Copy data. release_storage(); if (!share_data(sp.get(), true)) { - yask_exception e; - stringstream err; - err << "Error: unexpected failure in data sharing.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: unexpected failure in data sharing.\n"); } } @@ -455,13 +405,8 @@ namespace yask { Indices* fixed_indices) const { auto n = get_num_dims(); if (indices.getNumDims() != n) { - yask_exception e; - stringstream err; - err << "Error: '" << fn << "' called with " << indices.getNumDims() << - " indices instead of " << n << ".\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: '" << fn << "' called with " << indices.getNumDims() << + " indices instead of " << n << ".\n"); } if (fixed_indices) *fixed_indices = indices; @@ -486,14 +431,9 @@ namespace yask { // Handle outliers. if (!ok) { if (strict_indices) { - yask_exception e; - stringstream err; - err << "Error: " << fn << ": index in dim '" << dname << + THROW_YASK_EXCEPTION("Error: " << fn << ": index in dim '" << dname << "' is " << idx << ", which is not in [" << first_ok << - "..." << last_ok << "].\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + "..." << last_ok << "].\n"); } if (fixed_indices) { if (idx < first_ok) @@ -538,15 +478,10 @@ namespace yask { } // API get/set. - double YkGridBase::get_element(const Indices& indices) const throw(yask_exception) { + double YkGridBase::get_element(const Indices& indices) const { if (!is_storage_allocated()) { - yask_exception e; - stringstream err; - err << "Error: call to 'get_element' with no data allocated for grid '" << - get_name() << "'.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: call to 'get_element' with no data allocated for grid '" << + get_name() << "'.\n"); } checkIndices(indices, "get_element", true, false); idx_t asi = get_alloc_step_index(indices[Indices::step_posn]); @@ -555,7 +490,7 @@ namespace yask { } idx_t YkGridBase::set_element(double val, const Indices& indices, - bool strict_indices) throw(yask_exception) { + bool strict_indices) { idx_t nup = 0; if (get_raw_storage_buffer() && checkIndices(indices, "set_element", strict_indices, false)) { @@ -571,15 +506,10 @@ namespace yask { idx_t YkGridBase::get_elements_in_slice(void* buffer_ptr, const Indices& first_indices, - const Indices& last_indices) const throw(yask_exception) { + const Indices& last_indices) const { if (!is_storage_allocated()) { - yask_exception e; - stringstream err; - err << "Error: call to 'get_elements_in_slice' with no data allocated for grid '" << - get_name() << "'.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: call to 'get_elements_in_slice' with no data allocated for grid '" << + get_name() << "'.\n"); } checkIndices(first_indices, "get_elements_in_slice", true, false); checkIndices(last_indices, "get_elements_in_slice", true, false); @@ -604,7 +534,7 @@ namespace yask { idx_t YkGridBase::set_elements_in_slice_same(double val, const Indices& first_indices, const Indices& last_indices, - bool strict_indices) throw(yask_exception) { + bool strict_indices) { if (!is_storage_allocated()) return 0; @@ -637,7 +567,7 @@ namespace yask { } idx_t YkGridBase::set_elements_in_slice(const void* buffer_ptr, const Indices& first_indices, - const Indices& last_indices) throw(yask_exception) { + const Indices& last_indices) { if (!is_storage_allocated()) return 0; checkIndices(first_indices, "set_elements_in_slice", true, false); diff --git a/src/kernel/lib/realv_grids.hpp b/src/kernel/lib/realv_grids.hpp index 432d4db4..5882bcfc 100644 --- a/src/kernel/lib/realv_grids.hpp +++ b/src/kernel/lib/realv_grids.hpp @@ -97,19 +97,20 @@ namespace yask { auto* tp = dynamic_cast(_ggb); if (!tp) { if (die_on_failure) { + //TODO: Use THROW_YASK_EXCEPTION MACRO yask_exception e; std::stringstream err; err << "Error in share_data(): " "target grid not of expected type (internal inconsistency).\n"; e.add_message(err.str()); throw e; - //exit_yask(1); } return false; } auto* sp = dynamic_cast(src->_ggb); if (!sp) { if (die_on_failure) { + //TODO: Use THROW_YASK_EXCEPTION MACRO yask_exception e; std::stringstream err; err << "Error in share_data(): source grid "; @@ -119,7 +120,6 @@ namespace yask { err << ".\n"; e.add_message(err.str()); throw e; - //exit_yask(1); } return false; } @@ -332,11 +332,11 @@ namespace yask { } #define GET_GRID_API(api_name) \ - virtual idx_t api_name(const std::string& dim) const throw(yask_exception); \ - virtual idx_t api_name(int posn) const throw(yask_exception); + virtual idx_t api_name(const std::string& dim) const; \ + virtual idx_t api_name(int posn) const; #define SET_GRID_API(api_name) \ - virtual void api_name(const std::string& dim, idx_t n) throw(yask_exception); \ - virtual void api_name(int posn, idx_t n) throw(yask_exception); + virtual void api_name(const std::string& dim, idx_t n); \ + virtual void api_name(int posn, idx_t n); // Settings that should never be exposed as APIs because // they can break the usage model. @@ -373,70 +373,70 @@ namespace yask { #undef GET_GRID_API #undef SET_GRID_API - virtual void set_all_elements_same(double val) throw(yask_exception) =0; - virtual double get_element(const Indices& indices) const throw(yask_exception); - virtual double get_element(const GridIndices& indices) const throw(yask_exception) { + virtual void set_all_elements_same(double val) =0; + virtual double get_element(const Indices& indices) const; + virtual double get_element(const GridIndices& indices) const { const Indices indices2(indices); return get_element(indices2); } - virtual double get_element(const std::initializer_list& indices) const throw(yask_exception) { + virtual double get_element(const std::initializer_list& indices) const { const Indices indices2(indices); return get_element(indices2); } virtual idx_t get_elements_in_slice(void* buffer_ptr, const Indices& first_indices, - const Indices& last_indices) const throw(yask_exception); + const Indices& last_indices) const; virtual idx_t get_elements_in_slice(void* buffer_ptr, const GridIndices& first_indices, - const GridIndices& last_indices) const throw(yask_exception) { + const GridIndices& last_indices) const { const Indices first(first_indices); const Indices last(last_indices); return get_elements_in_slice(buffer_ptr, first, last); } virtual idx_t set_element(double val, const Indices& indices, - bool strict_indices = false) throw(yask_exception); + bool strict_indices = false); virtual idx_t set_element(double val, const GridIndices& indices, - bool strict_indices = false) throw(yask_exception) { + bool strict_indices = false) { const Indices indices2(indices); return set_element(val, indices2, strict_indices); } virtual idx_t set_element(double val, const std::initializer_list& indices, - bool strict_indices = false) throw(yask_exception) { + bool strict_indices = false) { const Indices indices2(indices); return set_element(val, indices2, strict_indices); } virtual idx_t set_elements_in_slice_same(double val, const Indices& first_indices, const Indices& last_indices, - bool strict_indices) throw(yask_exception); + bool strict_indices); virtual idx_t set_elements_in_slice_same(double val, const GridIndices& first_indices, const GridIndices& last_indices, - bool strict_indices) throw(yask_exception) { + bool strict_indices) { const Indices first(first_indices); const Indices last(last_indices); return set_elements_in_slice_same(val, first, last, strict_indices); } virtual idx_t set_elements_in_slice(const void* buffer_ptr, const Indices& first_indices, - const Indices& last_indices) throw(yask_exception); + const Indices& last_indices); virtual idx_t set_elements_in_slice(const void* buffer_ptr, const GridIndices& first_indices, - const GridIndices& last_indices) throw(yask_exception) { + const GridIndices& last_indices) { const Indices first(first_indices); const Indices last(last_indices); return set_elements_in_slice(buffer_ptr, first, last); } - virtual void alloc_storage() throw(yask_exception) { + virtual void alloc_storage() { _ggb->default_alloc(); } - virtual void release_storage() throw(yask_exception) { + virtual void release_storage() { _ggb->release_storage(); } - virtual void share_storage(yk_grid_ptr source) throw(yask_exception); + virtual void share_storage(yk_grid_ptr source); virtual bool is_storage_allocated() const { return _ggb->get_storage() != 0; } @@ -446,7 +446,7 @@ namespace yask { virtual idx_t get_num_storage_elements() const { return _allocs.product(); } - virtual bool is_storage_layout_identical(const yk_grid_ptr other) const throw(yask_exception); + virtual bool is_storage_layout_identical(const yk_grid_ptr other) const; virtual void* get_raw_storage_buffer() { return _ggb->get_storage(); } @@ -492,7 +492,7 @@ namespace yask { } // Init data. - virtual void set_all_elements_same(double seed) throw(yask_exception) { + virtual void set_all_elements_same(double seed) { _data.set_elems_same(seed); set_dirty_all(true); } @@ -639,7 +639,7 @@ namespace yask { } // Init data. - virtual void set_all_elements_same(double seed) throw(yask_exception) { + virtual void set_all_elements_same(double seed) { real_vec_t seedv = seed; // bcast. _data.set_elems_same(seedv); set_dirty_all(true); diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index 03f8a7c6..f04eda4a 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -38,40 +38,25 @@ namespace yask { return; if (dim == _step_dim) { if (!step_ok) { - yask_exception e; - stringstream err; - err << "Error in " << fn_name << "(): dimension '" << - dim << "' is the step dimension, which is not allowed.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error in " << fn_name << "(): dimension '" << + dim << "' is the step dimension, which is not allowed.\n"); } } else if (_domain_dims.lookup(dim)) { if (!domain_ok) { - yask_exception e; - stringstream err; - err << "Error in " << fn_name << "(): dimension '" << - dim << "' is a domain dimension, which is not allowed.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error in " << fn_name << "(): dimension '" << + dim << "' is a domain dimension, which is not allowed.\n"); } } else if (!misc_ok) { - yask_exception e; - stringstream err; - err << "Error in " << fn_name << "(): dimension '" << - dim << "' is a misc dimension, which is not allowed.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error in " << fn_name << "(): dimension '" << + dim << "' is a misc dimension, which is not allowed.\n"); } } // APIs. // See yask_kernel_api.hpp. - yk_env_ptr yk_factory::new_env() const throw(yask_exception) { + yk_env_ptr yk_factory::new_env() const { auto ep = make_shared(); assert(ep); ep->initEnv(0, 0); diff --git a/src/kernel/lib/utils.cpp b/src/kernel/lib/utils.cpp index 10126deb..40eb3000 100644 --- a/src/kernel/lib/utils.cpp +++ b/src/kernel/lib/utils.cpp @@ -54,12 +54,7 @@ namespace yask { #endif if (!p) { - yask_exception e; - stringstream err; - err << "error: cannot allocate " << makeByteStr(nbytes) << ".\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("error: cannot allocate " << makeByteStr(nbytes) << ".\n"); } return static_cast(p); } @@ -147,13 +142,8 @@ namespace yask { #endif if (min_val != rank_val || max_val != rank_val) { - yask_exception e; - stringstream err; - err << "error: " << descr << " values range from " << min_val << " to " << - max_val << " across the ranks. They should all be identical." << endl; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("error: " << descr << " values range from " << min_val << " to " << + max_val << " across the ranks. They should all be identical." << endl); } } @@ -219,24 +209,14 @@ namespace yask { int& argi) { if (size_t(argi) >= args.size() || args[argi].length() == 0) { - yask_exception e; - stringstream err; - err << "Error: no argument for option '" << args[argi - 1] << "'." << endl; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: no argument for option '" << args[argi - 1] << "'." << endl); } const char* nptr = args[argi].c_str(); char* endptr = 0; long long int val = strtoll(nptr, &endptr, 0); if (val == LLONG_MIN || val == LLONG_MAX || *endptr != '\0') { - yask_exception e; - stringstream err; - err << "Error: argument for option '" << args[argi - 1] << "' is not an integer." << endl; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("Error: argument for option '" << args[argi - 1] << "' is not an integer." << endl); } argi++; diff --git a/src/kernel/swig/yask_kernel_api.i b/src/kernel/swig/yask_kernel_api.i index a49f5398..a4a200aa 100644 --- a/src/kernel/swig/yask_kernel_api.i +++ b/src/kernel/swig/yask_kernel_api.i @@ -57,6 +57,15 @@ IN THE SOFTWARE. %template(vector_idx) std::vector; %template(vector_str) std::vector; %template(vector_grid_ptr) std::vector>; - + +%exception { + try { + $action + } catch (yask::yask_exception &e) { + PyErr_SetString(PyExc_RuntimeError, const_cast(e.get_message())); + SWIG_fail; + } +} + %include "yask_common_api.hpp" %include "yask_kernel_api.hpp" diff --git a/src/kernel/tests/yask_kernel_api_exception_test.cpp b/src/kernel/tests/yask_kernel_api_exception_test.cpp index e5914a3c..253bc39e 100644 --- a/src/kernel/tests/yask_kernel_api_exception_test.cpp +++ b/src/kernel/tests/yask_kernel_api_exception_test.cpp @@ -77,24 +77,24 @@ int main() { // Exception test cout << "Exception Test: Call 'run_solution' without calling prepare_solution().\n"; try { - soln->run_solution(0); + soln->run_solution(0); } catch (yask_exception e) { - cout << "YASK throws an exception.\n"; - cout << e.get_message(); - cout << "Exception Test: Catch exception correctly.\n"; - num_exception++; - } + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } // Exception test cout << "Exception Test: Call 'run_auto_tuner_now' without calling prepare_solution().\n"; try { - soln->run_auto_tuner_now(false); + soln->run_auto_tuner_now(false); } catch (yask_exception e) { - cout << "YASK throws an exception.\n"; - cout << e.get_message(); - cout << "Exception Test: Catch exception correctly.\n"; - num_exception++; - } + cout << "YASK throws an exception.\n"; + cout << e.get_message(); + cout << "Exception Test: Catch exception correctly.\n"; + num_exception++; + } // Allocate memory for any grids that do not have storage set. @@ -223,7 +223,7 @@ int main() { exit(1); } else - cout << "End of YASK kernel API test with exception.\n"; + cout << "End of YASK kernel API test with exception.\n"; return 0; } From 9dfbfff29223f66e2159f9031cd7324255a72ed9 Mon Sep 17 00:00:00 2001 From: Chuck Yount Date: Tue, 30 Jan 2018 14:08:36 -0700 Subject: [PATCH 6/7] Remove gratuitous added space. --- src/compiler/lib/Soln.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/lib/Soln.hpp b/src/compiler/lib/Soln.hpp index 76d7fd4f..38dad0f1 100644 --- a/src/compiler/lib/Soln.hpp +++ b/src/compiler/lib/Soln.hpp @@ -167,7 +167,7 @@ namespace yask { virtual void set_element_bytes(int nbytes) { _settings._elem_bytes = nbytes; } virtual int get_element_bytes() const { return _settings._elem_bytes; } virtual void format(const std::string& format_type, - yask_output_ptr output) ; + yask_output_ptr output); }; // A stencil solution that does not define any grids. From eb32c1bff4282559756acf220709870a3a2e701f Mon Sep 17 00:00:00 2001 From: Joonmoo Huh Date: Tue, 30 Jan 2018 15:45:52 -0700 Subject: [PATCH 7/7] Move out yask exception macro from api.hpp. Update minor version --- include/yask_common_api.hpp | 8 -------- src/common/common_utils.cpp | 2 +- src/common/common_utils.hpp | 41 +++++++++++++++++++++++++++++++++++++ src/common/output.cpp | 4 ++++ src/compiler/lib/Expr.hpp | 2 ++ src/kernel/lib/settings.cpp | 7 +------ src/kernel/lib/yask.hpp | 3 +++ 7 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 src/common/common_utils.hpp diff --git a/include/yask_common_api.hpp b/include/yask_common_api.hpp index c4ca0b2a..cce4c80a 100644 --- a/include/yask_common_api.hpp +++ b/include/yask_common_api.hpp @@ -90,14 +90,6 @@ namespace yask { const char* get_message(); }; - /// MACRO for throw yask_exception -#define THROW_YASK_EXCEPTION(message) \ - yask_exception e; \ - stringstream err; \ - err << message; \ - e.add_message(err.str()); \ - throw e; \ - /// Factory to create output objects. class yask_output_factory { public: diff --git a/src/common/common_utils.cpp b/src/common/common_utils.cpp index 22a91ccf..dd02bd25 100644 --- a/src/common/common_utils.cpp +++ b/src/common/common_utils.cpp @@ -41,7 +41,7 @@ namespace yask { // for numbers above 9 (at least up to 99). // Format: "major.minor.patch". - const string version = "2.01.10"; + const string version = "2.02.00"; string yask_get_version_string() { return version; diff --git a/src/common/common_utils.hpp b/src/common/common_utils.hpp new file mode 100644 index 00000000..2e57360e --- /dev/null +++ b/src/common/common_utils.hpp @@ -0,0 +1,41 @@ +/***************************************************************************** + +YASK: Yet Another Stencil Kernel +Copyright (c) 2014-2018, Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +*****************************************************************************/ +#ifndef COMMON_UTILS_HPP +#define COMMON_UTILS_HPP + +namespace yask { + +// MACRO for throw yask_exception +#define THROW_YASK_EXCEPTION(message) \ + yask_exception e; \ + stringstream err; \ + err << message; \ + e.add_message(err.str()); \ + throw e; \ + + +} // namespace yask. + +#endif /* SRC_COMMON_COMMON_UTILS_HPP_ */ diff --git a/src/common/output.cpp b/src/common/output.cpp index 98a3c61f..20f8c6be 100644 --- a/src/common/output.cpp +++ b/src/common/output.cpp @@ -26,6 +26,10 @@ IN THE SOFTWARE. //////// Methods for output object. ////////// #include "yask_common_api.hpp" + +// Common utilities. +#include "common_utils.hpp" + #include #include #include diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index 1d0aece3..c729a8b3 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -40,6 +40,8 @@ IN THE SOFTWARE. #include #include +// Common utilities. +#include "common_utils.hpp" #include "tuple.hpp" using namespace std; diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index f04eda4a..26c0f599 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -80,12 +80,7 @@ namespace yask { int provided = 0; MPI_Init_thread(argc, argv, MPI_THREAD_SERIALIZED, &provided); if (provided < MPI_THREAD_SERIALIZED) { - yask_exception e; - stringstream err; - err << "error: MPI_THREAD_SERIALIZED not provided.\n"; - e.add_message(err.str()); - throw e; - //exit_yask(1); + THROW_YASK_EXCEPTION("error: MPI_THREAD_SERIALIZED not provided.\n"); } is_init = true; } diff --git a/src/kernel/lib/yask.hpp b/src/kernel/lib/yask.hpp index 506f17ee..751ed2fc 100644 --- a/src/kernel/lib/yask.hpp +++ b/src/kernel/lib/yask.hpp @@ -34,6 +34,9 @@ IN THE SOFTWARE. // Include the API first. This helps to ensure that it will stand alone. #include "yask_kernel_api.hpp" +// Common utilities. +#include "common_utils.hpp" + // Additional type for unsigned indices. typedef std::uint64_t uidx_t;