HierBEM 重构体会
近期完成了 HierBEM 软件库的重构工作,提升了性能。在该过程中的体会整理如下。
文档
- 图示的作用与重要性:一图胜千言,容易在脑海中留下印象。无论是手绘还是使用绘图软件,怎么方便怎么来。如果只有文字描述,每次回顾相关内容时,加载信息时间长,忘得也快。此过程如同蜗牛爬井,进三尺退两尺,效率很低。
- 要将函数调用层级理清,尤其是 HierBEM 需要保留满阵组装和两个层级矩阵组装方法共三个代码分支。具体的重构与代码核查工作是依照函数调用关系展开的。
有限使用 AI
除了解读编译器出错信息外,我基本上没有使用 AI 来检查代码或者重构。这是由于有效的测试用例仅仅意味着后验正确性(posteriori correctness)。对于数值软件而言,它必须满足先验正确性(a priori correctness)。即在每一个逻辑分支中,从始至终的每个步骤都必须是正确无误的。 HierBEM 的本质是数学而不是软件,软件仅仅是其表现形式。
编码
- 要基于实测和亲自使用的体验,而非网上关于某种工具的宣传与教程,来构建属于自己的开发工具箱或者“瑞士军刀”。在不同的工作场景下,兼顾任务要求与硬件性能,了解每个工具的功能与性能局限,切换至最适合的工具,并让多种工具相互配合。例如,
- 使用
ripgrep进行项目内的全局搜索与替换,是重构的有效工具。 - 使用
clangd而非 VS Code IntelliSense 或 AI 进行语法和头文件的检查,效果要精确很多。 - 受系统内存限制,我无法在多进程编译的同时启用 eglot 或 gdb 。
- 使用
调试
对于只在较大问题规模下才会出现的程序异常,因程序运行时间过长,基本无法在 debug 模式下使用 gdb 来调试。此时有效的调试方法就是让程序输出信息。
重构
- 在软件的架构与性能上不能图快而打折扣。要不折不扣地做到想要的设计效果。比如,对于边界元矩阵组装的三个代码分支,一开始我想只保留性能最好的版本。但实际上其他两个分支虽然不具有工程实用价值,但作为参照也是很有用的。对于复杂的数值计算软件来说,将算法一气呵成地写下来也许并不是很难的事,但要想验证和确保算法实现的正确性,则是很花功夫的。因此,保留代码中的低性能分支具有重要的参考与验证价值。
- 尽管重构工作的路很长,且环顾四周一片渺茫,尽管做不到胸有成竹,但是终极目标与大方向要明确。然后,就是要坚定地朝着这个目标前行。正所谓,夫险以远,则至者少。参考算法开发的两种模式。
- 重构是需要高度专注与耗费精力的工作,因此一定要在精神状态好的时候进行。精神状态不佳的时候就不要工作了,放松、运动、休息。