thrust :: unique_by_key吃掉最后一个元素

时间:2012-06-17 08:59:02

标签: cuda gpu thrust

请考虑以下简单代码:

thrust::device_vector<int> positions(6);
thrust::sequence(positions.begin(), positions.end());
thrust::pair<thrust::device_vector<int>::iterator, thrust::device_vector<int>::iterator > end;
//copyListOfNgramCounteachdoc contains: 0,1,1,1,1,3
end.first = copyListOfNgramCounteachdoc.begin();
end.second = positions.begin();
for(int i =0 ; i < numDocs; i++){
    end= thrust::unique_by_key(end.first, end.first + 3,end.second);
}

int length = end.first - copyListOfNgramCounteachdoc.begin() ;
cout<<"the value of end -s is: "<<length;
for(int i =0 ; i< length ; i++){
  cout<<copyListOfNgramCounteachdoc[i];
}

我希望输出为此代码的0,1,1,3;但是,输出为0,1,1。任何人都可以让我知道我错过了什么?注意:copyListOfNgramCounteachdoc的内容是0,1,1,1,1,3。 copyListOfNgramCounteachdoc的类型也是thrust::device_vector<int>

编辑:

end.first = storeNcCounts.begin();
    end.second = storeCompactedPositions.begin();
    int indexToWriteForIndexesarr = 0;
    for(int i =0 ; i < numDocs; i++){
        iter = end.first;
        end = thrust::unique_by_key_copy(copyListOfNgramCounteachdoc.begin() + (i*numUniqueNgrams), copyListOfNgramCounteachdoc.begin()+(i*numUniqueNgrams)+ numUniqueNgrams,positions.begin() + (i*numUniqueNgrams),end.first,end.second);
        int numElementsCopied = (end.first - iter);
        endIndex = beginIndex + numElementsCopied - 1;
        storeBeginIndexEndIndexSCNCtoRead[indexToWriteForIndexesarr++] = beginIndex;
        storeBeginIndexEndIndexSCNCtoRead[indexToWriteForIndexesarr++] = endIndex;
        beginIndex = endIndex + 1;
    }

1 个答案:

答案 0 :(得分:1)

我认为在这种情况下您要使用的是thrust::unique_by_key_copy,但请继续阅读。

问题是unique_by_key除非必须更新输入数组。在第一次调用的情况下,它可以通过删除重复1来返回一系列唯一键 - 通过向前移动返回的迭代器,而不实际压缩输入数组。

如果用这个替换你的循环,你可以看到发生了什么:

end.first = copyListOfNgramCounteachdoc.begin();
end.second = positions.begin();
thrust::device_vector<int>::iterator iter;

for(int i =0 ; i < numDocs; i++){
  cout <<"before ";
  for(iter = end.first; iter != end.first+3; iter++) cout<<*iter;

  end = thrust::unique_by_key(end.first, end.first + 3,end.second);

  cout <<" after ";
  for(iter = copyListOfNgramCounteachdoc.begin(); iter != end.first; iter++) cout<<*iter;
  cout << endl;

  for(int i =0 ; i< 6; i++) cout<<copyListOfNgramCounteachdoc[i];
  cout << endl;
}

对于这段代码,我得到了这个输出:

before 011 after 01
011223
before 122 after 0112
011223

您可以看到copyListofNgramCounteachdoc中的值没有变化。这是有效的行为。如果您使用unique_by_key_copy而不是unique_by_key那么Thrust将被迫实际压缩值以保证唯一性,但在这种情况下,因为每个序列中只有两个值,所以没有需要。文档说:

  

返回值是迭代器new_last,因此[first,new_last]范围内没有两个连续元素相等。 [new_last,last]范围内的迭代器仍然可以解除引用,但它们指向的元素未指定。 unique是稳定的,这意味着未被删除的元素的相对顺序不变。

如果您使用unique_by_key_copy,则Thrust将被强制复制唯一键和值(具有明显的成本影响),您应该会看到您期望的行为。

顺便说一句,如果你只需要一次调用unique_by_key而不是循环播放它,我建议你这样做。