Тяга: sort_by_key с производительностью zip_iterator - PullRequest
3 голосов
/ 22 апреля 2011

Задача

Я использую sort_by_key, а значения передаются с помощью zip_iterator. Этот sort_by_key вызывается много раз, и после определенной итерации он становится в 10 раз медленнее ! В чем причина этого падения производительности ?

Симптом

Я сортирую 3 вектора, используя sort_by_key, один из которых выступает в качестве ключевого вектора:

struct Segment
{
  int v[2];
};

thrust::device_vector<int> keyVec;
thrust::device_vector<int> valVec;
thrust::device_vector<Segment> segVec;

// ... code which fills these vectors ...

thrust::sort_by_key( keyVec.begin(), keyVec.end(),
                     make_zip_iterator( make_tuple( valVec.begin(), segVec.begin() ) ) );

Размер вектора обычно составляет около 4 миллионов. В начальные 2 раза он вызывается, sort_by_key занимает 0,04 с, в цикле 3 - 0,1 с, а затем ухудшается до 0,3 с для остальных циклов. Таким образом, мы видим снижение производительности в 10 раз.

Дополнительная информация

Чтобы гарантировать, что единственным фактором деградации был sort_by_key, я заменил вышеперечисленное на ручную сортировку с использованием рукописного ядра:

thrust::device_vector<int> indexVec( keyVec.size() );
thrust::sequence( indexVec.begin(), indexVec.end() );

// Sort the keys and indexes
thrust::sort_by_key( keyVec.begin(), keyVec.end(), indexVec.begin() );

thrust::device_vector<int> valVec2( keyVec.size() );
thrust::device_vector<Segment> segVec2( keyVec.size() );

// Use index array and move vectors to destination
moveKernel<<< x, y >>>(
  toRawPtr( indexVec ),
  indexVec.size(),
  toRawPtr( valVec ),
  toRawPtr( segVec ),
  toRawPtr( valVec2 ),
  toRawPtr( segVec2 ) );

// Swap back into original vectors
valVec.swap( valVec2 );
segVec.swap( segVec2 );

Эта рукописная сортировка занимает 0,03 с, и эта производительность одинакова на всех итерациях, в отличие от падения производительности, наблюдаемого в sort_by_key и zip_iterator.

1 Ответ

1 голос
/ 22 апреля 2011

Для точной синхронизации каждого цикла вам нужно использовать cudaThreadSynchronize в конце каждого цикла.Время, которое вы получаете за первые два цикла, может не совпадать с тем, которое вы ищете.

...