有哪些优秀的技巧和/或技巧可用于优化和改进计算繁重程序的性能。我说的是复杂的图形计算或数学和模拟类型的编程,其中每一秒保存都是有用的,而IO重型程序只有一定的加速是有帮助的。
虽然这里经常提到改变算法是最有效的方法,但我试图找出不同算法的有效性,所以我想尽可能多地为每种算法创造效率。我正在解决的“问题”并不是众所周知的,所以网上几乎没有任何算法,但我正在寻找关于如何继续和寻找什么的好建议。
我正在探索进化算法和针对特定一组相关问题的更简单方法之间的有效性差异。我已经为这个问题写了三个进化算法,现在我已经写了一个蛮力技术,我想尽快做出来。
编辑:指定更多内容。我正在使用C#,我的算法都围绕计算和解决表达式的约束类型问题(使用表达式树)。通过表达式,我的意思是像x ^ 2 + 4或其他类似的东西,它们将被解析为表达式树。我的算法都创建和操作这些树,试图找到更好的近似值。但是我想以一般方式提出这个问题,以防它对任何其他人有所帮助。
我试图找出是否有可能编写一个有用的进化算法来寻找各种属性的良好近似表达式。两者都是因为我想知道什么是良好的近似,并看看进化的东西与传统方法的比较。
答案 0 :(得分:3)
这与任何其他优化几乎相同:简介,实验,基准,重复。
首先,您必须弄清楚代码的哪些部分占用了时间。然后尝试不同的方法来加速它们(尝试基于优点的方法比随机尝试更好的想法)。基准测试,看看你是否确实加快了它们的速度。如果您这样做,请将旧方法替换为新方法。再次介绍。
答案 1 :(得分:3)
如果有可能以其他方式做到这一点,我建议不要使用蛮力方法。但是,这里有一些指导方针可以帮助您以任何方式加速代码。
您可以对代码应用许多不同的优化,但在执行任何操作之前,您应该剖析以找出瓶颈所在。以下是一些分析器,可以让您对代码中的热点位置有所了解:
这些都使用抽样来获取数据,因此使用代码运行它们的开销应该是最小的。只有GProf要求您重新编译代码。此外,最后三个允许您同时执行时间和hardware performance counter配置文件,因此一旦您执行了时间(或CPU周期)配置文件,您可以放大更热的区域并找出为什么它们可能运行缓慢(缓存未命中,FP指令计数,等。)。
除此之外,还需要考虑如何最好地重构代码,这取决于问题所在。可能是你刚刚得到一个编译器没有很好地优化的循环,你可以内联或移动循环中的东西以帮助编译器输出。或者,如果你使用基本算术运算尽可能快地运行,你可能想尝试利用向量指令(SSE等)如果你的代码是并行的,你可能会遇到负载平衡问题,你可能需要重构您的代码,以便更好地跨核心分布数据。
这些只是几个例子。性能优化很复杂,如果你开始采用强力方法,它可能对你的帮助不大。
有关人们优化事物的方式的更多信息,最近的 Why do you program in assembly? 问题中有一些相当不错的例子。
答案 2 :(得分:2)
如果您的优化问题是(准)凸或可以转换为这样的形式,那么算法比进化搜索更有效。
如果您有大型矩阵,请注意线性代数例程。正确的算法可以使计算时间减少一个数量级,特别是如果你的矩阵很稀疏。
考虑如何将数据加载到内存中。即使你认为你把大部分时间花在纯算术上,你实际上也花了很多时间在缓存等级之间移动东西。尽可能多地利用数据来处理最快的内存。 / p>
尽量避免不必要的内存分配和解除分配。在这里,从纯粹的OO方法中退出是有意义的。
答案 3 :(得分:1)
这更像是在算法本身找到漏洞的一个提示......
要实现最高性能,请以最重要的方式简化内部循环中的所有内容。
保持简单的一个例子是经典的弹跳球动画。您可以通过在物理手册中查找定义并插入数字来实现重力,或者您可以这样做并节省宝贵的时钟周期:
initialize:
float y = 0; // y coordinate
float yi = 0; // incremental variable
loop:
y += yi;
yi += 0.001;
if (y > 10)
yi = -yi;
但是现在让我们说你必须在N体仿真中使用嵌套循环来做这件事,其中每个粒子都吸引到其他所有粒子。当你处理成千上万的粒子时,这可能是一个非常耗费处理器的任务。
当然,您应该采用相同的方法来简化最内部循环中的所有内容。但更重要的是,在最简单的层面上,您还应该明智地使用数据类型。例如,使用整数而不是浮点变量时,数学运算更快。此外,加法比乘法更快,乘法比除法快。
因此,考虑到所有这些,您应该能够主要使用整数的加法和乘法来简化最内部的循环。然后,您可能需要做的任何缩小都可以在之后完成。以y和yi为例,如果yi是你在内部循环中修改的整数,那么你可以在循环之后缩小它,如下所示:
y += yi * 0.01;
这些是非常基本的低级别性能提示,但无论何时我使用处理器密集型算法,我都会记住它们。当然,如果您接受这些想法并将其应用于GPU上的并行处理,那么您可以将算法提升到一个全新的水平。 =)
答案 4 :(得分:0)
你如何做到这一点取决于哪种语言最多 您正在使用。仍然是任何语言的关键 在探查器中。描述您的代码。看哪个 功能/操作花费最多时间然后确定 如果你能使这些昂贵的操作更有效率。
数值算法的标准瓶颈是记忆 用法(您是否按元素的顺序访问矩阵 存储在存储器中);沟通开销等。他们 可能与其他非数字程序有点不同。
此外,许多其他因素,如预处理等。 可以导致性能行为的巨大差异 相同问题的SAME算法。确保 您可以确定实施的最佳参数。
至于比较不同的算法,我建议 阅读论文
“具有性能配置文件的基准优化软件” JorgeMoré和Elizabeth D. Dolan,数学规划91(2002),201-213。
它提供了一种比较不同算法的漂亮,统一的方法 适用于同一问题集。真的应该更好地了解它 在优化社区之外(在我不那么谦虚的意见中) 至少)。
祝你好运!