【问题标题】:SIMD Implementation of std::nth_elementstd::nth_element 的 SIMD 实现
【发布时间】:2013-12-07 11:58:19
【问题描述】:

我有一个算法可以在我的双核 3 GHz Intel 处理器上平均运行 250 毫秒,我正在尝试对其进行优化。目前,我有一个 std::nth_element 调用,在 std::vectors 上调用了大约 6,000 次,包含 150 到 300 个元素,平均耗时 50 毫秒。我花了一些时间优化我使用的比较器,它目前从一个向量中查找两个doubles 并进行简单的< 比较。比较器运行std::nth_element 所需的时间可以忽略不计。比较器的复制构造函数也很简单。

由于这个调用目前占用了我算法 20% 的时间,并且由于大部分时间都花在了我没有编写的 nth_element 的代码中(即不是比较器),我想知道是否有人知道使用 SIMD 或任何其他方法优化 nth_element 的方法吗?我已经看到some questions 使用 OpenCL 和多线程并行化 std::nth_element,但是由于向量很短,我不确定我会从这种方法中获得多少好处,尽管我愿意被告知我错了。

如果有 SSE 方法,我可以使用任何 SSE 指令直到(我认为是当前)SSE4.2。

谢谢!

【问题讨论】:

  • @anjruu:前段时间我也遇到过类似的问题(尽管改用floats)。我花了一些时间研究适合 SIMD 的 nth_element 算法,最终决定做一个完整的排序。我使用了AA-sort described in this paper 的“核心”品种。对向量进行完全排序,然后只选择我想要的索引比使用 std::nth_element() 快得多。
  • 您需要确保时间花在执行 nth_element 的代码上,而不是访问包含元素本身的内存。我不知道这些元素有多大,但在我做过的一些详细的性能工作中,基本上开启了处理器实际上是无限快的,而触摸内存真的很费时间。
  • 我想知道对nth_element 的重复调用是否会以某种方式触发分区算法对已经几乎排序的数据的最坏情况行为。作为健全性检查,我肯定会尝试对整个向量进行排序并访问元素。
  • 等等,你是在一个 150 元素的向量上调用 nth_element 6000 次,还是在 6000 个 150 元素的向量上每次调用一次?
  • 除了nth_element和接受的答案中建议的算法之外,您可能还想进行性能测试std::partial_sort,当您只需要在一端只需要很少的元素时,这可能非常有效排序后的序列。此外,nth_element 的实现在实现之间可能会有很大差异。更换供应商可能会对您的绩效产生重大影响。

标签: c++ performance sse simd stl-algorithm


【解决方案1】:

两个想法:

  1. 多线程可能不会加快任何单个向量的处理速度,但随着向量数量的增长可能会有所帮助。

  2. 对于您的问题来说,排序工具太强大了:您正在计算向量的整个顺序,但您只关心前几位。您知道每个向量有多少元素构成前 5%,因此您应该让 one 穿过数组并找到最大的 k,而不是对整个事物进行排序。您可以在O(n) 时间使用k 额外空间来做到这一点,所以总体而言这可能是一场胜利。

【讨论】:

    猜你喜欢
    • 2015-05-22
    • 2012-06-19
    • 1970-01-01
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    相关资源
    最近更新 更多