Is there any faster way to rounding a tensor?

username: Eta_C
cooked: <p>Run:<br>
<code>torch.round(torch.tensor([-0.6, -0.5, -0.4, 0.4, 0.5, 0.6]))</code></p>
<p>Got:<br>
<code>tensor([-1., -0., -0., 0., 0., 1.])</code>.</p>
<p>Expect:<br>
<code>tensor([-1., -1., -0., 0., 1., 1.])</code>.</p>
<p>I try:</p>
<pre><code class="lang-auto">x = torch.tensor([-0.6, -0.5, -0.4, 0.4, 0.5, 0.6])
x[x &gt; 0] = torch.floor(x[x &gt; 0] + 0.5)
x[x &lt; 0] = torch.ceil(x[x &lt; 0] - 0.5)
</code></pre>
<p>But it is too slow.<br>
Run this code on 2080TI,</p>
<pre><code class="lang-python">import torch
import time

x = torch.rand(3, 64, 128, 128).float() * 10 - 5
x = x.cuda()
tic = time.time()
x[x &gt; 0] = torch.floor(x[x &gt; 0] + 0.5)
x[x &lt; 0] = torch.ceil(x[x &lt; 0] - 0.5)
toc = time.time()
print(toc - tic)  # 0.008876 (if use torch.round, it will be 0.0006)
</code></pre>
<p>So, is there any faster way to rounding a tensor in my way(<code>0.5 -&gt; 1</code> and <code>-0.5 -&gt; -1</code>)?</p>

username: Eta_C
cooked: <p>OK, finally I build a cpp extension to solve this problem.<br>
But I am also intersted in the python solution <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

username: albanD
cooked: <p>You can always add <code>1e-6</code> to your original Tensor <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"><br>
That should only add a single element-wise operation over the Tensor and won’t have such a bad overhead.</p>

username: Eta_C
cooked: <p>Thanks for your reply. But</p>
<pre data-code-wrap="python"><code class="lang-python">x = torch.tensor([-0.6, -0.5, -0.4, 0.4, 0.5, 0.6])
y = torch.round(x + 1e-6)  # [-1., -0., -0., 0., 1., 1.]
y = torch.floor(x + 1e-6)  # [-1., -1., -1., 0., 0., 0.]
y = torch.ceil(x + 1e-6)  # [-0., -0., -0., 1., 1., 1.]
</code></pre>
<p>All of them are not <code>[-1., -1., -0., 0., 1., 1.]</code>.</p>
<blockquote>
<p>element-wise operation won’t have such a bad overhead</p>
</blockquote>
<p>I tried <code>x = torch.sign(x) * torch.floor(torch.abs(x) + 0.5)</code>. It is indeed faster (a bit).<br>
Thank you.</p>

username: albanD
cooked: <p>Ho right you have negative values as well <img src="https://discuss.pytorch.org/images/emoji/apple/confused.png?v=9" title=":confused:" class="emoji" alt=":confused:"><br>
I’m afraid this is going to be hard to do as fast as round without reimplementing an efficient C kernel for it.</p>
<pre><code class="lang-auto">In [12]: x = torch.tensor([-0.6, -0.5, -0.4, 0.4, 0.5, 0.6])

In [13]: %timeit x.round()
56.9 µs ± 7.92 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [14]: %timeit torch.sign(x) * torch.floor(torch.abs(x) + 0.5)
349 µs ± 4.78 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [16]: %timeit (x + x.sign().float() / 2.).round()
305 µs ± 3.89 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
</code></pre>
<p>Note that these timings may not be representative for larger Tensors though. Or if you’re running on GPU.</p>

username: Eta_C
cooked: <p><code>(x + x.sign().float() / 2.).round()</code> is also incorrect.<br>
Thanks again. I had already known the solution.</p>