Yep, the inefficiency in p.data=x isn’t the setting part. Its that you allocated a new tensor x first, as opposed to just operating on p in place, which avoids allocating any new tensors.
p.copy_(x) is a safer alternative to p.data=x, so I’d recommend that over it, but since you’re still allocating a new tensor in both cases, it won’t be any more efficient.
The only way to avoid to allocating new tensors is to use the chain of in-place ops like you said.