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

Bring Nanobind. Fix object leak in from_numpy #2545

Merged
merged 100 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
c243a00
Bring nanobind. Using it for Vector.from_numpy
ferdonline Sep 26, 2023
1cf9518
format fixes. Dont run nanobind cmake
ferdonline Sep 26, 2023
53390db
Fix. clone depth 1 by default
ferdonline Sep 27, 2023
0ced67c
Fix compilation w nanobind when NOT NRN_ENABLE_PYTHON_DYNAMIC
ferdonline Sep 28, 2023
cdf47c5
Improve nrnpy_vec_from_python so it uses list getitem when possible. …
ferdonline Sep 28, 2023
9e2e0e7
Create nanobind target with better flags. No default visibility
ferdonline Sep 28, 2023
05ed787
Unique nanobind targets, one for each dyn python
ferdonline Sep 29, 2023
6e4d02c
Improve build as per the original script
ferdonline Oct 1, 2023
79f4ac8
Merge branch 'master' into feature/nanobind
ferdonline Oct 1, 2023
a183cda
For an object lib use setting similar to static lib
ferdonline Oct 18, 2023
45473c4
Address Sonar checks
ferdonline Oct 18, 2023
166f460
Merge branch 'master' into feature/nanobind
ferdonline Oct 18, 2023
d166106
Avoid warnings from 3rd party includes
ferdonline Oct 18, 2023
a4f9219
Upgrade to v2.0.0
May 24, 2024
547baab
Merge remote-tracking branch 'origin/master'
May 24, 2024
5789e33
foobar
May 24, 2024
7ef1aa9
foobar
May 24, 2024
33384b0
Fix formatting
github-actions[bot] May 24, 2024
6d28378
SHARED => STATIC
May 24, 2024
356756d
Merge remote-tracking branch 'origin/feature/nanobind'
May 24, 2024
a7e14ac
debug
May 28, 2024
d8353bd
Fix shared / object / static
May 28, 2024
fb8caa8
Revert "debug"
May 28, 2024
087edbc
More
May 28, 2024
47c3167
Debug windows...
May 28, 2024
b847e73
Export nrnpy_hoc
May 29, 2024
6f26ef0
Export more symbols for microsoft
May 29, 2024
b8f38bf
include
May 29, 2024
6fe9eaa
Simplify CI
May 29, 2024
2a4b45f
Revert "Simplify CI"
May 29, 2024
0e889f2
Simplify CI
May 29, 2024
60ae462
better linkage
May 29, 2024
741295f
Position is important
May 29, 2024
c280d6f
More export for windows
May 29, 2024
232dba3
Fix formatting
github-actions[bot] May 29, 2024
4c3abd8
NB_EXPORT for RXD
May 29, 2024
1c6c4f2
Merge remote-tracking branch 'origin/feature/nanobind'
May 29, 2024
501bb93
one left
May 29, 2024
41ee749
Extern in the right place NB_EXPORT the world
May 30, 2024
59b124c
Fix formatting
github-actions[bot] May 30, 2024
26c15ad
Simplify export
May 30, 2024
8a38487
Merge remote-tracking branch 'origin/feature/nanobind'
May 30, 2024
6d0f998
Fix formatting
github-actions[bot] May 30, 2024
8087f23
make_time_ptr
May 30, 2024
2162bb9
Merge remote-tracking branch 'origin/feature/nanobind'
May 30, 2024
c912b00
Revert "Simplify CI"
May 30, 2024
d8eee43
Revert "Debug windows..."
May 30, 2024
8201d10
Miss one endif
May 30, 2024
8b7200a
shortened nb_defs.h
May 30, 2024
9832d25
Fix formatting
github-actions[bot] May 30, 2024
430b64d
Use nanobind nb_defs
May 30, 2024
86b8964
Merge remote-tracking branch 'origin/feature/nanobind'
May 30, 2024
2729efc
Fix comments from Luc
May 30, 2024
3f537fa
Don't modify External
May 30, 2024
d018120
Reduce size of modification
May 30, 2024
b44c242
Fix formatting
github-actions[bot] May 30, 2024
df0d684
More verbose cmake
May 30, 2024
5cc8780
Merge remote-tracking branch 'origin/feature/nanobind'
May 30, 2024
0ffb545
Fix formatting
github-actions[bot] May 30, 2024
016fcdc
Need recursive for nanobind
May 30, 2024
b1c80b8
export all
May 30, 2024
dd0bfb0
Huge clean
May 30, 2024
58f43ce
Fix cmake
May 30, 2024
e936b96
failure
May 30, 2024
db63912
Try
May 30, 2024
4147249
We are compiling with MINGW
May 31, 2024
b87a990
Resurce only nanobind
May 31, 2024
3177806
Revert "Resurce only nanobind"
May 31, 2024
663e62f
Merge remote-tracking branch 'origin/master'
Jun 20, 2024
dbfab15
Try with a def file
Jun 20, 2024
c2d314a
Fix formatting
github-actions[bot] Jun 20, 2024
d7aa1ac
forgot nrnpy_hoc
Jun 20, 2024
41c50ad
Merge remote-tracking branch 'origin/feature/nanobind'
Jun 20, 2024
500f98c
Fix format?
Jun 21, 2024
3e3f72b
Merge remote-tracking branch 'origin/master'
Jun 24, 2024
87f833a
revert cmake way for symbol (because bug)
Jun 24, 2024
f17e86e
Fix formatting
github-actions[bot] Jun 24, 2024
a82c18a
Merge branch 'master' into feature/nanobind
Jun 24, 2024
d0985da
more include
Jun 24, 2024
491e123
Merge remote-tracking branch 'origin/feature/nanobind'
Jun 24, 2024
d725e92
No more nrnpython.def
Jun 24, 2024
ad67a76
export nrnpy_hoc
Jun 24, 2024
314c8af
add more NRN_EXPORT
Jun 24, 2024
93e5b48
Fix formatting
github-actions[bot] Jun 24, 2024
a6465ab
One more
Jun 24, 2024
36dd55c
Merge remote-tracking branch 'origin/feature/nanobind'
Jun 24, 2024
2ffb318
Fix formatting
github-actions[bot] Jun 24, 2024
6316e86
one more
Jun 25, 2024
c1413d7
Merge remote-tracking branch 'origin/feature/nanobind'
Jun 25, 2024
25b1725
one more
Jun 25, 2024
15a286b
Fix formatting
github-actions[bot] Jun 25, 2024
f84830b
Merge branch 'master' into feature/nanobind
Jun 25, 2024
49281aa
Revert GHCI changes
Jun 26, 2024
28bf8ef
Merge remote-tracking branch 'origin/feature/nanobind'
Jun 26, 2024
a342e8c
Test the new module
Jun 26, 2024
09c40ae
Merge branch 'master' into feature/nanobind
Jun 26, 2024
c218b71
Fix formatting
github-actions[bot] Jun 26, 2024
d3007ea
simplify disabling of adding modules
Jun 26, 2024
eb6e480
Merge remote-tracking branch 'origin/feature/nanobind'
Jun 26, 2024
ae200cc
Merge remote-tracking branch 'origin/master'
Jun 26, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
# * add 'live-debug-win' to your PR title
# * push something to your PR branch (note that just re-running the pipeline disregards the title update)
- name: live debug session on failure (manual steps required, check `.github/windows.yml`)
if: failure() && contains(github.event.pull_request.title, 'live-debug-win')
alkino marked this conversation as resolved.
Show resolved Hide resolved
if: failure()
uses: mxschmitt/action-tmate@v3

- name: Upload build artifact
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@
[submodule "external/eigen"]
path = external/eigen
url = https://gitlab.com/libeigen/eigen.git
[submodule "external/nanobind"]
path = external/nanobind
url = https://github.com/wjakob/nanobind
11 changes: 7 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ endif()
if(NRN_ENABLE_PYTHON)
# Make sure the USE_PYTHON macro is defined in the C++ code
list(APPEND NRN_COMPILE_DEFS USE_PYTHON)
# Ensure nanobind is there, but dont import, we don't want its CMake
nrn_add_external_project(nanobind False)
include(NanoBindMinimal)
endif()

# =============================================================================
Expand Down Expand Up @@ -572,6 +575,10 @@ endif()
# =============================================================================
add_subdirectory(src/sparse13)
add_subdirectory(src/gnu)
if(NRN_ENABLE_PYTHON)
add_subdirectory(src/nrnpython)
endif()

add_subdirectory(src/nrniv)

# Collect the environment variables that are needed to execute NEURON from the build directory. This
Expand Down Expand Up @@ -599,10 +606,6 @@ if(NRN_ENABLE_PYTHON)
endif()
add_subdirectory(bin)

if(NRN_ENABLE_PYTHON)
add_subdirectory(src/nrnpython)
endif()

if(NRN_MACOS_BUILD)
add_subdirectory(src/mac)
endif()
Expand Down
2 changes: 1 addition & 1 deletion cmake/ExternalProjectHelper.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function(nrn_initialize_submodule path)
endif()
message(STATUS "Sub-module : missing ${path} : running git submodule update --init")
execute_process(
COMMAND ${GIT_EXECUTABLE} submodule update --init -- ${path}
COMMAND ${GIT_EXECUTABLE} submodule update --recursive --init -- ${path}
alkino marked this conversation as resolved.
Show resolved Hide resolved
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE ret)
if(NOT ret EQUAL 0)
Expand Down
21 changes: 21 additions & 0 deletions cmake/NanoBindMinimal.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# =============================================================================
# minimal nanobind interface
# =============================================================================

set(NB_DIR ${PROJECT_SOURCE_DIR}/external/nanobind)

function(make_nanobind_target TARGET_NAME PYINC)
add_library(${TARGET_NAME} STATIC ${NB_DIR}/src/nb_combined.cpp)
target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${NB_DIR}/include)
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${NB_DIR}/ext/robin_map/include ${PYINC})
if(MSVC)
# Do not complain about vsnprintf
target_compile_definitions(${TARGET_NAME} PRIVATE -D_CRT_SECURE_NO_WARNINGS)
else()
# Generally needed to handle type punning in Python code
target_compile_options(${TARGET_NAME} PRIVATE -fno-strict-aliasing)
endif()
target_compile_features(${TARGET_NAME} PUBLIC cxx_std_17)
set_property(TARGET ${TARGET_NAME} PROPERTY POSITION_INDEPENDENT_CODE True)
set_property(TARGET ${TARGET_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
endfunction()
1 change: 1 addition & 0 deletions external/nanobind
Submodule nanobind added at 8d7f1e
13 changes: 11 additions & 2 deletions src/nrnpython/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,18 @@ if(NRN_ENABLE_PYTHON_DYNAMIC)
list(GET NRN_PYTHON_VERSIONS ${val} pyver)
list(GET NRN_PYTHON_INCLUDES ${val} pyinc)
list(GET NRN_PYTHON_LIBRARIES ${val} pylib)
set(nanobind_target "nanobind_py${pyver}")
make_nanobind_target(${nanobind_target} ${pyinc})
add_library(nrnpython${pyver} SHARED ${NRNPYTHON_FILES_LIST})
if(MSVC)
set_property(TARGET nrnpython${pyver} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 1)
endif()
target_include_directories(nrnpython${pyver} BEFORE PUBLIC ${pyinc} ${INCLUDE_DIRS})
target_link_libraries(nrnpython${pyver} nrniv_lib ${Readline_LIBRARY})
target_link_libraries(nrnpython${pyver} PUBLIC nrniv_lib)
target_link_libraries(nrnpython${pyver} PRIVATE ${Readline_LIBRARY} ${nanobind_target})
if(NRN_LINK_AGAINST_PYTHON)
target_link_libraries(nrnpython${pyver} ${pylib})
target_link_libraries(nrnpython${pyver} PUBLIC ${pylib})
endif()
add_dependencies(nrnpython${pyver} nrniv_lib)
list(APPEND nrnpython_lib_list nrnpython${pyver})
Expand All @@ -68,6 +75,8 @@ else()
target_link_libraries(nrnpython ${NRN_DEFAULT_PYTHON_LIBRARIES})
target_include_directories(nrnpython PUBLIC ${PROJECT_SOURCE_DIR}/${NRN_3RDPARTY_DIR}/eigen)
target_include_directories(nrnpython PUBLIC ${PROJECT_BINARY_DIR}/src/nrniv/oc_generated)
make_nanobind_target(nanobind ${NRN_DEFAULT_PYTHON_INCLUDES})
target_link_libraries(nrnpython nanobind)
endif()

configure_file(_config_params.py.in "${PROJECT_BINARY_DIR}/lib/python/neuron/_config_params.py"
Expand Down
91 changes: 49 additions & 42 deletions src/nrnpython/nrnpy_hoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include <vector>
#include <sstream>

#include <nanobind/nanobind.h>

namespace nb = nanobind;

extern PyTypeObject* psection_type;
extern std::vector<const char*> py_exposed_classes;

Expand Down Expand Up @@ -68,8 +72,6 @@
extern Object** (*nrnpy_vec_to_python_p_)(void*);
extern Object** (*nrnpy_vec_as_numpy_helper_)(int, double*);
extern Object* (*nrnpy_rvp_rxd_to_callable)(Object*);
extern "C" int nrnpy_set_vec_as_numpy(PyObject* (*p)(int, double*) ); // called by ctypes.
extern "C" int nrnpy_set_gui_callback(PyObject*);
extern Symbol* ivoc_alias_lookup(const char* name, Object* ob);
class NetCon;
extern int nrn_netcon_weight(NetCon*, double**);
Expand Down Expand Up @@ -2460,60 +2462,65 @@
return static_cast<char*>(data);
}


inline double pyobj_to_double_or_fail(PyObject* obj, long obj_id) {
if (!PyNumber_Check(obj)) {
char buf[50];
Sprintf(buf, "item %d is not a valid number", obj_id);
hoc_execerror(buf, 0);

Check warning on line 2470 in src/nrnpython/nrnpy_hoc.cpp

View check run for this annotation

Codecov / codecov/patch

src/nrnpython/nrnpy_hoc.cpp#L2469-L2470

Added lines #L2469 - L2470 were not covered by tests
}
return PyFloat_AsDouble(obj);
}

static IvocVect* nrnpy_vec_from_python(void* v) {
Vect* hv = (Vect*) v;
// printf("%s.from_array\n", hoc_object_name(hv->obj_));
Object* ho = *hoc_objgetarg(1);
if (ho->ctemplate->sym != nrnpy_pyobj_sym_) {
hoc_execerror(hoc_object_name(ho), " is not a PythonObject");
}
PyObject* po = nrnpy_hoc2pyobject(ho);
Py_INCREF(po);
if (!PySequence_Check(po)) {
if (!PyIter_Check(po)) {
// We borrow the list, so there's an INCREF and all items are alive
nb::object po = nb::borrow(nrnpy_hoc2pyobject(ho));

// If it's not a sequence, try iterating over it
if (!PySequence_Check(po.ptr())) {
if (!PyIter_Check(po.ptr())) {
hoc_execerror(hoc_object_name(ho),
" does not support the Python Sequence or Iterator protocol");
}
PyObject* iterator = PyObject_GetIter(po);
assert(iterator != NULL);
int i = 0;
PyObject* p;
while ((p = PyIter_Next(iterator)) != NULL) {
if (!PyNumber_Check(p)) {
char buf[50];
Sprintf(buf, "item %d not a number", i);
hoc_execerror(buf, 0);
}
hv->push_back(PyFloat_AsDouble(p));
Py_DECREF(p);
++i;
long i = 0;
for (nb::handle item: po) {
hv->push_back(pyobj_to_double_or_fail(item.ptr(), i));
i++;
}
return hv;
}

int size = nb::len(po);
hv->resize(size);
double* x = vector_vec(hv);

// If sequence provides __array_interface__ use it
long stride;
char* array_interface_ptr = double_array_interface(po.ptr(), stride);
if (array_interface_ptr) {
for (int i = 0, j = 0; i < size; ++i, j += stride) {
x[i] = *(double*) (array_interface_ptr + j);
}
return hv;
}

// If it's a normal list, convert to the good type so operator[] is more efficient
if (PyList_Check(po.ptr())) {
nb::list list_obj{std::move(po)};
for (long i = 0; i < size; ++i) {
x[i] = pyobj_to_double_or_fail(list_obj[i].ptr(), i);
}
Py_DECREF(iterator);
} else {
int size = PySequence_Size(po);
// printf("size = %d\n", size);
hv->resize(size);
double* x = vector_vec(hv);
long stride;
char* y = double_array_interface(po, stride);
if (y) {
for (int i = 0, j = 0; i < size; ++i, j += stride) {
x[i] = *(double*) (y + j);
}
} else {
for (int i = 0; i < size; ++i) {
PyObject* p = PySequence_GetItem(po, i);
if (!PyNumber_Check(p)) {
char buf[50];
Sprintf(buf, "item %d not a number", i);
hoc_execerror(buf, 0);
}
x[i] = PyFloat_AsDouble(p);
Py_DECREF(p);
}
for (long i = 0; i < size; ++i) {
x[i] = pyobj_to_double_or_fail(po[i].ptr(), i);
}
}
Py_DECREF(po);
return hv;
}

Expand Down
Loading