我正在用 Python 和 C 编写一个带有一些复杂物理模拟算法的科学程序。在实现算法之后,我发现有很多可能的优化来提高性能。常见的是预先计算值,使计算脱离循环,用更复杂的矩阵算法替换简单的矩阵算法等。但是出现了一个问题。未经优化的算法要慢得多,但它的逻辑和与理论的联系看起来更加清晰易读。此外,扩展和修改优化算法也更加困难。
所以,问题是——在提高性能的同时,我应该使用什么技术来保持可读性?现在我试图保持快速和清晰的分支并并行开发它们,但也许有更好的方法?
我正在用 Python 和 C 编写一个带有一些复杂物理模拟算法的科学程序。在实现算法之后,我发现有很多可能的优化来提高性能。常见的是预先计算值,使计算脱离循环,用更复杂的矩阵算法替换简单的矩阵算法等。但是出现了一个问题。未经优化的算法要慢得多,但它的逻辑和与理论的联系看起来更加清晰易读。此外,扩展和修改优化算法也更加困难。
所以,问题是——在提高性能的同时,我应该使用什么技术来保持可读性?现在我试图保持快速和清晰的分支并并行开发它们,但也许有更好的方法?
你的问题是一个非常好的问题,几乎在每一段代码中都会出现,无论是简单还是复杂,都是由任何想称自己为专业人士的程序员编写的。
我试图记住并牢记,新阅读我的代码的读者对问题的粗略看法和我最初拥有的相同直接(可能是蛮力)方法。然后,随着我对问题的深入理解和解决方案的路径变得更加清晰,我尝试写出反映更好理解的评论。我有时会成功,这些评论对读者有帮助,尤其是当我六周后回到代码时,它们对我很有帮助。无论如何,我的风格是写大量评论,当我不写评论时(因为:突然的洞察力让我兴奋;我想看到它运行;我的大脑被炸了),我几乎总是在以后非常后悔。
如果我可以维护两个并行代码流,那就太好了:天真的方式和更复杂的优化方式。但我从来没有成功过。
对我来说,最重要的是,如果我能写出清晰、完整、简洁、准确和最新的评论,那就是我能做的最好的了。
还有一件你已经知道的事情:优化通常并不意味着将大量代码硬塞到一个源代码行上,也许是通过调用一个函数,其参数是另一个函数,其参数是另一个函数,其参数是另一个函数。我知道有些人这样做是为了避免暂时存储函数的值。但是它对加速代码的作用很小(通常什么都没有),而且它是一个婊子。你没有消息,我知道。
通常假设您必须放弃可读性才能获得性能。
不一定如此。
您需要找出花费大量时间在做什么,为什么?
请注意,我没有说您需要进行任何测量。
很有可能您可以进行一些简单的更改以避免浪费运动,但在程序本身告诉您要修复的内容之前不要修复任何东西。
def whatYouShouldDo(servings, integration_method=oven):
"""
Make chicken soup
"""
# Comments:
# They are important. With some syntax highlighting, the comments are
# the first thing a new programmer will look for. Therefore, they should
# motivate your algorithm, outline it, and break it up into stages.
# You can MAKE IT FEEL AS IF YOU ARE READING TEXT, interspersing code
# amongst the text.
#
# Algorithm overview:
# To make chicken soup, we will acquire chicken broth and some noodles.
# Preprocessing ingredients is done to optimize cooking time. Then we
# will output in SOUP format via stdout.
#
# BEGIN ALGORITHM
#
# Preprocessing:
# 1. Thaw chicken broth.
broth = chickenstore.deserialize()
# 2. Mix with noodles
if not noodles in cache:
with begin_transaction(locals=poulty) as t:
cache[noodles] = t.buy(noodles) # get from local store
noodles = cache[noodles]
# 3. Perform 4th-order Runge-Kutta numerical integration
import kitchensink import * # FIXME: poor form, better to from kitchensink import pan at beginning
result = boilerplate.RK4(broth `semidirect_product` noodles)
# 4. Serve hot
log.debug('attempting to serve')
return result
log.debug('server successful')
另见http://en.wikipedia.org/wiki/Literate_programming#Example
我还听说这是http://en.wikipedia.org/wiki/Aspect-orienting_programming试图提供的帮助,尽管我还没有真正研究过。(这似乎是一种奇特的说法,即“将您的优化和调试以及其他垃圾放在您正在编写的函数之外”。)