目前我正在开发一个 Rust 程序,该程序应该在微控制器上运行多个音频处理节点。因此,我发现当我对常量值进行 for 循环时,处理速度要快得多。这就是为什么每个节点都有一个恒定的状态。我尝试了几种策略来设置状态,但没有一个让我真正满意。定义静态要容易得多,但我还没有找到真正适合常量的东西。
struct NodeA<const INPUT_LEN: usize, const OUTPUT_LEN: usize>;
这是配置节点的好方法,但首先,当状态中有太多项时,它会变得很难看,而且我还必须为状态使用常量数组,这在 const 泛型中是不允许的。
这个解决方案让我高兴了一段时间。我在特征中定义常量,并使节点在该特征上通用,这样我就可以从外部配置节点。
pub trait NodeAConfig {
const INPUT_LEN: usize;
const AUDIO_STATE: &'static [f32];
}
pub struct NodeA<Config: NodeAConfig>;
impl<Config: NodeAConfig> NodeA<Config> {
pub fn process() {
for i in 0..Config::INPUT_LEN {
todo();
}
}
}
struct MyConfig;
impl NodeAConfig for MyConfig {
const INPUT_LEN: usize = 10;
const AUDIO_STATE: &[0.0, 1.0, 2.0, 3.0];
}
NodeA<MyConfig>::process();
缺点是,我找不到将这些配置放入枚举中并将该枚举放入数组中以自动加载节点配置的解决方案,因为带有常量的特征无法使用 dyn 制成对象。
enum Configs { NodeA(Box<dyn NodeAConfig>) };
vec![Configs::NodeA(MyConfig);
我最满意的解决方案是使用结构体并定义结构体的常量实现,这样我什至可以在配置中调用 const 函数,并将配置通过枚举放入数组中。
pub struct NodeAConfig {
pub name: &'static str,
pub input_shape: [usize; 3],
pub size: usize,
}
pub struct NodeBConfig {
pub name: &'static str,
pub input_shape: [usize; 3],
pub len: usize,
}
pub enum NodeConfig {
NodeA(NodeAConfig),
NodeB(NodeBConfig),
}
pub struct Config<const NODES: usize> {
pub nodes: [NodeConfig; NODES];
}
impl<const NODES: usize> Config <Nodes> {
pub const fn config_a<const ID: usize>(&self) -> NodeAConfig {
match self.node_configs[ID] {
...
}
}
}
现在 Config 可以作为顶层的常量实现:
pub const CONFIG: Config<2> = Config {
nodes: [
NodeConfig::NodeA(NodeAConfig {
name: &"NodeA",
input_shape: [2, 2, 2],
size: 10,
}),
NodeConfig::NodeB(NodeBConfig {
name: &"NodeB",
input_shape: [2, 2, 2],
len: 10,
}),
],
};
节点本身有一个 const 通用 ID,可以使用它从节点列表中获取配置。
pub struct NodeA<const ID: usize>;
impl<const ID: usize> NodeA<ID> {
const CONFIG: NodeAConfig = CONFIG::config_a::<ID>();
}
现在唯一的问题是,节点必须引用 CONFIG 对象,因此需要在 crate 内定义该对象。我的目标是在外部定义这个 const CONFIG 对象,在实际使用节点处理器的库中。 即使当我定义 yaml 或 json 文件并使用 build.rs 文件在板条箱内写入配置时,此 yaml 文件也需要位于板条箱中,并且我无法将其放置在正在使用我的库的 prgoram 中,对吗?
有我监督过的解决方案吗?或者您认为有更好的方法来定义 const 状态吗?
鉴于您正在微控制器上的音频处理节点上工作,并且需要在运行时确定“恒定状态”,OnceCell 提供了符合人体工程学且安全的解决方案。