分离配置代码和算法代码的最佳做法

Best practice for separating configure and algorithm code

本文关键字:代码 最佳 算法 配置 分离      更新时间:2023-10-16

我正在编写一些代码来用c ++进行科学计算,我需要在自定义结构foo上进行一些计算。为了使整个事情在将来更容易维护,我想将设置结构(如foo.bar=1;等)的代码分离到一个单独的文件中。如何实现?该结构使用犰狳库来支持矩阵/线性代数。我已经编写了头文件f.hpp如下所示:

#include <armadillo>
#include <complex>
using namespace arma;
#ifndef __fn__
#define __fn__
struct foo
{
    cx_mat a;
    mat b;
    cx_cube c;
    complex<double> d;
    string desc;
};
#endif

将其添加到源代码文件中将要求您每次希望更改值时对其进行编译。这是一种不好的做法,特别是如果您的编译时间"很长"。

推荐的方法是让配置文件说'foo.ini'。如果您使用第三方/开源库(如 https://code.google.com/p/inih/或 http://www.hyperrealm.com/libconfig/),则可以拥有灵活的配置文件。

但是,如果你想保持简单,试试这个约定:具有交替键值对行的配置文件,具有固定的预期顺序。例如:

# foo.bar
42
# foo.pub
You're awesome
# foo.club
24/06/2015
# tab.a
64

请注意,值的顺序很重要,这将使我们很容易使用简单的C++代码进行解析。只需打开文件并重复调用 getLine(),忽略每隔一行并解析第二行以将其存储到结构中。

如果你想存储一个复杂的结构,比如

矩阵,你可以使用一个简单的策略来存储这样的结构,因为解析函数也是由我们编写的:

# Foo matrix rows
100
# Foo matrix cols
50
# Foo matrix elements, row-by-row:
0.5 3 5 23 ... ... 100
4 5 5 34 1 ... ... 100
.
.
3 33 33 2 ...  ... 100
# Diagonal Matrix rows-cols
20
# Diagonal Values, row-by-row others 0
45
22
92
.
.
20

另请注意,libconfig (http://www.hyperrealm.com/libconfig/) 允许您使用类似数组和 JSON 的文本来存储和表示这些复杂的数据结构。如果你想开始使用一个成熟的"配置语言",你可以使用它。

而且您可以节省大量编译时间。只需更新配置文件并重新运行程序即可。这样,其他程序可以输入配置值。

另一种可能性,在气味HPC中很常见,它是在应用程序中嵌入一些脚本语言。

您可以在应用程序中嵌入Lua或Guile(或Ocaml)解释器,并让它在运行复杂计算之前解释一些初始化脚本。该用户提供的脚本可以执行一些简单的解释计算来初始化数据。您只需要提供一些脚本原语来操作(和创建)用户将与其脚本组合的数据。

您还可以使您的应用程序成为一些现有框架的扩展(或插件),如Scilab,Octave,R,Python,NekoVM

顺便说一句,你的程序也可以读取一些简单的数据(也许使用像Json这样的文本序列化格式),你的用户自己会编写一些其他脚本或程序来提供你的(例如使用Unix管道)。

另一种方法可能是在 C++ 中初始化你的东西,它可能是生成的(甚至可能是由你的程序从一些更高级别的输入生成的),并在运行时编译该C++代码,然后使用 dlopen(3) 将其动态加载为插件(我在 MELT 中做这样的事情......

请注意,嵌入或集成一些解释器是一个主要的软件架构设计选择,你应该尽早做出选择。