使用迭代器实现人造丝“as_parallel_slice”
Implement rayon `as_parallel_slice` using iterators
我自己有个小问题:
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);
}
});
}
基本上我想使用 rayon 的 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 绑定到 return 一个切片,根据我的理解,在这种情况下我需要事先获得完整的数据吗?由于我正在处理 DNA 序列(可能有很多数据),我想我应该回过头来使用 crossbeam 和迭代器,而不是通过人造丝进行基于切片的并行化,或者它们是更好的方法吗?
除非您有一大块仅包含 Node
的连续内存,否则您无法创建 Node
的片段。但是你没有那个;来自每个 Node
的数据是从存储在三个单独的 Vec
中的数据位中延迟复制的。
创建切片的最明显方法是首先在 Vec<Node>
中创建所有 Node
,然后从中创建一个切片。但是,我怀疑这正是您不想做的。
我自己有个小问题:
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);
}
});
}
基本上我想使用 rayon 的 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 绑定到 return 一个切片,根据我的理解,在这种情况下我需要事先获得完整的数据吗?由于我正在处理 DNA 序列(可能有很多数据),我想我应该回过头来使用 crossbeam 和迭代器,而不是通过人造丝进行基于切片的并行化,或者它们是更好的方法吗?
除非您有一大块仅包含 Node
的连续内存,否则您无法创建 Node
的片段。但是你没有那个;来自每个 Node
的数据是从存储在三个单独的 Vec
中的数据位中延迟复制的。
创建切片的最明显方法是首先在 Vec<Node>
中创建所有 Node
,然后从中创建一个切片。但是,我怀疑这正是您不想做的。