出色的软件设计会降低20%的性能


17

我正在编写一个用于稀疏矩阵计算的小型库,以此来教自己充分利用面向对象的编程。我一直在努力建立一个不错的对象模型,其中各部分(稀疏矩阵和描述其连接结构的图形)之间的耦合非常松散。我个人认为,该代码具有更大的可扩展性和可维护性。

但是,它也比我使用钝器要慢一些。为了测试具有此对象模型的权衡,我编写了一个新的稀疏矩阵类型,该类型打破了基础图的封装,以查看运行的速度有多快。

起初,它看起来很暗淡。我曾经为之骄傲的代码比没有任何精美软件设计的版本慢60%。但是,我能够进行一些低级的优化-内联一个函数并稍微改变一个循环-完全不需要更改API。有了这些更改,现在它仅比竞争对手慢20%。

这使我想到一个问题:如果这意味着我有一个不错的对象模型,我应该接受多少性能损失?


您正在测量哪个稀疏矩阵运算?
比尔·巴特

矩阵向量相乘。矩阵范围在从尺寸。我使它们成为平均度数d = log 2 n的图拉普拉斯算子用于鄂尔多斯-仁伊随机图。另外,在某些机器上20%的数字会变得更糟,所以现在我更倾向于把整个事情扔掉。感叹ñ=102416384d=日志2ñ
Daniel Shapero 2014年

3
您正在使用哪种编程语言?通常,诸如C ++之类的东西将使您以低廉(或不存在)的成本摆脱优雅的设计。在其他没有元编程的语言(Java,Fortran等)中,20%的成本似乎是合理的。
LKlevin 2014年

您能告诉我们您的代码吗?您使用什么语言?什么编译器和编译标志?您是否找到性能影响的确切来源?您如何确保找到正确的原因?您使用了什么分析器,以及如何使用它?您确定不错的对象模型没有得到有效实施吗?20%的数据足够小,您需要收集大量数据并进行详细分析,然后再说这绝对是由于设计(而不是说实施不佳或其他一些编码问题)所致。
Kirill 2014年

简短的旁注:每个人似乎都公开赞扬优秀的设计胜于纯净的性能(当然,这有很充分的理由)。但是,为什么这么多真实世界的代码真的,真的无法维护?是否所有代码条都感到内and并因此公开保持沉默?
AlexE

Answers:


9

很少有科学软件开发人员了解好的设计原则,因此,如果这个答案有点冗长,我深表歉意。从软件工程的角度来看,科学软件开发人员的目标是设计一种解决方案,该解决方案应满足一系列经常相互冲突的约束。

这是这些约束的一些典型示例,可能会应用于稀疏矩阵库的设计:

  • 一个月内完成
  • 在笔记本电脑和多个工作站上正确运行
  • 高效运行

科学家逐渐关注软件工程的其他一些常见要求:

  • 文档(用户指南,教程,代码注释)
  • 可维护性(版本控制,测试,模块化设计)
  • 可重用性(模块化设计,“灵活性”)

您可能需要或多或少的这些要求之一。如果您想获得Gordon Bell的性能奖,那么即使只有零点几分都是有意义的,而且很少有评委会评估您的代码质量(只要您可以说服他们是对的)。如果您试图证明在共享资源(例如集群或超级计算机)上运行此代码的合理性,那么通常您必须捍卫关于代码性能的主张,但是这些主张很少非常严格。如果您想在期刊上发表一篇描述您的方法所带来的性能提升的论文,那么您就理所当然地要比竞争对手更快,而要想获得更好的可维护性和可重用性,必须权衡20%的性能。

回到您的问题,“足够的设计”,只要有足够的开发时间,就不应牺牲性能。如果目标是使代码尽可能快地运行,那么应该围绕这些约束来设计代码。您可能会使用诸如代码生成,内联汇编之类的技术,或者利用经过高度调整的库来帮助您解决问题。

但是,如果您没有足够的开发时间怎么办?有什么好吃的?好吧,这取决于一切,没有更多的背景,没有人能够给您一个很好的答案。

FWIW:如果您真的对编写高性能的稀疏矩阵内核感兴趣,那么您应该将其与优化的PETSc安装进行比较,并击败他们,与他们的团队合作,他们很乐意将调整后的内核合并到库中。


我对代码生成器感到好奇-我认为它们可能对我有用,但我担心它们很难维护。我知道Java程序员经常使用它们,但是它们通常是为针对特定应用程序生成代码而量身定制的。您知道使用它们的任何科学法规吗?
Daniel Shapero 2014年

ATLAS,FFTW,Spiral,OSKI,Ignition,stencil_codegen等仅举几例。它没有公开发布,但是如果MKL和ESSL中的几个重要内核都是以此方式生成的,我不会感到惊讶。编写可维护的内核生成代码将是一个有趣的后续问题。我对此有经验,但我不会认为自己是权威。
Aron Ahmadia 2014年

12

这是一个关于您花费时间的问题。对于我们大多数人来说,我们花费3/4的时间进行编程,并花费1/4的时间等待结果。(您的数字可能会有所不同,但是我认为数字并非完全没有优点。)因此,如果您的设计允许您以两倍的速度编程(3/4个时间单位而不是1.5个时间单位),那么您可以在性能上造成300%的损失(从1/4到1个时间单位),而在解决问题上花费的实时性方面仍然领先。

另一方面,如果您要执行繁重的计算,则计算的外观可能会有所不同,并且您可能希望花费更多的时间来优化代码。

对我来说,如果最终提高生产力,那么20%似乎是一个不错的权衡。


好的答案,我还要在性能很重要的地方添加重要性。给定的科学代码并不仅仅是矩阵乘法。如果您有20%的运行时使用矩阵乘法,那么20%的性能命中率总体上只有4%的差异,我很乐意以此为代价来换取易于使用的库。
Aurelius

1
更好的书面库意味着更少的错误,从而使您减少等待错误结果的时间。
Davidmh 2014年

4

恕我直言,高达50%的罚款(无论出于何种原因)还算不错。

实际上,仅基于编译器的类型,我已经看到了0-30%的性能差异。这是针对PETSc针对由低阶FE离散化产生的矩阵的稀疏MatMult例程。


1

随着时间的推移,软件设计不会自动改善。表演会。您的下一个CPU将获得20%的回报。此外,良好的软件设计将使将来更容易扩展或改进库。


我不认为这可以回答问题。
nicoguaro

0

一般原则是首先进行良好的设计,然后仅在需要时才对性能进行优化。如果真的需要,那么真正需要20%的性能提升的用例就很少见了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.