Optimizing speed of specific CNN (repetitive procedure)

username: mflova
cooked: <p>Hi!<br>
I am currently implementing the Monte Carlo sampling in order to calculate not only the output of the network but also its variance. To do so, it is needed to run the CNN with dropout enabled and input the same image like 20 times (which is, of course, 20 time slower compared to typical method). These outpus then are processed to obtain the mean and variance of the prediction.Right now the idea is working, but it takes 0.5s/image with following execution:</p>
<p>outputs = [net(inputs) for i in range(20)]</p>
<p>Is there a faster way to execute this? I thought about building batches with 20 images repeated, but I guess that the dropout will be the same for rsch batch, obtaining 20 times the same output per batch.<br>
Maybe anything related to parallelism?</p>

username: ptrblck
cooked: <p><code>nn.Dropout</code> will apply a mask to each sample separately as seen here:</p>
<pre><code class="lang-python">drop = nn.Dropout()
x = torch.ones(20, 2)
out = drop(x)
print(out)
</code></pre>
<p>However, if you are using a batched input, the batchnorm statistics would be different (in case you are using batchnorm layers).</p>

username: mflova
cooked: <p>Oh, that information was very useful, I didn’t know how to check it out at all.<br>
So supposing that I am obtaining the samples one by one with an iterator:</p>
<blockquote>
<p>for i in range(loops):<br>
try:<br>
inputs, targets = next(dataloader_iterator)<br>
except StopIteration:<br>
dataloader_iterator = iter(dataloader)<br>
inputs, targets = next(dataloader_iterator)</p>
<pre><code>      inputs, targets = inputs.to(device), targets.to(device)
</code></pre>
</blockquote>
<p>Given a single sample per iteration [target(i) and inputs(i)], which one is the fastest way to build a batch with these x20 inputs(i) and x20 targets(i)? This is my last step but I am not able to create it in an efficient way<br>
Thank you very much</p>

username: ptrblck
cooked: <p>If you use <code>batch_size=20</code> in your <code>DataLoader</code>, the created outputs should already be batches with 20 samples.</p>
<p>Please let me know, if I misunderstood the question.</p>

username: mflova
cooked: <p>Sorry I didn’t explain so well then.<br>
In a real world situation, each frame will be recorded by a camera. In terms of processing, I would like to create a batch with N times this same frame in order to feed this entire block into the network (with dropout enabled) and take advantage of parallelims of Cuda API:</p>
<blockquote>
<p>outputs = net(batch_frame)</p>
</blockquote>
<p>I have made some tests and the upper quote seems to be faster than the original approach (below):</p>
<blockquote>
<p>outputs = [net(frame) for i in range(N)]</p>
</blockquote>
<p>In which the frame is feeded N times into the network (but this time not in parallel).<br>
The problem is that I don’t know how I can create a batch with N times the same image</p>

username: ptrblck
cooked: <p>Assuming that each image tensor has the shape <code>[channels, height, width]</code>, you could use <code>expand</code> or <code>repeat</code> to create a tensor with the shape <code>[20, channels, height, width]</code>:</p>
<pre><code class="lang-python">x = torch.randn(3, 224, 224)

x = x.unsqueeze(0)
x1 = x.expand(20, -1, -1, -1)
print(x1.shape)
&gt; torch.Size([20, 3, 224, 224])

# or
x2 = x.repeat(20, 1, 1, 1)
print(x2.shape)
&gt; torch.Size([20, 3, 224, 224])
</code></pre>
<p>The former case would only manipulate the meta data (stride and shape), while the latter would trigger a copy.</p>