-
Notifications
You must be signed in to change notification settings - Fork 22.2k
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
Lazy conjugated tensor is not numpy interoperable #59945
Comments
Whoops, yup, we need to raise an error here. |
@pearu thanks for filing the issue! yeah we should raise an error here (same thing for |
Raising an error is BC-breaking. Why wouldn't you just use |
Note that |
I don't think so - before |
Btw, |
@rgommers yeah this would be bc-breaking but I think as @pearu mentioned above it might be best to ask user to resolve conjugation before calling these view operations on tensors with conjugate bit set to 1, similar to what we do for pytorch/aten/src/ATen/native/ComplexHelper.h Lines 36 to 39 in 061e71b
|
I don't think this is right either, and if it is it is going to lead to subtle bugs. As far as I understood @anjali411's presentation, this is why a conjugate bit is not allowed to flip back from 1 to 0. If there are any examples like |
Only in terms of "they point at the same memory at this point in time" I hope, not semantically. I'd expect this: b = a.conj()
a[:10] = -99 # does this modify b now?? (it shouldn't!) to not change Or maybe I misunderstood, and the introducing of conjugate views is BC-breaking for this kind of code? |
Maybe numpy(force = True) from another PR could be also used in this case (when > O(1) work is expected and desired) |
It does, and it looks like also in a correct way: >>> a = torch.tensor([1+2j])
>>> b = a.conj()
>>> b[0] = 3+4j
>>> a
tensor([3.-4.j]) IIUC, the conjugate bit is just an additional attribute to a tensor that certain operation implementations may take advantage of by avoiding materialization of intermediate conjugate results. Resetting conjugate bit twice corresponds to just double conjugation that is an identity operation. I don't see why It seems that the conjugate bit works reliably for operations that executions use the pytorch dispatching mechanism. Only operations that directly access the tensor memory, such as numpy interoperability operations, or operations that re-interpret the tensor memory such as On the other hand, while |
Okay, then ignore everything I wrote above. I had not even considered that gh-59943 may have the same root cause. |
@rgommers , I agree, the conjugate bit feature would deserve a new method, say,
I also think that |
@rgommers We argued a bit about whether or not to make this BC breaking change, and you were there too :P The most relevant discussion is in #43270 (comment) It took a while for us to actually land conjugate views on master so the BC breakage is a little worse than it might have been if we had managed to land this last year, but our guess is that the corpus of complex number using PyTorch code is still low enough that
I disagree. It's more important for numpy() to give a semantically equivalent output to the input, and that means we must error. |
About |
OK. No objections as one can do:
if one really wants to access |
I am working on #59790 and this issue is closely connected. Should I implement it in that PR, or is it supposed to be done separately after #59790 is merged? |
Thanks for that link. That's like a year ago - I had completely forgotten about that:)
Okay. Maybe I'm too scarred by working on NumPy for too long, and this is all not too bad. For me making a change after complex becoming stable simply didn't compute. Certainly PyTorch users are more forgiving about BC-breaking changes. In the end this does result in a better design. So if there aren't too many complaints from people using the nightlies, then will be fine to leave it as is I guess. This comment is also still relevant: #43270 (comment).
This was one of the pain points for the array API standard design as well. Since libraries are not consistent with each other about view-copy semantics, we say the same thing in the docs: "don't mutate arrays that can be views if you want code to be portable". It's very hard to guarantee though. |
I used to think that this was not so easy to do because of the base update problem: normally, tensors are mutable, but if you take out an immutable view to the tensor, if you mutate the base tensor, the view would get updated too, so this leads to the unsavory conclusion that when you take out an immutable view, this must make the base tensor immutable too. However, I recently realized that version counters neatly solve this problem. Instead making the base immutable, you just record the base version counter at time the view was taken out. If base mutates, and then you try to use the view, you now get an error message saying that the base has been updated and so the view is no longer valid. So we could easily implement this for Just need to implement it! |
… conjugate or negative bit set" Resolves #59945 and #59946 bc breaking note: Unlike before, complex_tensor.conj().numpy(), complex_float_tensor.conj().view(torch.float64), complex_float_tensor.conj().imag.view(torch.int32) now doesn't return a view but instead errors out Differential Revision: [D29819288](https://our.internmc.facebook.com/intern/diff/D29819288) [ghstack-poisoned]
… conjugate or negative bit set" Resolves #59945 and #59946 bc breaking note: Unlike before, complex_tensor.conj().numpy(), complex_float_tensor.conj().view(torch.float64), complex_float_tensor.conj().imag.view(torch.int32) now doesn't return a view but instead errors out Differential Revision: [D29819288](https://our.internmc.facebook.com/intern/diff/D29819288) [ghstack-poisoned]
… conjugate or negative bit set" Resolves #59945 and #59946 bc breaking note: Unlike before, complex_tensor.conj().numpy(), complex_float_tensor.conj().view(torch.float64), complex_float_tensor.conj().imag.view(torch.int32) now doesn't return a view but instead errors out Differential Revision: [D29819288](https://our.internmc.facebook.com/intern/diff/D29819288) [ghstack-poisoned]
This raising an error is biting us in SciPy, where The workaround is to just use |
🐛 Bug
The bug is best illustrated by the following examples (using the current master):
Expected behavior
Since the numpy view of a lazy conjugated tensor is impossible, the above examples should raise an exception rather than ignore the set conjugate bit.
cc @ezyang @gchanan @zou3519 @bdhirsh @jbschlosser @anjali411 @Varal7 @dylanbespalko @mruberry @lezcano @nikitaved @rgommers @heitorschueroff
The text was updated successfully, but these errors were encountered: