Реализуйте вискозиметр as_parallel_slice с помощью итераторов.

У меня есть небольшая проблема:

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 ограничивает Признак для возврата среза, согласно моему пониманию, в этом сценарии мне нужно заранее получить полные данные? Поскольку я работаю с последовательностями ДНК (которые могут содержать много данных), я думаю, мне следует вернуться к использованию перекрестной балки и итераторов вместо распараллеливания на основе срезов через район, или это лучший способ сделать то же самое?


person Avi Srivastava    schedule 29.06.2018    source источник


Ответы (1)


Вы не можете создать фрагмент из Nodes, если у вас нет фрагмента непрерывной памяти, содержащего только Nodes. Но у вас этого нет; данные из каждого Node лениво копируются из битов данных, хранящихся в трех отдельных Vec.

Самый очевидный способ создать срез - сначала создать все Node в Vec<Node>, а затем сделать из него срез. Однако я подозреваю, что это именно то, чего вы не хотите делать.

person Peter Hall    schedule 29.06.2018
comment
Для удобства Ави, изменение p1.par_chunks(2) на p1.into_iter().collect::<Vec<Node>>().par_chunks(2) даст желаемый результат, но будет полным дублированием данных. - person user25064; 29.06.2018
comment
@ user25064 Может быть и хуже. Вы не можете создать вектор и сразу вернуть его срез. Ему нужно, чтобы вектор принадлежал Pixel или чему-то другому, живущему до тех пор, пока нужен срез. - person Peter Hall; 29.06.2018
comment
Спасибо @PeterHall и user25064 за ответы, вы все правильно поняли, данные слишком велики, чтобы их можно было дублировать, и это приведет к увеличению общего использования ресурсов. Думаю, я вернусь к распараллеливанию на основе Crossbeam. Я считаю, что мне нужно поработать, чтобы понять разницу между вариантами использования вискозы и перекладины. Еще раз спасибо, ура! - person Avi Srivastava; 29.06.2018