我最近阅读了关于快速sqrt计算的an article。因此,我决定让SO社区及其专家帮助我找出哪些STL算法或数学计算可以通过编程黑客更快地实现?
如果您可以提供示例或链接,那就太棒了。
提前致谢。
答案 0 :(得分:9)
系统库开发人员关注的不仅仅是考虑性能:
正确性和标准合规性:严重!
一般用途:不会引入任何优化,除非它们使大多数用户受益。
可维护性:良好的手写汇编代码可以更快,但你看不到多少。为什么呢?
便携性:体面的库应该可以移植到不仅仅是Windows / x86 / 32bit。
您看到的许多优化黑客违反了上述一项或多项要求。 此外,当下一代CPU即将到来时,优化将无用甚至中断,不是一件受欢迎的事情。
如果您没有关于真正有用的探查器证据,请不要打扰优化系统库。如果你这样做,那么首先要处理你自己的算法和代码......
编辑:
我还应该提到其他一些包罗万象的问题:
利润/结果比的成本/努力:优化是一种投资。其中一些看似令人印象深刻的泡沫。从长远来看,其他人更深入,更有效。必须始终考虑它们的益处与开发和维护它们的成本有关。
营销人员:无论你怎么想,你最终会做任何他们想做的事情 - 或者认为他们想要的。
答案 1 :(得分:7)
对于特定的问题域,可能所有这些都可以更快。
现在真正的问题是,你应该加速哪些更快?没有,直到分析器告诉你。
答案 2 :(得分:2)
这是您真正需要倾听项目经理和MBA的地方。你建议的是重新实现STL和/或标准C库的部分内容。这样做的实施时间和维护负担都会产生相关的成本,因此除非你真正需要,否则你不应该这样做,正如约翰所指出的那样。规则很简单:这个计算你正在减慢你的速度(a.k.a.你受到CPU的约束)?如果没有,请不要仅仅为了它而创建自己的实现。
现在,如果你对快速数学真的很感兴趣,那么你可以从一些地方开始。 gnu multi-precision library实现了modern computer arithmetic和semi numerical algorithms中的许多算法,这些算法都是关于对任意精度整数和浮点数进行数学运算。编写它的人在每个构建平台的程序集中进行优化 - 它的速度与单核模式下的速度一样快。这是我可以想到的最优化数学的最一般情况,即不是特定于某个域的。
将我的第一段和第二段与thkala所说的相提并论,考虑到GMP / MPIR已针对每个cpu架构和它们支持的操作系统优化了装配版本。真。这是一项很重要的工作,但它正是使这些库在编程问题的特定小部分上如此快速的原因。
有时可以进行特定于域的增强。这是关于理解有问题的问题。例如,在执行finite field arithmetic under rijndael's finite field时,您可以根据特征多项式为2且具有8个项的知识,假设您的整数大小为uint8_t
,并且该加法/减法等效于{{1}操作。这是如何运作的?基本上,如果你加上或减去多项式的两个元素,它们包含零或一个。如果它们都是零或两者都是,则结果始终为零。如果它们不同,结果就是一个。逐项,相当于8位二进制字符串中的xor,其中每个位表示多项式中的项。乘法也相对有效。你可以打赌,rijndael旨在利用这种结果。
这是一个非常具体的结果。这完全取决于你为提高效率所做的工作。我无法想象许多STL函数纯粹针对cpu速度进行了优化,因为STL提供了以下内容:通过模板集合,这些集合是关于内存,文件访问是关于存储,异常处理等等。简而言之,真正快速是一个STL的优势和目标是实现目标。此外,您应该注意优化有不同的视图。例如,如果您的应用程序在IO上很重,那么您就是IO绑定的。具有高效的平方根计算并不是很有用,因为“慢”实际上意味着等待磁盘/ OS /您的文件解析例程。
简而言之,您作为STL库的开发人员正在尝试为许多不同的用例构建“全面”库。
但是,由于这些事情总是很有趣,你可能会对bit twiddling hacks感兴趣。我不记得我在哪里看到了这个,但我肯定从这里的其他人那里窃取了这个链接。
答案 3 :(得分:2)
<algorithm>
中的一些算法可针对vector<bool>::[const_]iterator
进行优化。其中包括:
find
count
fill
fill_n
copy
copy_backward
move // C++0x
move_backward // C++0x
swap_ranges
rotate
equal
我可能错过了一些。但是所有上述算法都可以优化,一次只能处理多个位,而不是一次只能处理一个位(就像一个简单的实现一样)。
这是我怀疑大多数STL实现都非常缺少的优化。这一点并不缺少:
答案 4 :(得分:1)
几乎没有。标准库按照原因设计。
以您提到的sqrt
为例,标准库版本尽可能快地编写,而不会牺牲数值准确性或可移植性。
你提到的那篇文章实在是太无用了。 是在网上浮动的一些好文章,描述了实现平方根的更有效方法。但是这篇文章不在其中(它甚至没有衡量所描述的算法是否更快!)Carmack的诀窍是慢而不是现代的std::sqrt
CPU,以及不太准确。
它曾在12年前的游戏中使用,当时CPU具有非常不同的性能特征。它的速度更快,但是CPU已经发生了变化,而今天,它比CPU的内置sqrt
指令更慢,更准确。
你可以实现比std::sqrt
更快的平方根函数,而不会失去准确性,但是你会失去可移植性,因为它依赖于旧CPU上没有的CPU功能。
速度,准确性,便携性:选择任意两种。标准库试图平衡所有这三个,这意味着如果你愿意牺牲准确性或可移植性,速度不是很好,而且准确性很好,但是如果你愿意的话可能没那么好牺牲速度,等等。
通常,忘记优化标准库的任何概念。您应该询问的问题是您是否可以编写更多专用代码。
标准库必须涵盖每个案例。如果您不需要,您可以加速您需要的案例。但它不再是标准库的合适替代品。
现在,毫无疑问标准库的部分内容可以进行优化。特别想到C ++ IOStreams库。它通常是天真的,而且非常低效地实施。 C ++委员会关于C ++性能的技术报告有一整章专门探讨如何实现IOStreams 更快。
但那是I / O,其中性能通常被认为是“不重要的”。
对于标准库的其余部分,您不太可能找到很多优化空间。