WHYSC 的开发动机与基本原则

FEALPy 是基于 Python 的 Numpy 模块开发的,并采用面向数组的编程方式来设计主体程序, 其主要特点是大量使用数组化的运算操作,这样可以充分利用 CPU 的多线程功能,加快程 序的执行效率。更得益于 Python 语言的灵活性,也大大提高了开发的效率。

但我在编程过程中,发现面向数组的编程方式实际上在某种程度上牺牲了开发的灵活性和效 率,对于复杂的算法,需要做大量的努力才能实现。因此没有大量的练习实践,很难应用面 向数组的方式灵活设计自己的程序。

一种思想或工具很难包打天下,不能手里有了锤子,看一切都是钉子。特别是最近在写并行 三维界面拟合的程序,算法细节很多,想用 Python 高效实现特别费劲,很难用数组化的方 式来实现。果断采用 C++ 来实现,于是就有了 WHYSC 这个软件包。

很多人会说,已经有很多优秀的科学计算开源软件了,国内的科学计算软件也发展的不错了 ,为什么还要费力自己写软件?做为一个科学计算研究工作者,我们的一个重要任务是做算 法创新研究,另一个重要任务是要培养下一代的科学计算人才。仅仅靠拿来主义是满足不了 算法研究和人才培养需要的。做科学计算算法研究,我的观点是即要拿来别人的东西做支撑 ,又要自己写代码,两条腿走路才稳当,才能走的长远。

一个软件写出来之后,是需要不断的重构,才能有生命力,才能满足不断变化的实际需要。 任正非在他的公开信《投入 20 亿美元全面提升华为软件质量》 , 就强调了“我们要重构腐 化的架构及不符合软件工程规范和质量要求的历史代码”。Google 也一直在鼓励重写已有代 码,所有软件每隔几年就要重写一次,这是优化代码的重要机会,在重写的过程中可以采用新 技术,并去掉一些没有价值的功能,同时可以培养更多的软件人才。

我希望每个做算法研究的人即要学习别人的好软件,也要花点精力写点自己的程序,最好有 一个自己长远一点的程序规划,然后点滴积累,说不定你的程序就会变成下一个优秀的开源 软件,对中国的软件发展有点贡献。

WHYSC 应该具备的特点

这个包的最终目标是成为一个科学计算常用算法的松散集合,所以你可以把它想像成一个算 法仓库。在我的设想中,它应该有下面特点

  • 各个算法模块都是独立可替换的,要方便扩展
  • 接入的第三方软件都要设计一个接口层,方便以后替换成新的算法模块
  • 支持并行
  • 考虑可移植性,尽量只依赖 C++ 标准库
  • 根据特定应用要求,可以灵活组合其中的算法模块形成应用软件

为什么要求可算法模块独立可替换?因为我们是做算法研究的,科研的首要目标是要创新, 不断发现新的更高效算法。但目前很多数值计算软件,设计过于复杂,比如很火的 Fenics ,算法模块间的依赖太强。这样的软件面向实际应用还可以,因为应用主要把数值软件当成 一个黑盒子,只关心结果和效率,不关心里面的算法,所以算法研究者很难嵌入新算法,进 行算法方面的创新研究。

因为个人精力有限,但还要想 WHYSC 马上可用,所以很多算法还要暂时调用其它软件来实 现。可是很多优秀的软件年代久远,虽然很好用,但设计思想很陈旧,也过于复杂。用最新 标准的语言,其实可以更清晰明了的实现。我的策略是在使用过程中理解这些软件中的算法 细节,将来有时间自己来实现,并进一步改进优化,这也是新研究课题的源泉吧。所以要设 计接口层,方便以后替换成自己实现的版本,也便于对比新算法和旧算法的优劣。

对每个人来说,生命本质就是一段时间,因此时间对每个人来说才是最宝贵的东西。我们做 算法研究,要提高算法的效率,本质上是为了帮助人们节省时间。现在个人电脑都是多核的 ,又有很多超级计算机可用。这么多并行的资源不用就浪费了,所以 WHYSC 一定要支持并 行,这也是自己更深入理解学习并行的实践吧。

有一些数值计算软件,因为比较老了,为了获得一些特性,设计了很多附加模块,但现如今 这些模块实现的功能,新语言标准库中已经支持的很好了,其实是完全可以去掉这些模块的 。 WHYSC 的设计遵循不重新发明轮子的标准来设计,尽量只用 C++ 标准库,这样程序也更 好移植到不同的系统上。

写数值软件如果仅仅为了多发几篇论文,也没有什么意思。正是因为这种鼓励发论文的科研 体制,导致了太多的算法研究成果只能停留在纸面上,没什么实际价值。当然这些算法也得 不到实际应用的检验,哪里还有什么向前演化的动力啊。所以 WHYSC 的设计上还要考虑实 际应用的需要,要能根据实际应用的需求任意组合形成实际应用软件。

WHYSC 的基本设计原则

1. 层次化

复杂的算法是分层的,实现算法的程序也应该是分层设计的,每一层只专注实现本层的功能 。层与层之间的调用也通过模板参数形式传入。这样每一层也是可以替换的。

2. 模块化

每一层又是由很多模块组成的。每一模块功能明确具体,而且尽量单一。每个模块的接口要 统一,只有一个入口。应用程序调用时,只需要包含一个接口头文件即可,比如最基本的模 块应该有:

  • Geometry: 实现常用的几何对象、断言和算法,接口为 Geometry_kernel
  • Algebra: 实现常用的代数对象和算法, 接口为 Algebra_kernel
  • Mesh: 实现常用的网格数据结构对象,及相应的拓扑操作算法, Mesh_kernel

上面的模块之间不会相互包含对方的头文件。当一个模块需要调用另一个模块时,另一个模 块以模板参数形式传入。

3. 简单化

WHYSC 的设计要尽量简单化。反过来说,就是要避免过度设计,比如面向对象设计中引入过 度复杂的继承关系。

4. 当前需求驱动

强调当前需求驱动的原则, 是考虑到自己精力有限,且学生都还没有完全成长起来的现实 情况。因此要想在这个体制中生存下去,就要立足于当前科研兴趣、项目、合作及学生培养 的实际需要,来开发这个软件。千万不能当下就追求一个大而全的东西。

WHYSC 要采用的编程技术

  • 面向对象
  • 模板化
  • 标准库

更多的技术细节在以后的实践中我会慢慢总结分享。

参考

  1. 任正非:全面提升软件工程能力与实践,打造可信的高质量产品
  2. 从软件工程的角度解读任正非的新年公开信
  3. CGAL:The Computational Geometry Algorithms Library

results matching ""

    No results matching ""