From 1120cc25b84e2dfdf2509baaa67d4196f359088c Mon Sep 17 00:00:00 2001 From: "Yount, Chuck" Date: Mon, 21 Nov 2022 16:20:36 -0800 Subject: [PATCH 1/3] Fix C++ kernel test to work on >1 rank. --- src/common/common_utils.cpp | 2 +- src/kernel/Makefile | 10 ++- src/kernel/lib/yk_var.hpp | 36 ++++++--- src/kernel/tests/yask_kernel_api_test.cpp | 97 +++++++++++++---------- 4 files changed, 87 insertions(+), 58 deletions(-) diff --git a/src/common/common_utils.cpp b/src/common/common_utils.cpp index 65d7085f..7ce586ad 100644 --- a/src/common/common_utils.cpp +++ b/src/common/common_utils.cpp @@ -43,7 +43,7 @@ namespace yask { // for numbers above 9 (at least up to 99). // Format: "major.minor.patch[-alpha|-beta]". - const string version = "4.00.02"; + const string version = "4.00.03"; string yask_get_version_string() { return version; diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 05f801b6..38c83aa3 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -965,10 +965,12 @@ $(YK_API_TEST_EXEC): $(YK_TEST_SRC_DIR)/yask_kernel_api_test.cpp $(YK_LIB) @ls -l $@ # Build and run C++ tests. +# First run on 1 rank, then multiple ranks if ranks>1. cxx-yk-api-test: $(TEST_MAKE) $(YK_API_TEST_EXEC) allow_new_var_types=1 @echo '*** Running the C++ YASK kernel API test...' $(RUN_PREFIX) $(YK_API_TEST_EXEC) + if (( $(ranks) > 1 )); then $(RUN_PREFIX) mpirun -np $(ranks) $(YK_API_TEST_EXEC); fi # Run Python kernel API test. py-yk-api-test: $(YK_TEST_SRC_DIR)/yask_kernel_api_test.py $(YK_PY_LIB) @@ -1063,10 +1065,10 @@ yk-test-no-yc: kernel-no-yc $(YK_SCRIPT) # Run the kernel API tests for C++ and Python with and w/o expected exceptions. api-tests: - $(MAKE) clean; $(MAKE) cxx-yk-api-test real_bytes=8 stencil=iso3dfd - $(MAKE) clean; $(MAKE) py-yk-api-test stencil=iso3dfd - $(MAKE) clean; $(MAKE) cxx-yk-api-test-with-exception real_bytes=8 stencil=iso3dfd - $(MAKE) clean; $(MAKE) py-yk-api-test-with-exception stencil=iso3dfd + $(MAKE) clean; $(MAKE) cxx-yk-api-test real_bytes=8 + $(MAKE) clean; $(MAKE) py-yk-api-test + $(MAKE) clean; $(MAKE) cxx-yk-api-test-with-exception real_bytes=8 + $(MAKE) clean; $(MAKE) py-yk-api-test-with-exception # Run several stencils using built-in validation. # NB: set arch var as applicable. diff --git a/src/kernel/lib/yk_var.hpp b/src/kernel/lib/yk_var.hpp index 0582e5da..45733b1d 100644 --- a/src/kernel/lib/yk_var.hpp +++ b/src/kernel/lib/yk_var.hpp @@ -654,7 +654,11 @@ namespace yask { // Find sizes needed for slicing. inline Indices get_slice_range(const Indices& first_indices, const Indices& last_indices) const { - return last_indices.add_const(1).sub_elements(first_indices); + host_assert(first_indices.get_num_dims() == last_indices.get_num_dims()); + Indices range = first_indices; + for (int i = 0; i < first_indices.get_num_dims(); i++) + range[i] = std::max(idx_t(0), last_indices[i] + 1 - first_indices[i]); + return range; } // Accessors to GenericVar. @@ -955,8 +959,8 @@ namespace yask { template idx_t _visit_elements_in_slice(bool strict_indices, void* buffer_ptr, - const Indices& first_indices, - const Indices& last_indices, + const Indices& in_first_indices, + const Indices& in_last_indices, bool on_device) { STATE_VARS(this); if (get_storage() == 0) { @@ -969,11 +973,17 @@ namespace yask { } TRACE_MSG(Visitor::fname() << ": " << make_info_string() << " [" << - make_index_string(first_indices) << " ... " << - make_index_string(last_indices) << "] with buffer at " << + make_index_string(in_first_indices) << " ... " << + make_index_string(in_last_indices) << "] with buffer at " << buffer_ptr << " on " << (on_device ? "OMP device" : "host")); - check_indices(first_indices, Visitor::fname(), strict_indices, true, false); - check_indices(last_indices, Visitor::fname(), strict_indices, true, false); + Indices first_indices, last_indices; + check_indices(in_first_indices, Visitor::fname(), strict_indices, + true, false, &first_indices); + check_indices(in_last_indices, Visitor::fname(), strict_indices, + true, false, &last_indices); + TRACE_MSG(Visitor::fname() << ": clipped to [" << + make_index_string(first_indices) << " ... " << + make_index_string(last_indices) << "]"); // Find range. auto range = get_slice_range(first_indices, last_indices); @@ -1927,31 +1937,31 @@ namespace yask { } virtual idx_t set_element(double val, const Indices& indices, - bool strict_indices = false); + bool strict_indices); virtual idx_t set_element(double val, const VarIndices& indices, - bool strict_indices = false) { + bool strict_indices) { const Indices indices2(indices); return set_element(val, indices2, strict_indices); } virtual idx_t set_element(double val, const idx_t_init_list& indices, - bool strict_indices = false) { + bool strict_indices) { const Indices indices2(indices); return set_element(val, indices2, strict_indices); } virtual idx_t add_to_element(double val, const Indices& indices, - bool strict_indices = false); + bool strict_indices); virtual idx_t add_to_element(double val, const VarIndices& indices, - bool strict_indices = false) { + bool strict_indices) { const Indices indices2(indices); return add_to_element(val, indices2, strict_indices); } virtual idx_t add_to_element(double val, const idx_t_init_list& indices, - bool strict_indices = false) { + bool strict_indices) { const Indices indices2(indices); return add_to_element(val, indices2, strict_indices); } diff --git a/src/kernel/tests/yask_kernel_api_test.cpp b/src/kernel/tests/yask_kernel_api_test.cpp index 101cf43c..3a3fb7e4 100644 --- a/src/kernel/tests/yask_kernel_api_test.cpp +++ b/src/kernel/tests/yask_kernel_api_test.cpp @@ -36,23 +36,30 @@ IN THE SOFTWARE. using namespace std; using namespace yask; -int main() { - - // The factory from which all other kernel objects are made. - yk_factory kfac; - - // Initalize MPI, etc. - auto env = kfac.new_env(); +int main(int argc, char** argv) { + int rank_num = -1; try { + // The factory from which all other kernel objects are made. + yk_factory kfac; + + // Initalize MPI, etc. + auto env = kfac.new_env(); + rank_num = env->get_rank_index(); + + // Local options. + for (int i = 1; i < argc; i++) + if (string(argv[i]) == "-trace") + env->set_trace_enabled(true); + // Create solution. auto soln = kfac.new_solution(env); + // Apply any YASK command-line options. + soln->apply_command_line_options(argc, argv); + // Show output only from last rank. - // This is an example of using the rank APIs, - // the yask_output_factory, and set_debug_output(). - int rank_num = env->get_rank_index(); if (rank_num < env->get_num_ranks() - 1) { yk_env::disable_debug_output(); cout << "Suppressing output on rank " << rank_num << ".\n"; @@ -187,7 +194,7 @@ int main() { continue; // Create indices describing a subset of the overall domain. - vector first_indices, last_indices; + vector first_cube_indices, last_cube_indices; for (auto dname : var->get_dim_names()) { idx_t first_idx = 0, last_idx = 0; @@ -222,61 +229,69 @@ int main() { } // Add indices to index vectors. - first_indices.push_back(first_idx); - last_indices.push_back(last_idx); + first_cube_indices.push_back(first_idx); + last_cube_indices.push_back(last_idx); } - assert(first_indices.size() == ndims); - assert(last_indices.size() == ndims); + assert(first_cube_indices.size() == ndims); + assert(last_cube_indices.size() == ndims); // Print range of inner cube. if (ndims == 0) os << " inner-cube is a single point for this scalar var.\n"; else os << " range of inner-cube: " << - var->format_indices(first_indices) << " to " << - var->format_indices(last_indices) << ".\n"; + var->format_indices(first_cube_indices) << " to " << + var->format_indices(last_cube_indices) << ".\n"; // Check 2 corners of inner-cube to make sure they were set properly. - if (var->are_indices_local(first_indices)) { - auto val2 = var->get_element(first_indices); + if (var->are_indices_local(first_cube_indices)) { + auto val2 = var->get_element(first_cube_indices); os << " first element in inner cube == " << val2 << ".\n"; assert(val2 == outer_val); } else - os << " first element NOT in rank.\n"; - if (var->are_indices_local(last_indices)) { - auto val2 = var->get_element(last_indices); + os << " first element NOT in this rank.\n"; + if (var->are_indices_local(last_cube_indices)) { + auto val2 = var->get_element(last_cube_indices); os << " last element in inner cube == " << val2 << ".\n"; assert(val2 == outer_val); } else - os << " last element NOT in rank.\n"; + os << " last element NOT in this rank.\n"; // Re-init the values in the inner cube using the indices created above. + // Use 'strict_indices = false' because first/last_cube_indices are global, + // so part or all of cube may be outside this rank. double inner_val = 2.0; - bool strict_indices = false; // because first/last_indices are global. - idx_t nset = var->set_elements_in_slice_same(inner_val, first_indices, last_indices, strict_indices); + bool strict_indices = false; + idx_t nset = var->set_elements_in_slice_same(inner_val, first_cube_indices, + last_cube_indices, strict_indices); os << " " << nset << " element(s) in inner-cube set to " << inner_val << ".\n"; - // Check values on 2 corners of the inner cube to make sure they were set properly. - if (var->are_indices_local(first_indices)) { - auto val2 = var->get_element(first_indices); + // Check values on 2 corners of the inner cube to make sure they + // were set properly. Only check if element is in this rank. + if (var->are_indices_local(first_cube_indices)) { + auto val2 = var->get_element(first_cube_indices); os << " first element in inner cube == " << val2 << ".\n"; assert(val2 == inner_val); } - if (var->are_indices_local(last_indices)) { - auto val2 = var->get_element(last_indices); + if (var->are_indices_local(last_cube_indices)) { + auto val2 = var->get_element(last_cube_indices); os << " last element in inner cube == " << val2 << ".\n"; assert(val2 == inner_val); } - // Add to value in first corner of the inner cube if it's in this rank. - nset = var->add_to_element(1.0, first_indices); - os << " " << nset << " element(s) updated.\n"; - - // Check to make sure they were updated. - if (var->are_indices_local(first_indices)) { - auto val2 = var->get_element(first_indices); + // Add to value in first corner of the inner cube if it's in + // this rank. Here, we can use the default 'strict_indices = + // true' parameter to add_to_element() because the call is + // inside the check for local indices. + if (var->are_indices_local(first_cube_indices)) { + nset = var->add_to_element(1.0, first_cube_indices); + os << " " << nset << " element(s) updated.\n"; + assert(nset == 1); + + // Check to make sure they were updated. + auto val2 = var->get_element(first_cube_indices); os << " first element in inner cube == " << val2 << ".\n"; assert(val2 == inner_val + 1.0); } @@ -295,19 +310,21 @@ int main() { // Apply the stencil solution to the data. soln->reset_auto_tuner(false); env->global_barrier(); - os << "Running the solution for 1 step...\n"; + os << "Running the solution on " << env->get_num_ranks() << " rank(s)...\n"; + os << "Running for 1 step...\n"; soln->run_solution(0); - os << "Running the solution for 4 more steps...\n"; + os << "Running for 4 more steps...\n"; soln->run_solution(1, 4); soln->end_solution(); soln->get_stats(); + env->global_barrier(); os << "End of YASK kernel API test.\n"; return 0; } catch (yask_exception e) { cerr << "YASK kernel API test: " << e.get_message() << - " on rank " << env->get_rank_index() << ".\n"; + " on rank " << rank_num << ".\n"; return 1; } } From f8bfab2e82c95a2c97e8859d9406861318bdee84 Mon Sep 17 00:00:00 2001 From: "Yount, Chuck" Date: Tue, 22 Nov 2022 11:34:44 -0800 Subject: [PATCH 2/3] Add yk_env::finalize() API. Call from yask_main.cpp and all API tests. --- .../html/classyask_1_1yk__env-members.html | 17 +++++---- docs/api/html/classyask_1_1yk__env.html | 31 ++++++++++++++++ docs/api/html/functions_f.html | 5 ++- docs/api/html/functions_func_f.html | 5 ++- docs/api/html/search/all_6.js | 1 + docs/api/html/search/functions_6.js | 1 + .../html/yask__kernel__api_8hpp_source.html | 7 ++-- docs/api/html/yk__var__api_8hpp_source.html | 2 +- include/yask_kernel_api.hpp | 12 ++++++ src/kernel/Makefile | 2 + src/kernel/lib/settings.hpp | 15 +++++++- src/kernel/lib/setup.cpp | 1 + src/kernel/tests/var_test.cpp | 1 + .../tests/yask_kernel_api_exception_test.cpp | 3 +- .../tests/yask_kernel_api_exception_test.py | 5 ++- src/kernel/tests/yask_kernel_api_test.cpp | 4 +- src/kernel/tests/yask_kernel_api_test.py | 37 ++++++++++++------- src/kernel/yask_main.cpp | 2 +- 18 files changed, 117 insertions(+), 34 deletions(-) diff --git a/docs/api/html/classyask_1_1yk__env-members.html b/docs/api/html/classyask_1_1yk__env-members.html index acc16f7c..84a18bc0 100644 --- a/docs/api/html/classyask_1_1yk__env-members.html +++ b/docs/api/html/classyask_1_1yk__env-members.html @@ -74,14 +74,15 @@

This is the complete list of members for yask::yk_env, including all inherited members.

- - - - - - - - + + + + + + + + +
disable_debug_output()yask::yk_envstatic
get_debug_output()yask::yk_envstatic
get_num_ranks() const =0yask::yk_envpure virtual
get_rank_index() const =0yask::yk_envpure virtual
global_barrier() const =0yask::yk_envpure virtual
is_trace_enabled()yask::yk_envstatic
set_debug_output(yask_output_ptr debug)yask::yk_envstatic
set_trace_enabled(bool enable)yask::yk_envstatic
~yk_env() (defined in yask::yk_env)yask::yk_envinlinevirtual
finalize()=0yask::yk_envpure virtual
get_debug_output()yask::yk_envstatic
get_num_ranks() const =0yask::yk_envpure virtual
get_rank_index() const =0yask::yk_envpure virtual
global_barrier() const =0yask::yk_envpure virtual
is_trace_enabled()yask::yk_envstatic
set_debug_output(yask_output_ptr debug)yask::yk_envstatic
set_trace_enabled(bool enable)yask::yk_envstatic
~yk_env() (defined in yask::yk_env)yask::yk_envinlinevirtual