It looks like python’s multiprocessing module also copies the data if we use a spawn start_method:
import multiprocessing as mp
x = [1, 2]
def foo(a):
    print(x)
    print(a)

if __name__ == '__main__':
   mp.set_start_method("spawn")
    x.append(3)
    p = mp.Process(target=foo, args=(x,))
    p.start()
    p.join()

To answer your question, there is a deepcopy, though shared memory will be used for Tensor data.
From the pytorch multiprocessing “best practices” page (https://pytorch.org/docs/stable/notes/multiprocessing.html 91):
We recommend using python:multiprocessing.Queue for passing all kinds of PyTorch objects between processes. It is possible to e.g. inherit the tensors and storages already in shared memory, when using the fork start method, however it is very bug prone and should be used with care, and only by advanced users. Queues, even though they’re sometimes a less elegant solution, will work properly in all cases.


You could thus use the fork start method with pytorch multiprocessing to avoid the copy, though as the docs mention this is not supported.