簡體   English   中英

如何有效地處理 rust 中不同具體類型的泛型類型?

[英]How to handle generic types with different concrete types in rust efficiently?

主要目標是實現一個計算圖,它處理帶有值的節點和帶有運算符的節點(想想簡單的算術運算符,如加法、減法、乘法等)。 一個算子節點最多可以占用兩個值節點,並“產生”一個結果值節點。

到目前為止,我使用枚舉來區分值和操作符節點:

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包含一個結構,它本身包含對特征 object ValueType的引用,該特征由各種具體類型實現。

但問題來了。 在編譯期間,泛型類型將被省略,並由實際類型替換。 泛型T也在整個計算圖中傳播(顯然):

pub struct ComputationGraph<T> where T : Copy + Clone {
    nodes: Vec<Node<T>>
}

這實際上將ComputeGraph的使用限制為一個特定的ValueType

此外,通用類型T不能是Sized ,因為值節點可以是由 rust 不可用的不同后端處理的 opqaue 類型(想想通過 FFI 提供的 C opqaue 類型)。

這個問題的一個可能的解決方案是引入一個額外的枚舉類型,它“鏡像”上面提到的 valuetype 特征的具體實現。 這種方法與枚舉調度類似。

有什么我沒有想到要使用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 庫。 memory 管理和設備交互對用戶應該是透明的。 Matrix 類型在 OpenCL 設備上分配空間,類型為原始類型緩沖區,適當的調用將返回指向 memory 的特定區域的指針。 考慮一個將通過標量類型縮放矩陣的操作,它由原始值表示。 (指向)緩沖區和標量都可以傳遞給 kernel function。 回到ComputeGraph ,似乎很明顯,所有 BLAS 操作都形成某種類型的計算圖,可以簡化為指令的線性列表(在這里考慮設置 kernel arguments,分配緩沖區,將 Z50484C19F1AFDAF38821AFDAF33 入隊存儲結果ETC... )。 說了這么多,計算圖需要能夠存儲各種類型的值節點。

與往常一樣,問題中提出的問題的答案是顯而易見的。 該圖需要一種泛型類型(具有特征邊界)。 正如問題中已經概述的那樣,使用枚舉來“聚集”各種子類型是解決方案。

一個例子來說明解決方案。 考慮以下“子類型”:

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現在可以用作圖中節點/頂點的主要類型。 該解決方案可能不是很優雅,但現在可以解決問題。 也許將來可能會進行一些代碼重組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM