Open nathanfarlow opened 1 month ago
The problem is that numpy_finalize
is being called more than once with the same ops
ptr, so freeing that many times is an issue. For example,
open! Core
let () =
Py.initialize ();
let m =
Py.Import.exec_code_module_from_string
~name:"go.py"
"import numpy as np\na = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32)"
in
let big_array = Py.Module.get m "a" |> Numpy.to_bigarray Float32 C_layout in
let arr = List.init 10 ~f:(Fn.const big_array) in
List.iter arr ~f:Owl.Dense.Ndarray.S.print;
Gc.full_major ()
,;;
will cause numpy_finalize
to be called 11 times, each with a different v
, but Custom_ops_val(v)
is the same across calls.
Ahah, in bigarray.c
, certain operations will copy the Custom_ops_val
. One example is in caml_ba_slice.
I'm not sure how to fix this. It seems like we need to do some ref counting in the finalizer unless we know that the subarrays are dead when the original array is finalized. From skimming bigarray.c
, I couldn't conclude that since the subarrays don't hold a reference to the original array. In the refcounting case, we could decrement in the finalizer, but I'm not sure where we'd increment the refcount without modifying bigarray.c
.
The folllowing code will segfault on my system.
Python 3.11.4 Ocaml 5.1.1 pyml 20231101
It dies in the OCaml garbage collector:
It might be related to this issue given that both code examples use
Numpy.to_bigarray
.