4

同じサイズの配列のペアがあり、それらをキーと値と呼びます。

例えば:

K: V
1: 99
1: 100
1: 100
1: 100
1: 103
2: 103
2: 105
3: 45
3: 67

キーがソートされ、各キーに関連付けられた値がソートされます。各キーとそれに対応するキーに関連付けられた値の重複を削除するにはどうすればよいですか?

つまり、上記を次のように圧縮します。

1: 99
1: 100
1: 103
2: 103 <-- This should remain, since key is different
2: 105
3: 45
3: 67

Thrustで利用可能なストリーム圧縮関数を見ましたが、これを行うものを見つけることができませんでした。これはスラストで可能ですか?それとも、独自のカーネルを作成して、ステンシル内の重複をマークして削除する必要がありますか?

4

2 に答える 2

3

キーはソートされ、各キーに関連付けられた値もソートされます。したがって、キーと値のペアがソートされていると見なすことができます。thrust::uniqueこれらの 2 つのベクトルを単一のベクトルとして見ることができる場合、これに直接作用します。これは、zip_iterator.

これをインプレースで実現し、キーと値のベクトルを一意の要素のみにトリミングする方法を次に示します。

typedef thrust::device_vector< int >                IntVector;
typedef IntVector::iterator                         IntIterator;
typedef thrust::tuple< IntIterator, IntIterator >   IntIteratorTuple;
typedef thrust::zip_iterator< IntIteratorTuple >    ZipIterator;

IntVector keyVector;
IntVector valVector;

ZipIterator newEnd = thrust::unique( thrust::make_zip_iterator( thrust::make_tuple( keyVector.begin(), valVector.begin() ) ),
                                     thrust::make_zip_iterator( thrust::make_tuple( keyVector.end(), valVector.end() ) ) );

IntIteratorTuple endTuple = newEnd.get_iterator_tuple();

keyVector.erase( thrust::get<0>( endTuple ), keyVector.end() );
valVector.erase( thrust::get<1>( endTuple ), valVector.end() );

圧縮して別の結果ストリームを生成したい場合は、タプルの両方の要素を調べる、タイプの独自のバイナリ述語を記述する必要があります。を使用して、個別のthrust::zip_iterator配列から仮想タプル イテレータを形成できます。

それを行う方法の完全な動作例は次のようになります。

#include <iostream>
#include <thrust/tuple.h>
#include <thrust/functional.h>
#include <thrust/device_vector.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/unique.h>

// Binary predicate for a tuple pair
typedef thrust::tuple<int, int> tuple_t;
struct tupleEqual
{
  __host__ __device__
    bool operator()(tuple_t x, tuple_t y)
    {
      return ( (x.get<0>()== y.get<0>()) && (x.get<1>() == y.get<1>()) );
    }
};

typedef thrust::device_vector<int>::iterator  intIterator;
typedef thrust::tuple<intIterator, intIterator> intIteratorTuple;
typedef thrust::zip_iterator<intIteratorTuple> zipIterator;
typedef thrust::device_vector<tuple_t>::iterator tupleIterator;

int main(void)
{
  thrust::device_vector<int> k(9), v(9);
  thrust::device_vector<tuple_t> kvcopy(9);

  k[0] = 1; k[1] = 1; k[2] = 1; 
  k[3] = 1; k[4] = 1; k[5] = 2;
  k[6] = 2; k[7] = 3; k[8] = 3;

  v[0] = 99;  v[1] = 100; v[2] = 100;
  v[3] = 100; v[4] = 103; v[5] = 103;
  v[6] = 105; v[7] = 45;  v[8] = 67;

  zipIterator kvBegin(thrust::make_tuple(k.begin(),v.begin()));
  zipIterator kvEnd(thrust::make_tuple(k.end(),v.end()));
  thrust::copy(kvBegin, kvEnd, kvcopy.begin());

  tupleIterator kvend = 
        thrust::unique(kvcopy.begin(), kvcopy.end(), tupleEqual());

  for(tupleIterator kvi = kvcopy.begin(); kvi != kvend; kvi++) {
    tuple_t r = *kvi;
    std::cout << r.get<0>() << "," << r.get<1>() << std::endl;
  }

  return 0;
}
于 2011-04-02T08:30:57.827 に答える
1

少し準備をしてストリーム圧縮を行います。基本的に、キーと値のペアごとにスレッドを起動し、前のキーと値のペアが等しいかどうかを確認し、そうでない場合は、それらのペアと同じサイズの別の配列にフラグ (int = 1) を設定します。他のすべてのフラグは未設定のままです (int = 0)。次に、フラグ配列に基づいてキーと値のペアのストリーム圧縮を行います。

于 2011-04-02T07:17:39.150 に答える