假设您有2D点数组,并且正在寻找最小/最大边界框。
手动操作会更快些
float min_x = min_y = highest, max_x = max_y = lowest;
for(auto p: points) {
max_x = max(max_x, p.x);
max_y = max(max_y, p.y);
min_x = min(min_x, p.x);
min_y = min(min_y, p.y);
}
或使用C ++工具:
auto[min_x, max_x] =
minmax_element(values.begin(), values.end(), [](auto p1, auto p2) { return p1.x < p2.x; });
auto[min_y, max_y] =
minmax_element(values.begin(), values.end(), [](auto p1, auto p2) { return p1.y < p2.y; });
我想知道从理论上讲哪个应该更快。我不在乎一台特定机器完成它所花费的时间(以毫秒为单位),我想知道在基准测试之前我应该期望这2个中的哪一个更快。
答案 0 :(得分:5)
始终充实C ++标准库中的功能:
由于它的规范非常明确,并且与特定的编译器绑定,因此该编译器可以识别C ++标准库函数并进行优化。也许功能甚至被硬编码到了编译器中?
minmax_element
是因为可以在一次遍历数据中找到其结果。 (实际上,该标准不允许它进行两次单独的遍历。)
答案 1 :(得分:2)
在很酷的算法命运中,找到数组中最小和最大元素的速度比分别找到每个元素的速度更快。一种可行的算法是将元素相互配对,进行比较,然后将较大的元素移入一个淘汰赛以找到最大的元素,将较小的元素移入另一个淘汰赛以找到最小的元素。您可以证明,这将使用大约3n / 2个比较,而不是分别独立地计算max和min,这将需要2n个比较。因此,从这种意义上讲,一起计算最小值和最大值将需要减少大约25%的比较。
关于哪种方法在实践中更快,这取决于您的硬件以及您所拥有的优化编译器的性能。一方面,具有良好优化程序的minmax_element应该生成的代码进行较少的比较,这可能使其比另一种方法更快。另一方面,其他代码是如此简单,以至于优化器可能能够将其展开到某个深度,然后在加快速度方面有所作为。也许比较并不是那么昂贵,而其他因素最终将对效率更加重要。
但是,实际上,除非在紧密的循环中调用此代码,并且您已对代码进行了分析以查看它是程序的瓶颈,否则担心这种细节级别的事情可能不值得投资(查找)。阿姆达尔定律(Amdahl's Law)-您可以量化专注于某件事将获得多少性能改进。力求代码清晰,并在需要时对其进行优化。
答案 2 :(得分:2)
我敢打赌,假设aN += bN
类型的四个语句首先是独立的,然后它们可以并行化,合并和自动向量化,我敢打赌。当存在用于最小/最大的单个指令操作码时(如x64 / simd体系结构),它当然会有所帮助。在这种情况下,有条件地跳过其他比较可能是过早优化的一个示例。而且,一次遍历一个数组应该对大型数组有所不同,因为内存访问通常比ALU操作花费更多。