gpt4 book ai didi

rust - 如何有效地处理具有不同混凝土类型的泛型类型的 rust ?

转载 作者:行者123 更新时间:2023-12-03 11:39:51 24 4
gpt4 key购买 nike

主要目标是实现一个计算图,该图处理带有值的节点和带有运算符的节点(想像简单的算术运算符,如加,减,乘等)。一个运算符(operator)节点最多可以包含两个值节点,然后“产生”一个结果值节点。

到目前为止,我使用枚举来区分值和运算符节点:

pub enum Node<'a, T> where T : Copy + Clone {
Value(ValueNode<'a, T>),
Operator(OperatorNode)
}

pub struct ValueNode<'a, T> {
id: usize,
value_object : &'a dyn ValueType<T>
}

更新: Node::Value包含一个结构,该结构本身包含对特征对象 ValueType的引用,该对象由多种具体类型实现。

但是问题来了。在编译过程中,通用类型将被删除,并由实际类型代替。通用类型 T也正在整个计算图中传播(很明显):
pub struct ComputationGraph<T> where T : Copy + Clone {
nodes: Vec<Node<T>>
}

这实际上将 ComputeGraph的使用限制为一个特定的 ValueType

此外,泛型类型 T不能是 Sized,因为值节点可以是opqaue类型,该类型由不通过rust无法获得的其他后端处理(请考虑通过FFI提供的C opqaue类型)。

解决此问题的一种可能的方法是引入一种附加的枚举类型,该枚举类型“镜像”上述valuetype特征的具体实现。这种方法与 enum dispatch相似。

我有没有想过使用 ValueType的多个实现的任何东西?

更新:

我要实现的是以下代码:
pub struct Scalar<T> where T : Copy + Clone{
data : T
}

fn main() {
let cg = ComputeGraph::new();

// a new scalar type. doesn't have to be a tuple struct
let a = Scalar::new::<f32>(1.0);

let b_size = 32;
let b = Container::new::<opaque_type>(32);

let op = OperatorAdd::new();

// cg.insert_operator_node constructs four nodes: 3 value nodes
// and one operator nodes internally.
let result = cg.insert_operator_node::<Container>(&op, &a, &b);

}

更新
ValueType<T>看起来像这样
pub trait ValueType<T> {
fn get_size(&self) -> usize;
fn get_value(&self) -> T;
}

更新

为了进一步提高我的问题的清晰度,请考虑一个由OpenCL支持的小型BLAS库。存储器管理和设备交互对用户应该是透明的。 Matrix类型在OpenCL设备上分配具有类型作为原始类型缓冲区的空间,并且适当的调用将返回指向该特定内存区域的指针。考虑一下将按标量类型缩放矩阵的操作,该操作由原始值表示。 (指向)缓冲区和标量都可以传递给内核函数。回到 ComputeGraph,似乎很明显,所有BLAS操作都形成某种类型的计算图,可以将其简化为线性的指令列表(在这里考虑设置内核参数,分配缓冲区,排队内核,存储结果,等等... )。综上所述,计算图需要能够存储各种类型的值节点。

最佳答案

与往常一样,对问题所提出问题的答案是显而易见的。该图需要一种通用类型(具有特征边界)。正如问题中已经概述的那样,使用枚举“聚类”各种子类型是解决方案。

一个例子来说明解决方案。考虑以下“子类型”:

struct Buffer<T> {
// fields
}

struct Scalar<T> {
// fields
}

struct Kernel {
// fields
}

包含类型的值可以打包成一个枚举:
enum MemType {
Buffer(Buffer<f32>);
Scalar(Scalar<f32>);
// more enum variants ..
}

现在, MemTypeKernel也可以打包在枚举中了
enum Node {
Value(MemType);
Operator(Kernel);
}
Node现在可以用作图形内节点/顶点的主要类型。该解决方案可能不是很优雅,但目前可以解决问题。也许将来可能会进行一些代码重组。

关于rust - 如何有效地处理具有不同混凝土类型的泛型类型的 rust ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61529128/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com