Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime debug information #679

Merged
merged 6 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Define project version and use via generated config header
project(ngen VERSION 0.1.0)

configure_file("${NGEN_INC_DIR}/NGenConfig.h.in" "${NGEN_INC_DIR}/NGenConfig.h")

add_executable(ngen "${NGEN_SRC_DIR}/NGen.cpp")

# Dependencies ================================================================
Expand Down Expand Up @@ -245,19 +243,23 @@ endif()
# -----------------------------------------------------------------------------

# Syntax: ngen_multiline_message("<message 1>" "<message 2>" ...)
function(ngen_multiline_message)
macro(ngen_multiline_message)
set(messages "${ARGN}")
foreach(msg IN LISTS messages)
set(_CONF "${NGEN_CONF_SUMMARY}")
string(APPEND _CONF "${msg}\n")
set(NGEN_CONF_SUMMARY "${_CONF}")

message(STATUS "${msg}")
endforeach()
endfunction()
endmacro()

# Syntax: ngen_dependent_multiline_message(<variable> "<message 1>" "<message 2>" ...)
function(ngen_dependent_multiline_message VARIABLE)
macro(ngen_dependent_multiline_message VARIABLE)
if(${VARIABLE})
ngen_multiline_message(${ARGN})
endif()
endfunction()
endmacro()

# This is used purely for configuration output,
# and does not affect the virtual environment used.
Expand Down Expand Up @@ -311,6 +313,7 @@ ngen_dependent_multiline_message(NGEN_WITH_MPI
" Include: ${MPI_CXX_INCLUDE_DIRS}")
ngen_dependent_multiline_message(NGEN_WITH_NETCDF
" NetCDF:"
" Version: ${NETCDF_VERSION}"
" Library: ${NETCDF_LIBRARY}"
" Library (CXX): ${NETCDF_CXX_LIBRARIES}"
" Include: ${NETCDF_INCLUDE_DIR}"
Expand Down Expand Up @@ -343,3 +346,5 @@ ngen_dependent_multiline_message(NGEN_WITH_PYTHON
" pybind11 Version: ${pybind11_VERSION}"
" pybind11 Include: ${pybind11_INCLUDE_DIR}")
message(STATUS "---------------------------------------------------------------------")

configure_file("${NGEN_INC_DIR}/NGenConfig.h.in" "${NGEN_INC_DIR}/NGenConfig.h")
20 changes: 18 additions & 2 deletions cmake/FindNetCDF.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,27 @@ list (APPEND NetCDF_libs "${NETCDF_C_LIBRARIES}")
set (NETCDF_LIBRARIES ${NetCDF_libs})
set (NETCDF_INCLUDE_DIRS ${NetCDF_includes})

if(NETCDF_C_INCLUDE_DIRS)
file(STRINGS "${NETCDF_C_INCLUDE_DIRS}/netcdf_meta.h" _netcdf_ver
REGEX "#define[ \t]+NC_VERSION_(MAJOR|MINOR|PATCH|NOTE)")

string(REGEX REPLACE ".*NC_VERSION_MAJOR *\([0-9]*\).*" "\\1" _netcdf_version_major "${_netcdf_ver}")
string(REGEX REPLACE ".*NC_VERSION_MINOR *\([0-9]*\).*" "\\1" _netcdf_version_minor "${_netcdf_ver}")
string(REGEX REPLACE ".*NC_VERSION_PATCH *\([0-9]*\).*" "\\1" _netcdf_version_patch "${_netcdf_ver}")
string(REGEX REPLACE ".*NC_VERSION_NOTE *\"\([^\"]*\)\".*" "\\1" _netcdf_version_note "${_netcdf_ver}")
set(NETCDF_VERSION "${_netcdf_version_major}.${_netcdf_version_minor}.${_netcdf_version_patch}${_netcdf_version_note}")
unset(_netcdf_version_major)
unset(_netcdf_version_minor)
unset(_netcdf_version_patch)
unset(_netcdf_version_note)
unset(_netcdf_version_lines)
endif()

# handle the QUIETLY and REQUIRED arguments and set NETCDF_FOUND to TRUE if
# all listed variables are TRUE
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (NetCDF
DEFAULT_MSG NETCDF_LIBRARIES NETCDF_INCLUDE_DIRS NETCDF_HAS_INTERFACES)
find_package_handle_standard_args(NetCDF
DEFAULT_MSG NETCDF_LIBRARIES NETCDF_INCLUDE_DIRS NETCDF_HAS_INTERFACES NETCDF_VERSION)

function(FindNetCDF_get_is_parallel_aware include_dir)
file(STRINGS "${include_dir}/netcdf_meta.h" _netcdf_lines
Expand Down
49 changes: 49 additions & 0 deletions include/NGenConfig.h.in
Original file line number Diff line number Diff line change
@@ -1,8 +1,57 @@
#ifndef NGEN_NGENCONFIG_H
#define NGEN_NGENCONFIG_H

#define NGEN_STRINGIFY(x) #x
#define NGEN_STRING(x) NGEN_STRINGIFY(x)

#define ngen_VERSION_MAJOR @ngen_VERSION_MAJOR@
#define ngen_VERSION_MINOR @ngen_VERSION_MINOR@
#define ngen_VERSION_PATCH @ngen_VERSION_PATCH@
#define ngen_VERSION NGEN_STRING(ngen_VERSION_MAJOR.ngen_VERSION_MINOR.ngen_VERSION_PATCH)

#cmakedefine01 NGEN_WITH_MPI
#cmakedefine01 NGEN_WITH_NETCDF
#cmakedefine01 NGEN_WITH_SQLITE
#cmakedefine01 NGEN_WITH_UDUNITS
#cmakedefine01 NGEN_WITH_BMI_FORTRAN
#cmakedefine01 NGEN_WITH_BMI_C
#cmakedefine01 NGEN_WITH_PYTHON
#cmakedefine01 NGEN_WITH_ROUTING
#cmakedefine01 NGEN_WITH_TESTS
#cmakedefine01 NGEN_QUIET

#include <string>

namespace ngen {

namespace exec_info
{
// Executable version

static constexpr const char* version = ngen_VERSION;

// Compile-time feature flags

static constexpr bool with_mpi = NGEN_WITH_MPI;
static constexpr bool with_netcdf = NGEN_WITH_NETCDF;
static constexpr bool with_sqlite = NGEN_WITH_SQLITE;
static constexpr bool with_udunits = NGEN_WITH_UDUNITS;
static constexpr bool with_bmi_fortran = NGEN_WITH_BMI_FORTRAN;
static constexpr bool with_bmi_c = NGEN_WITH_BMI_C;
static constexpr bool with_python = NGEN_WITH_PYTHON;
static constexpr bool with_routing = NGEN_WITH_ROUTING;
static constexpr bool with_quiet = NGEN_QUIET;

//! Compile-time build summary
static constexpr const char* build_summary = R"(@NGEN_CONF_SUMMARY@)";

void runtime_summary(std::ostream& stream) noexcept;
void runtime_usage(const std::string& cmd, std::ostream& stream) noexcept;
};

} // namespace ngen

#undef NGEN_STRING
#undef NGEN_STRINGIFY

#endif //NGEN_NGENCONFIG_H
1 change: 1 addition & 0 deletions include/core/nexus/HY_PointHydroNexusRemote.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <unordered_map>
#include <string>
#include <list>
PhilMiller marked this conversation as resolved.
Show resolved Hide resolved


/** This class representa a point nexus that can have both upstream and downstream connections to catments that are
Expand Down
94 changes: 94 additions & 0 deletions src/NGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#endif // WRITE_PID_FILE_FOR_GDB_SERVER

#ifdef ACTIVATE_PYTHON
#include <pybind11/embed.h>
#include "python/InterpreterUtil.hpp"
#endif // ACTIVATE_PYTHON

Expand Down Expand Up @@ -57,7 +58,100 @@ int mpi_num_procs;

std::unordered_map<std::string, std::ofstream> nexus_outfiles;

void ngen::exec_info::runtime_summary(std::ostream& stream) noexcept
{
stream << "Runtime configuration summary:\n";

#if NGEN_WITH_MPI
stream << " MPI:\n"
<< " Rank: " << mpi_rank << "\n"
<< " Processors: " << mpi_num_procs << "\n";
program-- marked this conversation as resolved.
Show resolved Hide resolved
#endif // NGEN_WITH_MPI

#if NGEN_WITH_PYTHON // -------------------------------------------------------
{ // START RAII
py::scoped_interpreter guard{};

auto sys = py::module_::import("sys");
auto sysconfig = py::module_::import("sysconfig");

// try catch
py::module_ numpy;
bool imported_numpy = false;
std::string err;
try {
numpy = py::module_::import("numpy");
imported_numpy = true;
} catch(py::error_already_set& e) {
err = e.what();
PhilMiller marked this conversation as resolved.
Show resolved Hide resolved
}

// Lambda to convert py::dict -> std::unordered_map<std::string, std::string>
const auto dict_to_map = [](const py::dict& dict) -> std::unordered_map<std::string, std::string> {
std::unordered_map<std::string, std::string> map;
for (const auto& kv : dict)
map[kv.first.cast<std::string>()] = kv.second.cast<std::string>();

return map;
};

const auto python_paths = dict_to_map(sysconfig.attr("get_paths")().cast<py::dict>());
const auto python_venv = std::getenv("VIRTUAL_ENV") == nullptr ? "<none>" : std::getenv("VIRTUAL_ENV");

stream << " Python:\n"
<< " Version: " << sys.attr("version").cast<std::string>() << "\n"
<< " Virtual Env: " << python_venv << "\n"
<< " Executable: " << sys.attr("executable").cast<std::string>() << "\n"
<< " Site Library: " << python_paths.at("purelib") << "\n"
<< " Include: " << python_paths.at("include") << "\n"
<< " Runtime Library: " << python_paths.at("stdlib") << "\n";

if (imported_numpy) {
stream << " NumPy Version: " << numpy.attr("version").attr("version").cast<std::string>() << "\n"
<< " NumPy Include: " << numpy.attr("get_include")().cast<std::string>() << "\n";
} else {
// Output NumPy import error
stream << " NumPy: " << err << "\n";
}

#if NGEN_WITH_ROUTING

// TODO: Maybe hash the package sources?
//
// In site-packages, the RECORD file for dist contains
// hashes generated for all files -- maybe parse this and
// pull a combined hash?

#endif // NGEN_WITH_ROUTING
} // END RAII
#endif // NGEN_WITH_PYTHON // -------------------------------------------------


} // ngen::exec_info::runtime_summary

int main(int argc, char *argv[]) {

if (argc > 1 && std::string{argv[1]} == "--info") {
#if NGEN_WITH_MPI
MPI_Init(nullptr, nullptr);
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
MPI_Comm_size(MPI_COMM_WORLD, &mpi_num_procs);

if (mpi_rank == 0)
#endif
{
std::ostringstream output;
output << ngen::exec_info::build_summary;
ngen::exec_info::runtime_summary(output);
std::cout << output.str() << std::endl;
} // if (mpi_rank == 0)
#if NGEN_WITH_MPI
MPI_Finalize();
#endif

exit(1);
}

std::cout << "NGen Framework " << ngen_VERSION_MAJOR << "."
<< ngen_VERSION_MINOR << "."
<< ngen_VERSION_PATCH << std::endl;
Expand Down
Loading