DistributedDataParralled not support cuda?

liubanglan: <p>there was not proper synchronization with the CUDA events that recored copies into this contents tensor before bucket contents tensor allreduce. it seems like not supporting cuda?</p>
<p>web link:<br>
<aside class="onebox githubblob">
  <header class="source">
      <a href="https://github.com/pytorch/pytorch/blob/master/torch/csrc/distributed/c10d/reducer.cpp#L404" target="_blank" rel="nofollow noopener">github.com</a>
  </header>
  <article class="onebox-body">
    <h4><a href="https://github.com/pytorch/pytorch/blob/master/torch/csrc/distributed/c10d/reducer.cpp#L404" target="_blank" rel="nofollow noopener">pytorch/pytorch/blob/master/torch/csrc/distributed/c10d/reducer.cpp#L404</a></h4>
<pre class="onebox"><code class="lang-cpp"><ol class="start lines" start="394" style="counter-reset: li-counter 393 ;">
<li>
</li>
<li>// Keep going, until we either:</li>
<li>// - have kicked off reduction for all buckets, or</li>
<li>// - found a bucket that's not yet ready for reduction.</li>
<li>for (; next_bucket_ &lt; buckets_.size() &amp;&amp; buckets_[next_bucket_].pending == 0;</li>
<li>     next_bucket_++) {</li>
<li>  auto&amp; bucket = buckets_[next_bucket_];</li>
<li>  std::vector&lt;at::Tensor&gt; tensors;</li>
<li>  tensors.reserve(bucket.replicas.size());</li>
<li>  for (const auto&amp; replica : bucket.replicas) {</li>
<li class="selected">    // TODO(@pietern): Ensure proper synchronization with the CUDA events</li>
<li>    // that recorded copies into this contents tensor. If these copies are</li>
<li>    // executed on non-default streams, the current stream for the device</li>
<li>    // that holds the contents tensor must wait on these events.</li>
<li>    //</li>
<li>    // As long as autograd uses the default stream for every device,</li>
<li>    // these operations are implicitly sequenced, and we don't need to</li>
<li>    // do any extra synchronization here.</li>
<li>    //</li>
<li>    tensors.push_back(replica.contents);</li>
<li>  }</li>
</ol></code></pre>


  </article>
  <div class="onebox-metadata">
    
    
  </div>
  <div style="clear: both"></div>
</aside>
</p>

mrshenli: <p>DistributedDataParallel (DDP) does supports CUDA. The comment suggests extra care might be necessary when backward run on non-default stream. Actually, even if backward occurs on non-default streams it should be fine for most use cases. Below is why:</p>
<p>background: I learned from <a class="mention" href="/u/alband">@albanD</a> that autograd engine will use the same stream as the forward pass.</p>
<p>Let’s take a look at what could go wrong for the code you quoted.</p>
<p>1: the tensor is not ready when launching the allreduce operation<br>
2: the tensor was destroyed too soon before the allreduce finishes.</p>
<p>We can rule out 2 for now, as all_reduce does recordStream() properly to prevent CUDA blocks to be freed too early.</p>
<p>Then the only thing left is 1. The operation on that tensor before allreduce is <code>bucket_view.copy_(grad.view({-1}), /* non_blocking */ true);</code> in <code>mark_variable_ready_dense</code>. The copy here happens on the same device (replica.contents and grad). And Reducer itself does not switch streams in between. So the only case that could hit race condition is when the application used different streams for different operators during the forward pass, and grads associated with those operators fall into the same bucket in reducer.</p>