基于块或基于流的系统编程的最佳实践
Best practices in block based or flow based system programming
我正在尝试实现一个类似于 Labview 的系统(在 Java 中),其中一些模块能够
- 采购
- 下沉
- 穿越
数据。
每个块都有多个输入 (>= 0) 和多个输出 (>= 0),并专门用于输入、输出和转换数据的功能。数据流表示为样本,取自各种设备(温度计、风速计、辐射传感器、功率计等)的现场测量。
每个样本都与一个 "epoch" 相关,这是一个捕获所有值的瞬间,从触发器开始(源块应该有一个特殊的触发器输入),因此来自一个时期的样本组应该与来自同一样本的其他样本。
例如,一个典型的区块链可以由一个源(温度传感器)表示,然后是一个平均器块(传递),最后是一个能够将数据记录到数据库中的接收器(接收器块)。
我已经实施了一个类似推送的策略,其中每个块都拥有 "next-block" 引用并在其上调用一个方法来传递要处理的数据。该策略在遇到块(如比较器块,具有两个浮点输入和一个布尔输出)需要基于相同样本时期输出比较值的情况之前一直有效。
问题是我无法找到并应用抽象此问题的模式。也许这类似于 Labview 或 Simulink 块在内部的工作方式,但我仍然没有成功找到 "best-practice"。我的 "push-policy" 的主要问题是,根据链的大小和深度,具有多个输入的块完成处理属于不同时期的样本(想象一个比较器块比较来自两个不同测量值的两个样本)。
提前感谢所有建议、技巧、最佳实践以及所有能够解决我的哲学问题而非编程问题的一切。
有趣的问题!
我建议将 "the block"(用盒子表示的功能单元)、拓扑(块如何连接的定义)和控制(实例化块、仲裁消息传递和进行流量控制导致块在正确的时间执行等)。 objective 是为了消除块之间的耦合(块之间应该完全不知道彼此)并创建一个任意可配置的系统。
以下是我对三个主要组成部分的看法:
拓扑结构
拓扑定义:拓扑的定义通常发生在资源文件中,而不是代码文件(应该是用户可配置的权限)。资源文件应该包含关于什么块的信息,它们的输入(输出通常可以从输入的知识中导出)并定义块可能具有的任何属性。例如,资源 JSON 文件可能如下所示:
[{ uniqueId:"1",
type:"Number",
val:0.3
},
{ uniqueId:"2",
type:"Sine",
stepSize:0.1,
initialOutput=0
},
{ uniqueId:"3",
type:"Multiplier",
inputs:["1","2"],
initialOutput=0
},
{ uniqueId:"4",
type:"Plotter",
inputs:["3"],
}]
控制
控制机制首先读取拓扑定义(不要忘记验证),然后使用此信息实例化块组件并创建消息传递基础结构,使用每个块具有的输入知识将块组件连接在一起(将每个输入视为一个单独的消息队列)。特别是控制器需要确定每个时间步中块的执行顺序。在每个时间步,控件都会执行几个步骤,首先从区块链的开头开始,将输出推送到 "listening" 的输入队列。执行下一层块。将输出推送到下一层块等。(或类似的其他策略。)
阻止
这些块基本上只知道如何接受给定的输入和 return 合适的输出。
顺便说一句,您可以研究的另一个类似系统是电气工程师使用的电路仿真程序(如 Spice)。这些通常包括电路组件(您的块)、节点列表文件(拓扑定义)和某种模拟运行时。
反正这是我的想法..
这种问题可以通过同步输入来解决。
在LabVIEW VI中,输入都是在VI启动时定义的。因此,它们都具有相同的时代。通过不同路径工作需要多长时间的差异就变得没有实际意义了。
在多个 VI 处理一个数据集的情况下,有一个 VI 每个周期从源收集一次所有数据。该代码分为三个阶段。收集数据。处理数据。输出数据。这意味着所有源数据都具有相同的纪元。
对于控制应用程序,这种同步对于使控制系统数学稳定至关重要。
我正在尝试实现一个类似于 Labview 的系统(在 Java 中),其中一些模块能够
- 采购
- 下沉
- 穿越
数据。
每个块都有多个输入 (>= 0) 和多个输出 (>= 0),并专门用于输入、输出和转换数据的功能。数据流表示为样本,取自各种设备(温度计、风速计、辐射传感器、功率计等)的现场测量。
每个样本都与一个 "epoch" 相关,这是一个捕获所有值的瞬间,从触发器开始(源块应该有一个特殊的触发器输入),因此来自一个时期的样本组应该与来自同一样本的其他样本。
例如,一个典型的区块链可以由一个源(温度传感器)表示,然后是一个平均器块(传递),最后是一个能够将数据记录到数据库中的接收器(接收器块)。
我已经实施了一个类似推送的策略,其中每个块都拥有 "next-block" 引用并在其上调用一个方法来传递要处理的数据。该策略在遇到块(如比较器块,具有两个浮点输入和一个布尔输出)需要基于相同样本时期输出比较值的情况之前一直有效。
问题是我无法找到并应用抽象此问题的模式。也许这类似于 Labview 或 Simulink 块在内部的工作方式,但我仍然没有成功找到 "best-practice"。我的 "push-policy" 的主要问题是,根据链的大小和深度,具有多个输入的块完成处理属于不同时期的样本(想象一个比较器块比较来自两个不同测量值的两个样本)。
提前感谢所有建议、技巧、最佳实践以及所有能够解决我的哲学问题而非编程问题的一切。
有趣的问题!
我建议将 "the block"(用盒子表示的功能单元)、拓扑(块如何连接的定义)和控制(实例化块、仲裁消息传递和进行流量控制导致块在正确的时间执行等)。 objective 是为了消除块之间的耦合(块之间应该完全不知道彼此)并创建一个任意可配置的系统。
以下是我对三个主要组成部分的看法:
拓扑结构
拓扑定义:拓扑的定义通常发生在资源文件中,而不是代码文件(应该是用户可配置的权限)。资源文件应该包含关于什么块的信息,它们的输入(输出通常可以从输入的知识中导出)并定义块可能具有的任何属性。例如,资源 JSON 文件可能如下所示:
[{ uniqueId:"1",
type:"Number",
val:0.3
},
{ uniqueId:"2",
type:"Sine",
stepSize:0.1,
initialOutput=0
},
{ uniqueId:"3",
type:"Multiplier",
inputs:["1","2"],
initialOutput=0
},
{ uniqueId:"4",
type:"Plotter",
inputs:["3"],
}]
控制
控制机制首先读取拓扑定义(不要忘记验证),然后使用此信息实例化块组件并创建消息传递基础结构,使用每个块具有的输入知识将块组件连接在一起(将每个输入视为一个单独的消息队列)。特别是控制器需要确定每个时间步中块的执行顺序。在每个时间步,控件都会执行几个步骤,首先从区块链的开头开始,将输出推送到 "listening" 的输入队列。执行下一层块。将输出推送到下一层块等。(或类似的其他策略。)
阻止
这些块基本上只知道如何接受给定的输入和 return 合适的输出。
顺便说一句,您可以研究的另一个类似系统是电气工程师使用的电路仿真程序(如 Spice)。这些通常包括电路组件(您的块)、节点列表文件(拓扑定义)和某种模拟运行时。
反正这是我的想法..
这种问题可以通过同步输入来解决。
在LabVIEW VI中,输入都是在VI启动时定义的。因此,它们都具有相同的时代。通过不同路径工作需要多长时间的差异就变得没有实际意义了。
在多个 VI 处理一个数据集的情况下,有一个 VI 每个周期从源收集一次所有数据。该代码分为三个阶段。收集数据。处理数据。输出数据。这意味着所有源数据都具有相同的纪元。
对于控制应用程序,这种同步对于使控制系统数学稳定至关重要。