使用SSE加速lower_bound函数

时间:2011-01-22 20:12:44

标签: c assembly x86 x86-64 sse


在我正在进行的项目中,我经常需要在排序数组中找到可以插入元素的最低可能索引(如C ++中的std :: lower_bound)。 我使用SSE加速我的算法似乎很吸引人,因为我正在使用uint32数组,其大小通常是处理器缓存行的大小。 我之前从未使用过SSE指令,所以我无法弄清楚这个函数的SSE实现会是什么样子。请提供一些提示,以帮助我以最佳方式将其写出来。

1 个答案:

答案 0 :(得分:9)

使用SSE不会像std::lower_bound那样很好地扩展。 SSE使事情变得更快的原因是它允许您一次进行多次计算。例如,单个SSE指令可能导致一次进行4次乘法运算。但是,std::lower_bound操作的方式无法并行化,因为算法中的每个步骤都需要先前步骤的比较结果。此外,它已经是O(lg n),因此不太可能成为瓶颈。

此外,在转向内联汇编之前,您应该知道无论何时使用内联汇编,都会破坏程序中该部分可能出现的大多数编译器优化,并且通常会导致程序变慢 - 通常编译器写出比我们人类更好的汇编程序。

如果您想使用SSE,最好使用 intrinsics - 特殊的“函数”或编译器提供的关键字,它们调用SSE指令但允许进行优化。 Microsoft's Visual C++以及GNU Compiler Collection中提供了此类内在函数。 (可能是大多数编译器。请参阅编译器的文档)

不要试图使用SSE加速std::lower_bound,而应该首先尝试不需要调用它。例如,如果您经常使用lower_bound将元素插入到向量中,您应该知道有效创建的是insertion sort,并且插入排序很差,这将需要四维时间。您可能最好只将新元素放在向量的末尾,然后在需要对其进行排序时对向量进行排序,从而将事物简化为O(n lg n)排序。如果您的数据访问模式过于频繁,那么您应该使用类似std::set的东西,它为插入提供O(lg n)操作,而不是O(n + lg n)插入你现在正在使用这些载体。

当然,请记住基准测试:)