定制设计算法的好处
Posted
技术标签:
【中文标题】定制设计算法的好处【英文标题】:Benefits of Custom Designed Algorithms 【发布时间】:2012-02-22 23:04:35 【问题描述】:在许多语言中,特别是对我而言,Java 和 C++,都有一个庞大的标准库。在这个库中实现了计算机科学、搜索、排序、散列等方面的许多经典问题。我的问题是,说实现自己的算法与简单地使用库的版本相比有什么好处吗?有没有什么特别的例子是这样的?
我之所以这么问,是因为在学校里大量的时间都花在了排序上,但是在我的实际代码中,当人们已经在 Java 和 C++ 中实现和优化了排序算法时,我发现没有理由利用这些知识。
编辑:我与我认识的一位教授详细讨论了这个问题,并发布了他的回复,有人能想出更多补充吗?
【问题讨论】:
这些库通常不带有非比较排序,公平地说,这并不经常有用,但是当它们出现时,它们几乎总是比任何排序都快得多在图书馆。 这类似于常见的“我为什么需要数学?” 在开发新事物之前先了解现有技术非常有用,实际上几乎是必要的。想象一下,一位从未研究过标志性建筑和重要建筑是如何设计的建筑师……扩展类比,一个人可能会出于某些目的采用现成的设计,并为另一种目的设计一些衍生的或新的东西。很难一概而论,但是如果不研究以前的作品,您将无法做到很多ab novo。此外,许多追求需要开发其他人尚未看到的东西。 【参考方案1】:大多数时候,库存库函数的性能将比您自定义代码的任何内容都高。
如果您有一个非常具体(而不是一般)的问题,您可能会通过编写专门的函数来提高性能,但作为开发人员,您应该有意识地努力不要“重新发明***”。
【讨论】:
【参考方案2】:排序是一个很好的例子。如果您对要排序的数据一无所知,除了如何比较元素之外,那么标准的排序算法会很好。在这种情况下,在 C++ 中,STL 排序就可以了。
但有时您对自己的数据了解得更多。例如,如果您的数据由均匀分布的数字组成,那么基数排序会快得多。但是从某种意义上说,基数排序是“侵入性的”,它需要更多地了解您的数据,而不仅仅是一个数字是否大于另一个数字。这使得编写每个人都可以共享的通用接口变得更加困难。所以 STL 缺少基数排序,在这种情况下,您可以通过编写自己的代码来做得更好。
【讨论】:
【参考方案3】:一般来说,标准库包含非常快速的代码来解决非常普遍的问题。如果你有一个特定的问题,你可以在很多情况下比图书馆做得更好。当然,您最终可能会遇到图书馆无法解决的复杂问题,在这种情况下,您从研究解决问题的解决方案中获得的知识可能会被证明是无价的。
【讨论】:
【参考方案4】:在大学或学校,或者如果作为一名休闲程序员学习,你会(或者在我强烈的意见中,你应该)被鼓励自己实现这些东西的一个子集。为什么?学习。对我来说,实现一个重要的已经发明的***(B 树)是我在大学期间最形成性的经历之一。
我当然同意,作为开发人员,您应该努力不要重新发明***,但是当通过形成性经验学习时,适用不同的规则。我在这个论坛的其他地方读到,要使用抽象级别 N 的东西,拥有抽象级别 N-1 的工作知识并熟悉级别 N-2 是一个非常好的主意。我会同意的。除了形成性之外,它还可以让您在确实遇到库存库不合适时遇到问题的那一天做好准备。相信我,这可能发生在你 50 年的职业生涯中。如果您正在学习诸如 data structures
之类的基础知识,最终目标不是完成产品的完整性,而是自我改进,那么“重新发明***”是值得的。
【讨论】:
【参考方案5】:预代数/代数/三角学/微积分值得学习吗?
我不知道这是一个“我在学校浪费我的时间/金钱”的目标问题,还是一个真诚的问题,即你自己的版本是否会更好。
至于在学校浪费你的时间/金钱:如果你只想在开发一个有用的应用程序上大吃一惊,那么学习这些已经实现的算法绝对是在浪费你的时间——你只需要将一些效果很好的东西拼凑在一起。
另一方面,如果您正在尝试制作一些真正重要的东西,需要快速,并且需要成为正确工作的正确工具 - 那么它通常不存在,而您会回到 Stack Overflow 等网站,询问第一年或第二年的计算机科学问题,因为您对现有技术不够熟悉,无法推出自己的变体。
根据我的工作,我一直在两边。我需要快速开发它,还是必须运行良好?对于快速应用程序编程,除非有我绝对必须解决的性能或功能障碍,否则它的库存功能很多。对于专业的游戏编程,它必须快速运行。那时,真正的知识开始进入内存管理、IO 访问优化、计算几何、低级和算法优化,以及各种巧妙的乐趣。而且很少有股票实现可以完成工作。
我是在学校学到的大部分内容吗?不,因为已经知道其中的大部分内容,但毫无疑问,学位有所帮助。另一方面,您不了解其中的大部分内容(否则您不会问),所以是的,简而言之:这是值得的。
一些具体的例子:
如果您想制作真正令人惊叹的游戏,请使用实时和呼吸算法,这样您就可以编写其他人无法编写的代码。如果您想制作不是特别令人惊叹的有趣游戏,请使用股票代码并专注于设计。它有限制,但发展速度更快。
如果您想对嵌入式设备(一个相当大的市场)进行编程,通常库存代码是行不通的。通常存在库实现无法满足的代码或数据内存限制。
如果您需要适度的硬件提供出色的服务器性能,库存代码将无法满足要求。 (See this Slashdot entry.)
如果您想进行任何有趣的手机开发,资源紧缩要求您变得聪明,甚至经常用于“无聊”的应用程序。 (用户体验就是一切,大量数据的股票排序功能通常太慢了。)
您被限制使用的库通常不能满足您的需要。 (例如,C# 没有“稳定”的排序方法。我一直遇到这种烦恼,并编写了自己的解决方案。)
如果您正在处理大量数据(现在大多数企业都有),您最终会遇到界面太慢并且需要一些巧妙的变通办法的情况,通常需要很好地使用自定义数据结构。
【讨论】:
【参考方案6】:这些库为您提供经过测试且运行良好的实现,因此经验法则是使用这些实现。如果您有一个非常特殊/复杂的问题,您可以在其中使用一些领域知识,那么您有一个案例是您需要实现自己的算法版本。
我记得 Bill Pugh 在他的编程语言课上给出的一个例子,他们分析了一个复杂应用程序的性能,他们意识到程序员对排序算法的错误自定义实现(该代码在实际运行中多次使用)应用程序)导致 90% 的性能下降!
【讨论】:
【参考方案7】:在与计算机科学教授详细讨论后,他的意见如下:
使用库的原因
1.您正在编写有截止日期的代码。
妨碍您快速及时地完成项目的能力是没有意义的。这就是为什么编写库毕竟是为了节省时间并避免“重新发明***”2.如果你想全面优化你的代码。
很有可能是一群才华横溢的人,他们用 Java 或 C++ 编写了算法,或者任何人的库在优化该语言的算法方面做得比你可能在一两个小时内完成的时间要好得多.或者四个。3.你已经解决了这个问题。
如果您已经解决了这个问题,并且对它的设计方式有很好的全面了解,那么您就不需要费力地研究复杂的解决方案,因为您不会获得太多好处。话虽如此,仍有很多理由需要自己制定解决方案。
自己动手的理由
1.一旦遇到通过非库解决方案更好地优化的问题,就完全有必要对问题解决技术和算法有基本的了解。
如果您有一个高度明确的问题,那么在使用网络或游戏等时经常会出现此类问题。能够发现特定算法将优于库版本的情况变得非常宝贵。2. 对算法及其设计和使用有很好的理解会让你在工作中更有价值。
任何中庸的程序员都可以编写一个函数来比较两个对象,然后将它们放入库函数中,但是能够发现情况并最终提高程序功能和速度的程序员将受到好评管理。3. 拥有如何做某事的概念通常比能够做到这一点更有价值。
凭借对 Java 库以及如何使用它们的出色知识,您很有可能可以成功解决 Java 中的任何问题。但是,当您被聘用在 erlang 中工作时,您将面临一些艰难的时期。如果您知道 Java 库的作用,而不仅仅是知道 Java 库的作用,您就可以将这些想法转移到任何语言中。4.作为程序员,我们永远不会真正满足于仅仅有一些“工作”。
您很可能很想了解为什么会起作用。可能正是这种好奇心驱使你进入这个研究领域。不要否认这种好奇心!鼓励它并随心所欲地学习。5. 最后,创建自己的排序或散列等个人方式会带来巨大的成功和成就感。
想象一下,当您宣称您可以在n log(n)
时间内找到两个顶点之间的最短路径时,您的朋友会看到您多么酷!严肃地说,知道您完全有能力理解并根据知识选择最佳解决方案是非常有益的。不是某些图书馆给你的。
【讨论】:
以上是关于定制设计算法的好处的主要内容,如果未能解决你的问题,请参考以下文章