Traceback (most recent call last):
File "test2.py", line 5, in <module>
b = example2(a)
RuntimeError: Precondition violation!
Internal error: trivial_assigner called with unequal types.
/miniforge/envs/flyem-forge/include/xtensor/xassign.hpp(377)
the problem is that m + 2 returns a xexpression<int> and not xexpression<uint8>. This is the generic C++ behavior, e.g.:
uint a = 3, b = 5;
auto c = a + b;
std::cout << std::is_same<decltype(c), int>::value << std::endl; // will print true!
However, we've become recently aware of this issue (2 days ago) and we'll be working on a fix. In the meantime, changing the return type from your example2 function to pyarray<int> should solve the issue.
But as far as I can tell, pyarray is designed to do the right thing here. The pyarray typecaster does indeed check the dtype of the numpy array before permitting pybind11 to make the conversion.
Sorry, I had a copy+paste error in that test program. But the proper test still shows a problem. I edited the code above. See the output for uint64. What's going on?
Thanks for testing. I am not sure where the overload resolution goes wrong. Either it's in the pybind11 code, or in our code. Will need to be investigated!
Worth noting: I am using pybind11 2.1.1 instead of the latest (2.2.1), because that's the newest version that is permitted by the current xtensor-python recipe on conda-forge.
I suppose I should try a newer version of pybind11 before reporting the problem to them...
I have to pause my investigation for now, but I'll try to get back to this later tonight or tomorrow.
I don't think that it should not make much of a difference (pybind11 2.2.1 vs 2.1.1). We pinned to 2.1.x because there was a breaking change in 2.2.0 that we reported and should be fixed in 2.2.1.
I just tested the overload resolution with the pybind11 cmake example and it works correctly. Let me investigate if it is our pybind11 variant or our code.
Activity
wolfv commented on Oct 25, 2017
Hi,
the problem is that m + 2 returns a xexpression<int> and not xexpression<uint8>. This is the generic C++ behavior, e.g.:
However, we've become recently aware of this issue (2 days ago) and we'll be working on a fix. In the meantime, changing the return type from your example2 function to pyarray<int> should solve the issue.
SylvainCorlay commented on Oct 25, 2017
Thanks for the detailed report @stuarteberg !
stuarteberg commented on Oct 25, 2017
Thanks very much for the explanation.
I had wondered about that, so I naïvely tried m + static_cast<uint8_t>(2), which made no difference. But after your explanation, I see why.
Instead of changing the return type, can I just cast the output to the correct type (without incurring large temporaries)?
Does xtensor already have a static_cast-like xfunction? Here's what I tried, which seems to work:
Can you spot any problems with that approach?
stuarteberg commented on Oct 25, 2017
... and, sorry, one more question. Now that it works for uint8_t, I want to expose this function for all dtypes. I tried this:
With this test program:
And it produces this output:
But as far as I can tell, pyarray is designed to do the right thing here. The pyarray typecaster does indeed check the dtype of the numpy array before permitting pybind11 to make the conversion.
What am I doing wrong here?
wolfv commented on Oct 25, 2017
and it didn't work? looks good to me
wolfv commented on Oct 25, 2017
btw. great solution! xcast is neat. maybe we'll integrate it into xtensor
stuarteberg commented on Oct 25, 2017
(Sorry, I hit "enter" on my last comment too soon. See my edits for the complete question.)
stuarteberg commented on Oct 25, 2017
Oh no! I see the bug in my test program. Stand by...
stuarteberg commented on Oct 25, 2017
Sorry, I had a copy+paste error in that test program. But the proper test still shows a problem. I edited the code above. See the output for uint64. What's going on?
wolfv commented on Oct 25, 2017
hmm, so pybind basically chooses the wrong overload, right?
stuarteberg commented on Oct 25, 2017
Looks that way...
wolfv commented on Oct 25, 2017
ok, what happens if you reorder the functions?
E.g.
PYBIND11_PLUGIN(example_module) { using namespace pybind11::literals; xt::import_numpy(); py::module m("example_module", ""); m.def("example2", example2<uint64_t>); m.def("example2", example2<uint8_t>); m.def("example2", example2<uint16_t>); m.def("example2", example2<uint32_t>); return m.ptr(); }and can you also try to remove the other overloads?
stuarteberg commented on Oct 25, 2017
Good idea. In that case, the output is correct:
It seems that the uint64 call just defaults to whichever overload is listed first. When I put uint32 first, then I get this:
wolfv commented on Oct 25, 2017
Thanks for testing. I am not sure where the overload resolution goes wrong. Either it's in the pybind11 code, or in our code. Will need to be investigated!
wolfv commented on Oct 25, 2017
@yoshipon do you know if this issue could be caused by the type caster?
stuarteberg commented on Oct 25, 2017
Worth noting: I am using pybind11 2.1.1 instead of the latest (2.2.1), because that's the newest version that is permitted by the current xtensor-python recipe on conda-forge.
I suppose I should try a newer version of pybind11 before reporting the problem to them...
I have to pause my investigation for now, but I'll try to get back to this later tonight or tomorrow.
SylvainCorlay commented on Oct 25, 2017
I don't think that it should not make much of a difference (pybind11 2.2.1 vs 2.1.1). We pinned to 2.1.x because there was a breaking change in 2.2.0 that we reported and should be fixed in 2.2.1.
wolfv commented on Oct 26, 2017
I just tested the overload resolution with the pybind11 cmake example and it works correctly. Let me investigate if it is our pybind11 variant or our code.
wolfv commented on Oct 26, 2017
Sorry, this was maybe not clear: I tested with the pybind11 py::array that can also accept a numpy array.
wolfv commented on Oct 26, 2017
Hi @stuarteberg thanks again for the report. I found the issue, and I am working on a fix.
I hope I'll be able to push a fix today.
Cheers,
Wolf