推力:sort_by_key 与 zip_iterator 性能

Posted

技术标签:

【中文标题】推力:sort_by_key 与 zip_iterator 性能【英文标题】:Thrust: sort_by_key with zip_iterator performance 【发布时间】:2011-08-10 19:58:45 【问题描述】:

问题

我正在使用 sort_by_key 并使用 zip_iterator 传递值。这个sort_by_key 被调用了很多次,经过一定的迭代,它变成了10x 性能下降的原因是什么?

症状

我正在使用sort_by_key 对 3 个向量进行排序,其中一个作为关键向量:

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() ) ) );

向量的大小通常在 400 万左右。在最初的 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 看到的性能下降不同。

【问题讨论】:

这仍然是 Thrust 1.6 的问题吗? 【参考方案1】:

为了在每个循环中准确计时,您需要在每个循环结束时使用 cudaThreadSynchronize。您获得的前两个循环的时间可能不是您正在寻找的实际时间。

【讨论】:

Pavan:我在记录时间之前使用的是 cudaThreadSynchronize,并且时间使用的是 Windows 高分辨率计时器 API。

以上是关于推力:sort_by_key 与 zip_iterator 性能的主要内容,如果未能解决你的问题,请参考以下文章

推力::设备向量使用推力::替换或推力::转换与自定义函子/谓词

thrust :: sort_by_key上的配置参数无效

将 cv::cuda::GpuMat 与推力和测试推力 API 一起使用时出现问题

cuda 推力::for_each 与推力::counting_iterator

为啥我不能在使用 sort_by_key 对向量进行排序时使用返回引用的键函数?

将推力与 printf / cout 一起使用