Skip to content

Commit

Permalink
Tutorials (#113)
Browse files Browse the repository at this point in the history
* comment out cppyy

* backup

* unit tested

* unit tests are done

* Committing clang-format changes

* waiting on cmaize patch [skip ci]

* Fix depends and CMaize package order

* 'CMaize-ify' the pybind11 references

* move CMake module to NWXCMake

* use correct option name

* Committing license headers

* uses new api

* better install [skip ci]

* cereal version same as MADNESS

* python is g2g

* Update CMakeLists.txt

---------

Co-authored-by: Clang Robot <[email protected]>
Co-authored-by: zachcran <[email protected]>
Co-authored-by: license[bot] <license[bot]@github.com>
Co-authored-by: Jonathan M. Waldrop <[email protected]>
  • Loading branch information
5 people authored May 29, 2023
1 parent a49ddb3 commit 48d0cb9
Show file tree
Hide file tree
Showing 32 changed files with 1,303 additions and 79 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ Release/

# Users commonly store their specific CMake settings in a toolchain file
toolchain.cmake

# For development often install to a subdirectory of the repo called "install"
install/
54 changes: 44 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ set(

include(get_cmaize)
include(nwx_versions)
include(nwx_cxx_api_docs)


### Options ###
# These are the default values, used only if the user hasn't already set them.
option(BUILD_TESTING "Should we build the tests?" OFF)
option(BUILD_PYBINDINGS "Should we build Python3 bindings?" ON)
option(BUILD_SHARED_LIBS "Should we build shared libraries?" ON)
option(BUILD_PYBIND11_PYBINDINGS "Should we build pybind11 python bindings?" OFF)
option(BUILD_CPPYY_PYBINDINGS "Should the python bindings be Cppyy?" OFF)
option(BUILD_CUDA_BINDINGS "Enable CUDA Bindings" OFF )
option(BUILD_HIP_BINDINGS "Enable HIP Bindings" OFF )
option(BUILD_SYCL_BINDINGS "Enable SYCL Bindings" OFF )
Expand All @@ -51,7 +52,10 @@ endif()
set(project_inc_dir "${CMAKE_CURRENT_LIST_DIR}/include/${PROJECT_NAME}")
set(project_src_dir "${CMAKE_CURRENT_LIST_DIR}/src/${PROJECT_NAME}")

# set(DOXYGEN_OUTPUT_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/docs/build/html/cxx_api)
# Project dependencies
set(project_depends "")

include(nwx_cxx_api_docs)
nwx_cxx_api_docs("README.md" "${project_inc_dir}" "${project_src_dir}")

#TODO: Make sure MADworld uses the Cereal we build
Expand All @@ -69,6 +73,8 @@ cmaize_find_or_build_dependency(
BUILD_TESTING=OFF
)

list(APPEND project_depends MADNESS)

cmaize_find_or_build_dependency(
spdlog
URL github.com/gabime/spdlog
Expand All @@ -77,6 +83,7 @@ cmaize_find_or_build_dependency(
FIND_TARGET spdlog::spdlog
CMAKE_ARGS SPDLOG_INSTALL=ON
)
list(APPEND project_depends spdlog)

# PAPI bindings are enabled, leading to building PAPI with CUDA or rocm support
if("${BUILD_PAPI_BINDINGS}")
Expand All @@ -88,22 +95,30 @@ cmaize_find_or_build_dependency(
URL github.com/USCiLab/cereal
VERSION ${NWX_CEREAL_VERSION}
BUILD_TARGET cereal
FIND_TARGET cereal::cereal
FIND_TARGET cereal
CMAKE_ARGS JUST_INSTALL_CEREAL=ON
)
list(APPEND project_depends cereal)

cmaize_add_library(
${PROJECT_NAME}
SOURCE_DIR "${project_src_dir}"
INCLUDE_DIRS "${project_inc_dir}"
DEPENDS MADNESS cereal spdlog
DEPENDS "${project_depends}"
)

include(nwx_python_mods)
cppyy_make_python_package(MPI PACKAGE parallelzone NAMESPACES parallelzone )
# N.B. this is a no-op if BUILD_PYBIND11_PYBINDINGS is not turned on
include(nwx_pybind11)
nwx_add_pybind11_module(
${PROJECT_NAME}
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/src/python"
DEPENDS "${PROJECT_NAME}"
)

if("${BUILD_TESTING}")
set(CXX_TEST_DIR "${CMAKE_CURRENT_LIST_DIR}/tests/cxx")
set(PYTHON_TEST_DIR "${CMAKE_CURRENT_LIST_DIR}/tests/python")

cmaize_find_or_build_dependency(
Catch2
URL github.com/catchorg/Catch2
Expand All @@ -115,14 +130,23 @@ if("${BUILD_TESTING}")
test_parallelzone
SOURCE_DIR "${CXX_TEST_DIR}/unit_tests"
INCLUDE_DIRS "${project_src_dir}"
DEPENDS Catch2 MADNESS parallelzone cereal
DEPENDS Catch2::Catch2 ${PROJECT_NAME}
)
cmaize_add_tests(
test_parallelzone_docs
SOURCE_DIR "${CXX_TEST_DIR}/doc_snippets"
INCLUDE_DIRS "${project_src_dir}"
DEPENDS Catch2 MADNESS parallelzone cereal
DEPENDS Catch2::Catch2 ${PROJECT_NAME}
)

# N.B. these are no-ops if BUILD_PYBIND11_PYBINDINGS is not turned on
nwx_pybind11_tests(
py_parallelzone "${PYTHON_TEST_DIR}/unit_tests/test_parallelzone.py"
)
nwx_pybind11_tests(
py_doc_snippets "${PYTHON_TEST_DIR}/doc_snippets/test_doc_snippets.py"
)

find_package(MPI REQUIRED)
add_test(
NAME "test_pz_under_mpi"
Expand All @@ -136,4 +160,14 @@ if("${BUILD_TESTING}")
)
endif()

if("${BUILD_CPPYY_PYBINDINGS}")
# Cppyy bindings
include(nwx_python_mods)
cppyy_make_python_package(
MPI
PACKAGE parallelzone
NAMESPACES parallelzone
)
endif()

cmaize_add_package(${PROJECT_NAME} NAMESPACE nwx::)
1 change: 1 addition & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
sphinx
sphinx_rtd_theme
sphinx_tabs
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
extensions = [
'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx',
'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.mathjax',
'sphinx.ext.githubpages'
'sphinx.ext.githubpages', 'sphinx_tabs.tabs'
]
dir_path = os.path.dirname(os.path.realpath(__file__))
doc_path = os.path.dirname(dir_path)
Expand Down
72 changes: 60 additions & 12 deletions docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,32 +22,80 @@ runtime environment. The ``RuntimeView`` groups the process local resources
typically interact with ``RuntimeView`` and the ``ResourceSet`` object for
the current process. As an example:

.. literalinclude:: ../../tests/cxx/doc_snippets/quickstart.cpp
:language: c++
:lines: 26-36
.. tabs::

.. tab:: C++

.. literalinclude:: ../../tests/cxx/doc_snippets/quickstart.cpp
:language: c++
:lines: 26-36
:dedent: 4

.. tab:: Python

.. literalinclude:: ../../tests/python/doc_snippets/test_quickstart.py
:language: python
:lines: 24-34
:dedent: 8

The ``RuntimeView`` also allows you to access other ``ResourceSet`` instances.
Typically this is done to send or receive information. For example, say we
wanted to copy data from each resource set into the RAM of the 0-th
resource set:

.. literalinclude:: ../../tests/cxx/doc_snippets/quickstart.cpp
:language: c++
:lines: 38-45
.. tabs::

.. tab:: C++

.. literalinclude:: ../../tests/cxx/doc_snippets/quickstart.cpp
:language: c++
:lines: 38-45
:dedent: 4

.. tab:: Python

.. note::

MPI operations are presently limited to the C++ API. Consider using
mpi4py for your Python-based MPI needs.

If we instead wanted every resource set to have a copy of the result, we do a
``RuntimeView``-wide gather:

.. literalinclude:: ../../tests/cxx/doc_snippets/quickstart.cpp
:language: c++
:lines: 47-48
.. tabs::

.. tab:: C++

.. literalinclude:: ../../tests/cxx/doc_snippets/quickstart.cpp
:language: c++
:lines: 47-48
:dedent: 4

.. tab:: Python

.. note::

MPI operations are presently limited to the C++ API. Consider using
mpi4py for your Python-based MPI needs.

Another major feature of parallelzone is introspection of the runtime
environment. Say we wanted to know how much total RAM each resource set has:

.. literalinclude:: ../../tests/cxx/doc_snippets/quickstart.cpp
:language: c++
:lines: 50-51
.. tabs::

.. tab:: C++

.. literalinclude:: ../../tests/cxx/doc_snippets/quickstart.cpp
:language: c++
:lines: 50-51
:dedent: 4

.. tab:: Python

.. literalinclude:: ../../tests/python/doc_snippets/test_quickstart.py
:language: python
:lines: 36-37
:dedent: 8

To summarize:

Expand Down
28 changes: 24 additions & 4 deletions docs/source/user/quick_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,19 @@ better yet, add the missing feature/fix the inefficiency.

To answer the question, given a ``RuntimeView`` object ``rv``:

.. code-block:: c++
.. tabs::

rv.mpi_comm();
.. tab:: C++

.. code-block:: c++

rv.mpi_comm();

.. tab:: Python

.. code-block:: python
rv.mpi_comm()
********************************************
How do I get the current process's MPI rank?
Expand All @@ -40,6 +50,16 @@ Like the MPI communicator, you in general shouldn't need the rank as interacting
with ``ResourceSet`` instances should suffice; however, if you still want it
then given a ``RuntimeView`` object ``rv``:

.. code-block:: c++
.. tabs::

.. tab:: C++

.. code-block:: c++

rv.my_resource_set().mpi_rank();

.. tab:: Python

.. code-block:: python
rv.my_resource_set().mpi_rank();
rv.my_resource_set().mpi_rank()
73 changes: 61 additions & 12 deletions docs/source/user/ram.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,44 @@ Getting RAM
turn are containers of hardware including ``RAM``. Assuming we have a
``RuntimeView`` object ``rv`` we can get a ``RAM`` object by:

.. literalinclude:: ../../../tests/cxx/doc_snippets/ram.cpp
:language: c++
:lines: 29-33
.. tabs::

.. tab:: C++

.. literalinclude:: ../../../tests/cxx/doc_snippets/ram.cpp
:language: c++
:lines: 29-33
:dedent: 4

.. tab:: Python

.. literalinclude:: ../../../tests/python/doc_snippets/test_ram.py
:language: c++
:lines: 23-27
:dedent: 8

The first call to ``ResourceSet::ram()`` retrieves a handle to the RAM which
is local to rank 0. The second call gets the ``RAM`` instance local to the
current process (which for rank 0 is the same as ``rank_0_ram``). Once you
have the ``RAM`` object you can see basic stats such as how much total memory
it has by using member functions, for example:

.. literalinclude:: ../../../tests/cxx/doc_snippets/ram.cpp
:language: c++
:lines: 35-37
.. tabs::

.. tab:: C++

.. literalinclude:: ../../../tests/cxx/doc_snippets/ram.cpp
:language: c++
:lines: 35-37
:dedent: 4

.. tab:: Python

.. literalinclude:: ../../../tests/python/doc_snippets/test_ram.py
:language: c++
:lines: 29-31
:dedent: 8


*************************
All-to-One MPI Operations
Expand All @@ -54,15 +79,39 @@ tutorial will have process :math:`p` "compute" three integers: :math:`p`,
:math:`p+1`, and :math:`p+2`. If we want to collect all of these computed
results into rank 0's RAM we would do:

.. literalinclude:: ../../../tests/cxx/doc_snippets/ram.cpp
:language: c++
:lines: 39-43
.. tabs::

.. tab:: C++

.. literalinclude:: ../../../tests/cxx/doc_snippets/ram.cpp
:language: c++
:lines: 39-43
:dedent: 4

.. tab:: Python

.. note::

MPI operations are presently limited to the C++ API. Consider using
mpi4py for your Python-based MPI needs.

The resulting object ``all_data`` is a ``std::optional`` which has a value if
``rank_0_ram`` is local to the current process. We can exploit whether or not
``all_data`` has a value to avoid needing to remember which process was the
root for the gather operation. For example:

.. literalinclude:: ../../../tests/cxx/doc_snippets/ram.cpp
:language: c++
:lines: 45-49
.. tabs::

.. tab:: C++

.. literalinclude:: ../../../tests/cxx/doc_snippets/ram.cpp
:language: c++
:lines: 45-49
:dedent: 4

.. tab:: Python

.. note::

MPI operations are presently limited to the C++ API. Consider using
mpi4py for your Python-based MPI needs.
Loading

0 comments on commit 48d0cb9

Please sign in to comment.