-
Notifications
You must be signed in to change notification settings - Fork 2.2k
NumPy registered dtypes may not be shared across modules #468
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
Comments
Just to clarify: the problem here is a static data member in a template? It makes sense that this wouldn't be shared across modules (and I'm actually surprised that it works when LTO is not used). I like approach 2, but I don't get the signature of your unordered_map. Why not make it PS: In that case, it would be important to make |
@wjakob Yes, that seems to be the problem (and I was surprised as well that it does sometimes work). To expand on (2), my suggestion is more or less this: // common.h
struct internals {
...
// could be extended with more optional data to be shared across Python modules
// without breaking base pybind11 API
std::unordered_map<std::string, void *> capsules; // could be named `shared_data`
} // numpy.h
struct numpy_type_info { ... }
struct numpy_internals {
std::unordered_map<std::type_index, numpy_type_info> registered_dtypes;
};
...
numpy_internals& get_numpy_internals() {
// (numpy_internals *) get_internals().capsules["numpy"]
} The extra map in |
Hi @aldanor, in that case, let's make it a public API: namespace pybind11 {
/// Returns a named pointer that is shared among all extension modules (using the same pybind11 version) running in the current interpreter. Names with underscores are reserved for internal usage. Returns ``nullptr`` if no matching entry was found.
void *get_shared_data(const char *name);
/// ...
void set_shared_data(const char *name, void *data);
}; You'll probably want to cache the lookup in |
Closed via #472 |
We've recently run into a series of strange problems when sharing registered NumPy dtypes across multiple pybind modules -- the dtypes would appear to be missing when using LTO (
-flto
on gcc 5), likely due to the template static data being BSS (and it would somehow work when the flag was disabled).A simple failing example is as follows:
The point is, we shouldn't rely on the linker to stitch things together, and the proper approach would be to do the same thing as we do with everything else -- i.e., share data through capsules. This would imply that accessing a dtype of a C++ type would require indexing an associated hashmap, but that's probably acceptable.
I see three possible ways of doing this so that the rest of pybind11 code remains (almost) untouched:
numpy.h
could register its own capsule ("numpy_internals"), and share it the same way it's done inget_internals()
. The loading would be done inapi_lookup
, where NumPy API capsule is loaded. This new capsule would hold anunordered_map<std::type_index, numpy_type_info>
, wherenumpy_type_info
would hold a pointer to the dtype and the format string (at the very least).Allow extending
internals
without changing or breaking the base API -- this functionality could be very handy in future when things stabilize. Basically, add something likestd::unordered_map<std::string, void *> capsules
tointernals
(could use ints instead of strings for keys), then e.g.numpy.h
would get its own "capsule" viaget_internals().capsules["numpy"]
. This way, we don't have to copy/paste PyCapsule calls, plus we use the same capsule versioning conversion across all code (e.g. pybind11_1.8).The same as (2), but in
type_info
. However, this limits the "custom" data to being per-type, so (2) is probably a better option.+@wjakob +@bennorth
The text was updated successfully, but these errors were encountered: