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

[Experiment] Nanobind #127

Open
wants to merge 1 commit into
base: development
Choose a base branch
from
Open
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
29 changes: 18 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,23 @@ find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
# default installation directories: Python
pyamrex_set_default_install_dirs_python()

# pybind11
# builds pybind11 from git (default), form local source or
# nanobind
# builds nanobind from git (default), form local source or
# finds an existing install
include(${pyAMReX_SOURCE_DIR}/cmake/dependencies/pybind11.cmake)
include(${pyAMReX_SOURCE_DIR}/cmake/dependencies/nanobind.cmake)


# Targets #####################################################################
#
# collect all objects for compilation
add_library(pyAMReX MODULE src/pyAMReX.cpp)
nanobind_build_library(
nanobind # Target name
NB_STATIC STABLE_API LTO # Optional flags (see below)
)

nanobind_add_module(pyAMReX
src/pyAMReX.cpp
)
add_library(pyAMReX::pyAMReX ALIAS pyAMReX)

# own headers
Expand All @@ -110,22 +117,22 @@ set_target_properties(pyAMReX PROPERTIES

# link dependencies
target_link_libraries(pyAMReX PUBLIC AMReX::amrex)
target_link_libraries(pyAMReX PRIVATE pybind11::module pybind11::lto pybind11::windows_extras)
#target_link_libraries(pyAMReX PRIVATE nanobind) #::module nanobind::lto nanobind::windows_extras)

# binary name: we will encoded 1D, 2D and 3D in here so we can provide a
# wrapper library that pre-compiled all three geometry variants of AMReX
#set_pyAMReX_binary_name()

# set Python module properties
set_target_properties(pyAMReX PROPERTIES
# hide symbols for combining multiple pybind11 modules downstream & for
# hide symbols for combining multiple nanobind modules downstream & for
# reduced binary size
CXX_VISIBILITY_PRESET "hidden"
CUDA_VISIBILITY_PRESET "hidden"
# name of the pybind-generated python module, which is wrapped in another
# name of the nanobind-generated python module, which is wrapped in another
# fluffy front-end modules, so we can extend it with pure Python
ARCHIVE_OUTPUT_NAME amrex_pybind
LIBRARY_OUTPUT_NAME amrex_pybind
ARCHIVE_OUTPUT_NAME amrex_nanobind
LIBRARY_OUTPUT_NAME amrex_nanobind
# build output directories - mainly set to run tests from CMake & IDEs
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_PYTHON_OUTPUT_DIRECTORY}/amrex
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_PYTHON_OUTPUT_DIRECTORY}/amrex
Expand All @@ -152,10 +159,10 @@ if(EMSCRIPTEN)
set_target_properties(pyAMReX PROPERTIES
PREFIX "")
else()
pybind11_extension(pyAMReX)
nanobind_extension(pyAMReX)
endif()
if(NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug|RelWithDebInfo)
pybind11_strip(pyAMReX)
nanobind_strip(pyAMReX)
endif()

# AMReX helper function: propagate CUDA specific target & source properties
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pyAMReX depends on the following popular third party software.
- a mature [C++17](https://en.wikipedia.org/wiki/C%2B%2B17) compiler, e.g., GCC 8, Clang 7, NVCC 11.0, MSVC 19.15 or newer
- [CMake 3.20.0+](https://cmake.org)
- [AMReX *development*](https://amrex-codes.github.io): we automatically download and compile a copy of AMReX
- [pybind11](https://github.com/pybind/pybind11/) 2.10.1+: we automatically download and compile a copy of pybind11 ([new BSD](https://github.com/pybind/pybind11/blob/master/LICENSE))
- [pybind11](https://github.com/pybind/nanobind/) 2.10.1+: we automatically download and compile a copy of pybind11 ([new BSD](https://github.com/pybind/nanobind/blob/master/LICENSE))
- [Python](https://python.org) 3.7+
- [Numpy](https://numpy.org) 1.15+

Expand Down
60 changes: 60 additions & 0 deletions cmake/dependencies/nanobind.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
function(find_nanobind)
if(TARGET nanobind::module)
message(STATUS "nanobind::module target already imported")
elseif(pyAMReX_nanobind_src)
message(STATUS "Compiling local nanobind ...")
message(STATUS "nanobind source path: ${pyAMReX_nanobind_src}")
elseif(pyAMReX_nanobind_internal)
message(STATUS "Downloading nanobind ...")
message(STATUS "nanobind repository: ${pyAMReX_nanobind_repo} (${pyAMReX_nanobind_branch})")
include(FetchContent)
endif()
if(TARGET nanobind::module)
# nothing to do, target already exists in the superbuild
elseif(pyAMReX_nanobind_internal OR pyAMReX_nanobind_src)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)

if(pyAMReX_nanobind_src)
add_subdirectory(${pyAMReX_nanobind_src} _deps/localnanobind-build/)
else()
FetchContent_Declare(fetchednanobind
GIT_REPOSITORY ${pyAMReX_nanobind_repo}
GIT_TAG ${pyAMReX_nanobind_branch}
BUILD_IN_SOURCE 0
)
FetchContent_GetProperties(fetchednanobind)

if(NOT fetchednanobind_POPULATED)
FetchContent_Populate(fetchednanobind)
add_subdirectory(${fetchednanobind_SOURCE_DIR} ${fetchednanobind_BINARY_DIR})
endif()

# advanced fetch options
mark_as_advanced(FETCHCONTENT_BASE_DIR)
mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED)
mark_as_advanced(FETCHCONTENT_QUIET)
mark_as_advanced(FETCHCONTENT_SOURCE_DIR_FETCHEDnanobind)
mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED)
mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_FETCHEDnanobind)
endif()
elseif(NOT pyAMReX_nanobind_internal)
find_package(nanobind 1.2.0 CONFIG REQUIRED)
message(STATUS "nanobind: Found version '${nanobind_VERSION}'")
endif()
endfunction()

# local source-tree
set(pyAMReX_nanobind_src ""
CACHE PATH
"Local path to nanobind source directory (preferred if set)")

# Git fetcher
option(pyAMReX_nanobind_internal "Download & build nanobind" ON)
set(pyAMReX_nanobind_repo "https://github.com/wjakob/nanobind.git"
CACHE STRING
"Repository URI to pull and build nanobind from if(pyAMReX_nanobind_internal)")
set(pyAMReX_nanobind_branch "v1.2.0"
CACHE STRING
"Repository branch for pyAMReX_nanobind_repo if(pyAMReX_nanobind_internal)")

find_nanobind()
60 changes: 0 additions & 60 deletions cmake/dependencies/pybind11.cmake

This file was deleted.

46 changes: 27 additions & 19 deletions src/AmrCore/AmrMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,24 @@
#include <AMReX_Config.H>
#include <AMReX_AmrMesh.H>

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <nanobind/nanobind.h>
#include <nanobind/operators.h>
#include <nanobind/stl/function.h>
#include <nanobind/stl/list.h>
#include <nanobind/stl/optional.h>
#include <nanobind/stl/pair.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/tuple.h>
#include <nanobind/stl/variant.h>
#include <nanobind/stl/vector.h>

#include <sstream>

namespace py = pybind11;
namespace py = nanobind;
using namespace amrex;


void init_AmrMesh(py::module &m) {
void init_AmrMesh(py::module_ &m) {
py::class_< AmrInfo >(m, "AmrInfo")
.def("__repr__",
[](AmrInfo const & amr_info) {
Expand All @@ -27,28 +35,28 @@ void init_AmrMesh(py::module &m) {

.def(py::init< >())

.def_readwrite("verbose", &AmrInfo::verbose)
.def_readwrite("max_level", &AmrInfo::max_level)
.def_rw("verbose", &AmrInfo::verbose)
.def_rw("max_level", &AmrInfo::max_level)

// note: https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html#making-opaque-types
//.def_readwrite("ref_ratio", &AmrInfo::ref_ratio)
//.def_readwrite("blocking_factor", &AmrInfo::blocking_factor)
//.def_readwrite("max_grid_size", &AmrInfo::max_grid_size)
//.def_readwrite("n_error_buf", &AmrInfo::n_error_buf)
//.def_rw("ref_ratio", &AmrInfo::ref_ratio)
//.def_rw("blocking_factor", &AmrInfo::blocking_factor)
//.def_rw("max_grid_size", &AmrInfo::max_grid_size)
//.def_rw("n_error_buf", &AmrInfo::n_error_buf)
.def("ref_ratio", [](AmrInfo const & amr_info, int lev){ return amr_info.ref_ratio.at(lev); })
.def("blocking_factor", [](AmrInfo const & amr_info, int lev){ return amr_info.blocking_factor.at(lev); })
.def("max_grid_size", [](AmrInfo const & amr_info, int lev){ return amr_info.max_grid_size.at(lev); })
.def("n_error_buf", [](AmrInfo const & amr_info, int lev){ return amr_info.n_error_buf.at(lev); })

.def_readwrite("grid_eff", &AmrInfo::grid_eff)
.def_readwrite("n_proper", &AmrInfo::n_proper)
.def_readwrite("use_fixed_upto_level", &AmrInfo::use_fixed_upto_level)
.def_readwrite("use_fixed_coarse_grids", &AmrInfo::use_fixed_coarse_grids)
.def_readwrite("refine_grid_layout", &AmrInfo::refine_grid_layout)
.def_readwrite("refine_grid_layout_dims", &AmrInfo::refine_grid_layout_dims)
.def_readwrite("check_input", &AmrInfo::check_input)
.def_readwrite("use_new_chop", &AmrInfo::use_new_chop)
.def_readwrite("iterate_on_new_grids", &AmrInfo::iterate_on_new_grids)
.def_rw("grid_eff", &AmrInfo::grid_eff)
.def_rw("n_proper", &AmrInfo::n_proper)
.def_rw("use_fixed_upto_level", &AmrInfo::use_fixed_upto_level)
.def_rw("use_fixed_coarse_grids", &AmrInfo::use_fixed_coarse_grids)
.def_rw("refine_grid_layout", &AmrInfo::refine_grid_layout)
.def_rw("refine_grid_layout_dims", &AmrInfo::refine_grid_layout_dims)
.def_rw("check_input", &AmrInfo::check_input)
.def_rw("use_new_chop", &AmrInfo::use_new_chop)
.def_rw("iterate_on_new_grids", &AmrInfo::iterate_on_new_grids)

;

Expand Down
32 changes: 20 additions & 12 deletions src/Base/AMReX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,27 @@
#include <AMReX_Vector.H>
#include <AMReX_ParmParse.H>

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <nanobind/nanobind.h>
#include <nanobind/operators.h>
#include <nanobind/stl/function.h>
#include <nanobind/stl/list.h>
#include <nanobind/stl/optional.h>
#include <nanobind/stl/pair.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/tuple.h>
#include <nanobind/stl/variant.h>
#include <nanobind/stl/vector.h>

#include <string>

namespace py = pybind11;
namespace py = nanobind;
using namespace amrex;

namespace amrex {
struct Config {};
}

void init_AMReX(py::module& m)
void init_AMReX(py::module_& m)
{
py::class_<AMReX>(m, "AMReX")
.def_static("empty", &AMReX::empty)
Expand All @@ -26,18 +34,18 @@ void init_AMReX(py::module& m)
;

py::class_<Config>(m, "Config")
.def_property_readonly_static(
.def_prop_rw_static(
"amrex_version",
[](py::object) { return Version(); },
"AMReX library version")
.def_property_readonly_static(
.def_prop_rw_static(
"spacedim",
[](py::object) { return AMREX_SPACEDIM; })
.def_property_static(
.def_prop_rw_static(
"verbose",
[](py::object) { return Verbose(); },
[](py::object, const int v) { SetVerbose(v); })
.def_property_readonly_static(
.def_prop_rw_static(
"have_mpi",
[](py::object){
#ifdef AMREX_USE_MPI
Expand All @@ -46,7 +54,7 @@ void init_AMReX(py::module& m)
return false;
#endif
})
.def_property_readonly_static(
.def_prop_rw_static(
"have_gpu",
[](py::object){
#ifdef AMREX_USE_GPU
Expand All @@ -55,7 +63,7 @@ void init_AMReX(py::module& m)
return false;
#endif
})
.def_property_readonly_static(
.def_prop_rw_static(
"have_omp",
[](py::object){
#ifdef AMREX_USE_OMP
Expand All @@ -64,7 +72,7 @@ void init_AMReX(py::module& m)
return false;
#endif
})
.def_property_readonly_static(
.def_prop_rw_static(
"gpu_backend",
[](py::object){
#ifdef AMREX_USE_CUDA
Expand Down Expand Up @@ -109,7 +117,7 @@ void init_AMReX(py::module& m)
// This is a convenience helper/bandage for making work with Python
// garbage collectors in various implementations more easy.
// https://github.com/AMReX-Codes/pyamrex/issues/81
auto m_gc = py::module::import("gc");
auto m_gc = py::module_::import_("gc");
auto collect = m_gc.attr("collect");
collect();
};
Expand Down
18 changes: 13 additions & 5 deletions src/Base/Arena.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,23 @@
*/
#include <AMReX_Arena.H>

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <nanobind/nanobind.h>
#include <nanobind/numpy.h>
#include <nanobind/operators.h>
#include <nanobind/stl/function.h>
#include <nanobind/stl/list.h>
#include <nanobind/stl/optional.h>
#include <nanobind/stl/pair.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/tuple.h>
#include <nanobind/stl/variant.h>
#include <nanobind/stl/vector.h>

namespace py = pybind11;
namespace py = nanobind;
using namespace amrex;


void init_Arena(py::module &m) {
void init_Arena(py::module_ &m) {
py::class_< Arena >(m, "Arena");

m.def("The_Arena", &The_Arena, py::return_value_policy::reference)
Expand Down
Loading