[英]Need to use floats for performance yet want double-precision calculations
[英]Most effective Algorithm to find maximum of double-precision values
在一组变量中找到最大值的最有效方法是什么?
我看到了解决方案, 例如
private double findMax(double... vals) {
double max = Double.NEGATIVE_INFINITY;
for (double d : vals) {
if (d > max) max = d;
}
return max;
}
但是,最有效的算法是什么?
如果列表未排序,则无法将复杂度降低到O(n)
以下...但是您可以将常数因子提高很多。 使用SIMD。 例如,在SSE中,您将使用MAXSS
指令在单个周期内执行4位比较+选择操作。 稍微展开循环以降低循环控制逻辑的成本。 然后在循环之外,从SSE寄存器中捕获的四个值中找出最大值。
这对于任何大小的列表都有好处...对于真正的大列表,使用多线程也是有意义的。
假设列表中没有按任何特定顺序排列的元素,那么您在问题中提到的算法是最佳的。 它必须查看每个元素一次,因此花费的时间与列表的大小O(n)
成正比。
没有找到上限小于O(n)
的最大值的算法。
证明:假设有一个矛盾,有一种算法可以在不到O(n)
时间内找到列表的最大值。 然后必须至少有一个它不检查的元素。 如果算法选择该元素为最大值,则对手可能会为该元素选择一个值,使其小于被检查的元素之一。 如果算法选择任何其他元素作为最大值,则对手可能会为该元素选择一个值,使其大于其他元素。 无论哪种情况,该算法都无法找到最大值。
编辑:这是我的尝试答案,但是请看一下@BenVoigt提出了一种优化表达式的更好方法的评论
if (d>max) max=d
(如果有if (d>max) max=d
,找到一个更有效的表达式是一个问题。 假设我们需要列表未排序的一般情况(如果我们将其保持排序,那么我们将在评论中将最后一项选择为@IgnacioVazquez点),然后对分支预测进行一些研究( 为什么处理排序的索引更快?数组比未排序的数组? ,请参阅第4个答案),看起来像
if (d>max) max=d;
可以更有效地重写为
max=d>max?d:max;
原因是,第一个语句通常翻译为分支 ( 尽管它完全依赖于编译器和语言,但是至少在C和C ++中,甚至在Java等基于VM的语言中也会发生 ),而第二个语句则翻译为有条件的行动 。
如果预测出错(必须重置执行管道),则现代处理器在分支机构中将遭受重大损失,而条件移动是原子操作,不会影响管道。
列表中元素的随机性质(一个概率可以相等于大于或小于当前最大值)将导致许多分支预测出错。
请参考链接的问题,对所有这些以及基准进行很好的讨论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.