什么是在 C++ 中运行参数研究的好方法

计算科学 软件 有限元 Python C++
2021-12-22 20:23:41

问题

我目前正在研究有限元 Navier Stokes 模拟,我想研究各种参数的影响。一些参数在输入文件中或通过命令行选项指定;其他参数在 Makefile 中作为标志提供,因此每当我更改这些选项时都必须重新编译我的代码。我有兴趣获得一些关于系统探索参数空间的好方法的建议。

  • 是否有有用的 C++/Python 库/框架可以帮助解决这类问题?例如,发现boost.Program_options是一个很大的帮助,因为可以使用命令行参数重载输入文件选项。我还看到有些人使用作业文件非常有效地描述每种情况,一位同事建议将参数作为注释块写入 vtu 文件也可以。
  • 也许根本不值得在这方面投入太多时间?这只是分散注意力和浪费时间,最好只是通过测试过程蛮力和临时性的吗?

一些想法

我目前主要是手工做事,我遇到了以下问题:

  • 命名测试用例我尝试将结果存储在使用下划线分隔的运行参数命名的文件夹中,例如Re100_dt02_BDF1.... 如果缩写太多,它们很快就会变得冗长或难以阅读/晦涩难懂。此外,实数参数包括.尴尬/丑陋的 a。
  • 记录运行数据有时我希望看到写入终端的结果并保存到文本文件中。例如,来自 StackOverflow 的这个答案有点帮助,但解决方案似乎有点侵入性。
  • 根据参数绘制数据将各种日志文件中的相关数据收集到一个文件中需要相当长的时间,然后我可以绘制该文件,如果使用更好的系统,这可能会变得更容易。
  • 记录对数据的评论检查结果后,我在文本文件中写了一些评论,但有时很难将其与结果文件夹保持同步。
4个回答

如果你想写一些通用的东西,你可以使用 shell 脚本来完成,如果它是非常简单的,就像Pedro 建议的那样,或者使用更高级别的数学编程语言,如 Python 或 MATLAB 进行聚合。我同意纯文本文件对少量数据很有用,但是对于大于几兆字节的数据,您可能应该切换到二进制数据。

另一方面,如果您只是在进行参数估计,我建议您使用专门为此而设计的软件。我大学的几位研究人员对DAKOTA很幸运,这是一个来自桑迪亚国家实验室的不确定性量化工具箱(根据 GNU 小通用公共许可证提供)。

这是描述达科他州的桑迪亚页面的摘录:

我们提供了多种方法,允许用户运行一组计算机模拟来评估模型输出相对于模型输入的敏感性。常见类别包括参数研究、抽样方法和实验设计。在参数研究中,一些输入参数在一个范围内步进,同时保持其他输入参数固定,并评估输出如何变化。在采样方法中,从输入空间分布生成样本并计算输入值的输出响应。DAKOTA 中可用的特定采样方法包括 Monte Carlo、Latin Hypercube 和(即将推出)准蒙特卡洛。在实验设计中,输出在一组输入“设计”点进行评估,这些输入“设计”点被选择以代表性的方式对空间进行采样。DAKOTA 中可用的特定实验方法设计包括 Box-Behnken、中心复合和因子设计。灵敏度度量是一种表达输出对输入的依赖性的数学方法。Dakota 中提供了多种敏感性指标,例如简单和偏相关系数以及等级相关性。我们目前的研究侧重于以最少的运行次数生成灵敏度指标的方法,以及使用贝叶斯分析技术对计算机模型中的参数进行最佳估计的方法。

只是对你的两个观点的一些评论:

  • 记录运行数据:您最好的选择可能是通过tee命令管道输出,该命令在大多数 shell 中都应该可用。

  • 根据参数绘制数据:我想这是一个口味问题,但是当我必须进行复杂的数据聚合时,我将结果存储为纯文本,将它们作为矩阵读入 Matlab,然后进行所有计算、绘图甚至 LaTeX 输出从那里。显然,您最熟悉的任何编程/脚本语言都会给您最好的结果。

对于我的博士工作,我遇到了和你类似的问题。但是,由于我使用的不是我的代码,所以我没有你那样的灵活性。也就是说,我确实有一些建议。

正如佩德罗建议的那样,有 tee 命令。但是,如果它不可用,或者您想在软件本身中内置一些东西,我建议您查看该boost::iostreams库。它提供了定义标准库不做的输入源和输出接收器的机制。特别是,tee_device它允许您将两个输出接收器连接到您的流,而其他流可以充当接收器。这将允许您同时输出到stdout和日志文件配置相关。

我同意这boost::program_options对配置您的软件非常有帮助。但是,它有几个缺陷可能会影响你做事的方式。首先,如果您需要分层配置,$^1$ 那么ini文件是完成它的痛苦方式。其次,更重要的是,boost::program_options它没有输出功能,因此您不能将状态保存为配置文件以供以后检查或恢复停止的代码。作为替代方案,我建议使用boost::property_tree支持分层配置文件并保存树以供以后重用。这有一个额外的好处,如果您需要检查代码,您可以在重新启动时将其当前状态保存为输入。

为了从不同的计算中收集数据,我遍历了我想包含在一个集合中的所有数据文件,然后我使用awk在文件中生成一行,并将所有结果通过管道传输到我的输出中。这可能需要几分钟,但不幸的是,我没有更好的方法。

至于处理/评论您的数据,我不能足够强调 Mathematica 笔记本格式的有用性。它让我可以在一个地方组织我的观察、推测和可视化。不过,我的笔记本通常会超过 100 MB。为了更好地衡量,Mathematica在矩阵任务上的表现与 Matlab 一样好。此外,它还可用于实时记录具有完整数学格式的笔记。

我希望我对命名问题有更好的解决方案,但这是相当有害的。因此,考虑将一些数据输出到数据库中可能是值得的。但是,如果您不希望这样做,请考虑使用 XFS 中的扩展属性来捕获有关您的模拟的更完整信息,并将您的配置文件与它用于生成的数据一起存储。

1. 作为需要分层配置文件的示例,我的一个朋友正在检查AFM中不同尖端几何形状的影响,并且每个几何形状都有一组不同的参数。此外,除此之外,他还在测试几种计算方案,以便将它们与实验进行比较,它们的参数差异很大。

我在安装 PETSC 时了解了 PyTables。而且我猜表(或数据库)方法非常适合探索参数空间,尽管我还没有尝试过。我们可以使用特定参数记录每次运行,然后我们可以查阅满足某些条件的任何聚合,例如,我们可以修复 dt、BDF1 并查找所有相关记录以研究由于其他参数引起的变化。

我想听听实际使用表(或数据库)方法来探索参数空间的人的意见。我会很感激详细的例子。