【问题标题】:Implement rayon `as_parallel_slice` using iterators使用迭代器实现人造丝`as_parallel_slice`
【发布时间】:2018-06-29 07:32:22
【问题描述】:

我自己有一个小问题:

extern crate rayon;
use rayon::prelude::*;

#[derive(Debug)]
struct Pixel {
    r: Vec<i8>,
    g: Vec<i8>,
    b: Vec<i8>,
}

#[derive(Debug)]
struct Node{
    r: i8,
    g: i8,
    b: i8,
}

struct PixelIterator<'a> {
    pixel: &'a Pixel,
    index: usize,
}

impl<'a> IntoIterator for &'a Pixel {
    type Item = Node;
    type IntoIter = PixelIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        println!("Into &");
        PixelIterator { pixel: self, index: 0 }
    }
}

impl<'a> Iterator for PixelIterator<'a> {
    type Item = Node;
    fn next(&mut self) -> Option<Node> {
        println!("next &");
        let result = match self.index {
            0 | 1 | 2 | 3  => Node {
                r: self.pixel.r[self.index],
                g: self.pixel.g[self.index],
                b: self.pixel.b[self.index],
            },
            _ => return None,
        };
        self.index += 1;
        Some(result)
    }
}

impl ParallelSlice<Node> for Pixel {
    fn as_parallel_slice(&self) -> &[Node] {
        // ??
    }
}

fn main() {
    let p1 = Pixel {
        r: vec![11, 21, 31, 41],
        g: vec![12, 22, 32, 42],
        b: vec![13, 23, 33, 43],
    };

    p1.par_chunks(2).enumerate().for_each(|(index, chnk)| {
        for (cindex, i) in chnk.into_iter().enumerate(){
            println!("{:?}, {:?}", (index*2)+cindex, i);   
        }
    });
}

playground

基本上我想使用人造丝的per_chunk 函数,它要求我必须实现ParallelSlice 特征。我想知道 as_parallel_slice 函数应该输入什么,以便我可以得到输出(顺序无关紧要):

0 Node { 11, 12, 13} 
1 Node { 21, 22, 23}
2 Node { 31, 32, 33}
3 Node { 41, 42, 43}

一个更愚蠢的问题是as_parallel_slice 限制 Trait 返回一个切片,根据我在这种情况下的理解,我需要事先获得完整的数据吗?由于我正在处理 DNA 序列(可能是大量数据),我想我应该回退到使用横梁和迭代器,而不是通过人造丝进行基于切片的并行化,或者它们是做同样事情的更好方法吗?

【问题讨论】:

    标签: rust rayon


    【解决方案1】:

    您不能创建Nodes 的切片,除非您有一块仅包含Nodes 的连续内存。但你没有那个;每个Node 的数据都是从存储在三个独立Vecs 中的数据位中延迟复制的。

    最明显的创建切片的方法是首先在Vec&lt;Node&gt; 中创建所有Nodes,然后对其进行切片。但是,我怀疑这正是您不想做的。

    【讨论】:

    • 只是为了 Avi 的利益而详细说明,将 p1.par_chunks(2) 更改为 p1.into_iter().collect::&lt;Vec&lt;Node&gt;&gt;().par_chunks(2) 将提供您想要的输出,但会完全复制数据。
    • @user25064 可能比这更糟。您不能创建一个向量并立即返回它的一部分。他必须拥有Pixel 拥有的向量或其他只要切片需要就存在的东西。
    • 感谢@PeterHall 和 user25064 的回答,您说得对,数据太大而无法复制,会增加整体资源使用量。我想我会回到基于 Crossbeam 的并行化。我必须努力了解人造丝和横梁用例之间的区别。再次感谢,干杯!
    猜你喜欢
    • 1970-01-01
    • 2021-05-02
    • 1970-01-01
    • 2020-11-09
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    相关资源
    最近更新 更多