PyTorch multiprocessing with CUDA sets tensors to 0

johnny12: <p>The following code works perfectly on CPU. On CUDA, the second print shows that the weights are all 0.</p>
<p>If I don’t pass <code>l</code> to the pool, it works. If I replace the pool from <code>concurrent.futures</code> with <code>mp.Process</code> weights are still 0.</p>
<p>This happens only on CUDA.</p>
<p>What am I doing wrong?</p>
<p>Python 3.10.9<br>
PyTorch 2.0.0<br>
CUDA 11.7</p>
<pre><code class="lang-python">import torch
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import ProcessPoolExecutor
from torch import multiprocessing as mp

def goo(l):
    return l(torch.rand(2, device='cuda'))

def run():
    ctx = mp.get_context('spawn')

    l = torch.nn.Linear(2, 2).to('cuda').share_memory()
    print(vars(l))

    pool = ProcessPoolExecutor(1, mp_context=ctx)
    pool.submit(goo, l)

    def foo():
        print(vars(l))

    thread = ThreadPoolExecutor(1)
    thread.submit(foo)

if __name__ == '__main__':
    run()
</code></pre>

kumpera: <p>What pytorch version are you using? I cannot reproduce your issue with a recent of it.</p>

johnny12: <p>Python 3.10.9<br>
PyTorch 2.0.0<br>
CUDA 11.7</p>
<p>Happens on Windows.</p>
<p>So for you my code doesn’t print 0 weights and bias in the 2nd print?</p>
<p>EDIT: tested also with the latest nightly, still 0.</p>

johnny12: <p>Btw, this is the output I get. The 2nd print shows that weights and bias are 0.</p>
<pre><code class="lang-auto">{'training': True, '_parameters': OrderedDict([('weight', Parameter containing:
tensor([[0.5381, 0.1457],
        [0.2658, 0.5354]], device='cuda:0', requires_grad=True)), ('bias', Parameter containing:
tensor([-0.6313,  0.0193], device='cuda:0', requires_grad=True))]), '_buffers': OrderedDict(), '_non_persistent_buffers_set': set(), '_backward_pre_hooks': OrderedDict(), '_backward_hooks': OrderedDict(), '_is_full_backward_hook': None, '_forward_hooks': OrderedDict(), '_forward_hooks_with_kwargs': OrderedDict(), '_forward_pre_hooks': OrderedDict(), '_forward_pre_hooks_with_kwargs': OrderedDict(), '_state_dict_hooks': OrderedDict(), '_state_dict_pre_hooks': OrderedDict(), '_load_state_dict_pre_hooks': OrderedDict(), '_load_state_dict_post_hooks': OrderedDict(), '_modules': OrderedDict(), 'in_features': 2, 'out_features': 2}
{'training': True, '_parameters': OrderedDict([('weight', Parameter containing:
tensor([[0., 0.],
        [0., 0.]], device='cuda:0', requires_grad=True)), ('bias', Parameter containing:
tensor([0., 0.], device='cuda:0', requires_grad=True))]), '_buffers': OrderedDict(), '_non_persistent_buffers_set': set(), '_backward_pre_hooks': OrderedDict(), '_backward_hooks': OrderedDict(), '_is_full_backward_hook': None, '_forward_hooks': OrderedDict(), '_forward_hooks_with_kwargs': OrderedDict(), '_forward_pre_hooks': OrderedDict(), '_forward_pre_hooks_with_kwargs': OrderedDict(), '_state_dict_hooks': OrderedDict(), '_state_dict_pre_hooks': OrderedDict(), '_load_state_dict_pre_hooks': OrderedDict(), '_load_state_dict_post_hooks': OrderedDict(), '_modules': OrderedDict(), 'in_features': 2, 'out_features': 2}
</code></pre>

kumpera: <p><a class="mention" href="/u/colesbury">@colesbury</a> any idea on what could be the issue on windows?</p>

colesbury: <p><a class="mention" href="/u/kumpera">@kumpera</a>, no idea, other than it sounds like a bug with sharing GPU memory across processes on Windows.</p>

jakkes12: <p>Getting this as well, on WSL.</p>

jakkes12: <p>The example posted in the original post seems to produce the correct behavior on WSL2, CUDA12.2, Python 3.10.12 and PyTorch 2.0.1. However, the below produces very odd behavior. It seems placing the module in shared memory resets the variables.</p>
<pre><code class="lang-auto">import torch
import threading
from torch import multiprocessing as mp

def goo(l):
    print("entering goo")
    print(list(l.parameters()))
    x = l(torch.rand(2, device='cuda'))
    print(x)
    print("leaving goo")

def run():
    ctx = mp.get_context('spawn')

    l = torch.nn.Linear(2, 2).to('cuda').share_memory()
    
    print("##### regular call #####")
    goo(l)

    print("##### thread call #####")
    thread = threading.Thread(target=goo, args=(l, ))
    thread.start()
    thread.join()

    print("##### process call #####")
    process = ctx.Process(target=goo, args=(l,))
    process.start()
    process.join()

    print("##### thread call #####")
    thread = threading.Thread(target=goo, args=(l, ))
    thread.start()
    thread.join()

    print("##### regular call #####")
    goo(l)

if __name__ == '__main__':
    run()
</code></pre>
<p>outputs</p>
<pre><code class="lang-auto">##### regular call #####
entering goo
[Parameter containing:
tensor([[ 0.2169, -0.5305],
        [ 0.1662, -0.3463]], device='cuda:0', requires_grad=True), Parameter containing:
tensor([-0.4492,  0.0421], device='cuda:0', requires_grad=True)]
tensor([-0.9618, -0.2915], device='cuda:0', grad_fn=&lt;AddBackward0&gt;)
leaving goo
##### thread call #####
entering goo
[Parameter containing:
tensor([[ 0.2169, -0.5305],
        [ 0.1662, -0.3463]], device='cuda:0', requires_grad=True), Parameter containing:
tensor([-0.4492,  0.0421], device='cuda:0', requires_grad=True)]
tensor([-0.7600, -0.1606], device='cuda:0', grad_fn=&lt;AddBackward0&gt;)
leaving goo
##### process call #####
entering goo
[Parameter containing:
tensor([[0., 0.],
        [0., 0.]], device='cuda:0', requires_grad=True), Parameter containing:
tensor([0., 0.], device='cuda:0', requires_grad=True)]
tensor([0., 0.], device='cuda:0', grad_fn=&lt;AddBackward0&gt;)
leaving goo
##### thread call #####
entering goo
[Parameter containing:
tensor([[0., 0.],
        [0., 0.]], device='cuda:0', requires_grad=True), Parameter containing:
tensor([0., 0.], device='cuda:0', requires_grad=True)]
tensor([0., 0.], device='cuda:0', grad_fn=&lt;AddBackward0&gt;)
leaving goo
##### regular call #####
entering goo
[Parameter containing:
tensor([[0., 0.],
        [0., 0.]], device='cuda:0', requires_grad=True), Parameter containing:
tensor([0., 0.], device='cuda:0', requires_grad=True)]
tensor([0., 0.], device='cuda:0', grad_fn=&lt;AddBackward0&gt;)
leaving goo
</code></pre>

jakkes12: <p>Bumping this…! Very annoying issue.</p>

wavelet: <p>I have the same issue using:<br>
Windows 10 (no WSL) and Widnows 10 + Ubuntu 22.04 in WSL<br>
Python 3.11.7<br>
PyTorch 2.1.2<br>
CUDA 12.1</p>
<p>Is there any workaround?</p>

Skirlax: <p>I have the same issue under windows. However, even when just doing deepcopy of the network and giving each process a copy, the parameters get set to 0.</p>
<p>Did anyone manage to solve it?</p>

1943_Yonv: <p>I have same issue. <a href="https://discuss.pytorch.org/t/torch-multiprocessing-on-cuda-turns-tensors-to-zeros/186455">Torch.multiprocessing on CUDA turns tensors to zeros</a></p>

tobiaswuerth: <p>Jup, same issue here on Windows 11, torch 2.5.1+cu124.</p>
<p>As soon as I start another process, all tensors are set to zero. This even happens for external libraries (like lpips) I import, instantiate and when calling forward the registered buffers in its constructor are 0. Very weird.</p>
<p>Please help</p>