Is it a bug for torch.unique on gpu?

daiwx2002: <p>How can I get the unique value of an array without changing the sequence of elements in the array?<br>
for example, for array [5,5,3,3,4,4]<br>
If I use torch.unique direct on gpu, the result is always asendingly sorted: [3,4,5]<br>
If I use torch.unique on cpu, the result is still not correct: [4,3,5]<br>
Only numpy.unique can get what I wanted: [5,3,4]<br>
So is this a bug of torch.unique?</p>
<h1>code to test:</h1>
<p>import torch<br>
import numpy as np<br>
c=torch.tensor([5,5,3,3,4,4]).cuda()<br>
print('raw array on gpu: '+str( c ))<br>
d=torch.unique( c )<br>
print('unique by torch.unique on gpu: '+str(d))<br>
c2=c.cpu()<br>
d2=torch.unique(c2)<br>
print('unique by torch.unique on cpu: '+str(d2))<br>
c3=c2.numpy()<br>
d3,i=np.unique(c3,return_index=True)<br>
d3=d3[np.argsort(i)]<br>
print('unique by numpy: '+str(d3))</p>

ptrblck: <p>The GPU implementation works currently with a sorted array, such that the <code>sorted</code> argument is ignored.<br>
If <code>sorted</code> is set to <code>False</code>, the CPU implementation uses <code>std::unordered_set</code> if the <code>dim</code> argument is skipped (which does not guarantee any order) or a sorted tensor and the “slow-pointer/fast-pointer” implementation, if the <code>dim</code> argument is specified.</p>
<p>What is your current use case? Maybe we could use the inverse indices to fix your use case.</p>

daiwx2002: <p>Thanks for your answer.<br>
Yeah. I think the inverse indices will fix my case exactly, but the unique function of GPU implementation currently is not able to do it, also I cannot find a subsitute for it. I hope it can be fixed soon.</p>

ptrblck: <p>The GPU version also provides the inverse indices if you specify <code>return_inverse=True</code>. What would you like to do exactly which is not working currently?</p>

daiwx2002: <p>I want to get the output as :<br>
[5, 3, 4]<br>
if  the input is:<br>
torch.tensor([5,5,3,3,4,4]).cuda()</p>

ptrblck: <p>This code should work:</p>
<pre><code class="lang-python">x = torch.tensor([5,5,3,3,4,4])
x_unique = torch.unique(x, sorted=True)
x_idx = (torch.cat([(x==x_u).nonzero()[0] for x_u in x_unique])).sort()[0]
print(x[x_idx])
&gt; tensor([5, 3, 4])
</code></pre>

daiwx2002: <p>Thanks.<br>
The code works, but its not efficient.<br>
I mean that the function torch.unique should have got the answer I want</p>

enemis: <p>Stumbled upon this now as well. If there is different behaviour, maybe include a warning or similar? I am often changing between gpu and cpu, and this error would not have been expected.</p>
<p>Also, for my case (5x5 tensors), it was significantly faster to transform to cpu and do the sort there and  back again.</p>
<pre><code class="lang-auto">def unique_via_cpu(x, device):
    return torch.unique(x.cpu(), sorted=False).to(device)
</code></pre>
<p>Compared to the function posted above by <a class="mention" href="/u/ptrblck">@ptrblck</a>:<br>
118 µs ± 1.05 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)<br>
vs.<br>
2.86 ms ± 31.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)</p>

ptrblck: <p>Maybe setting the default to <code>sorted=True</code> would prevent your issues.</p>
<p>Anyway, we are currently working on some performance regressions, so that you should see some improvements in the next couple of days. Sorry for the inconvenience.</p>