Есть ли способ конвертировать ChunkMut <T>из Vec :: chunks_mut в слайс & mut [T]? - PullRequest
0 голосов
/ 24 февраля 2019

Я заполняю вектор параллельно, но для этого обобщенного вопроса я нашел только подсказки и никаких ответов.

Приведенный ниже код работает, но я хочу переключиться на Rng::fill вместо итерации по каждому чанку.Может быть невозможно иметь несколько изменяемых фрагментов внутри одного Vec;Я не уверен.

extern crate rayon;
extern crate rand;
extern crate rand_xoshiro;

use rand::{Rng, SeedableRng};
use rand_xoshiro::Xoshiro256StarStar;
use rayon::prelude::*;
use std::{iter, env};
use std::sync::{Arc, Mutex};

// i16 because I was filling up my RAM for large tests...
fn gen_rand_vec(data: &mut [i16]) {
    let num_threads = rayon::current_num_threads();
    let mut rng = rand::thread_rng();
    let mut prng = Xoshiro256StarStar::from_rng(&mut rng).unwrap();
    // lazy iterator of fast, unique RNGs
    // Arc and Mutex are just so it can be accessed from multiple threads
    let rng_it = Arc::new(Mutex::new(iter::repeat(()).map(|()| {
        let new_prng = prng.clone();
        prng.jump();
        new_prng
    })));
    // generates random numbers for each chunk in parallel
    // par_chunks_mut is parallel version of chunks_mut
    data.par_chunks_mut(data.len() / num_threads).for_each(|chunk| {
        // I used extra braces because it might be required to unlock Mutex. 
        // Not sure.
        let mut prng = { rng_it.lock().unwrap().next().unwrap() };
        for i in chunk.iter_mut() {
            *i = prng.gen_range(-1024, 1024);
        }
    });
}

1 Ответ

0 голосов
/ 24 февраля 2019

Оказывается, что итератор ChunksMut дает срезы.Я не уверен, как извлечь это из документации.Я понял это, прочитав источник :

#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ChunksMut<'a, T:'a> {
    v: &'a mut [T],
    chunk_size: usize
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Iterator for ChunksMut<'a, T> {
    type Item = &'a mut [T];

    #[inline]
    fn next(&mut self) -> Option<&'a mut [T]> {
        if self.v.is_empty() {
            None
        } else {
            let sz = cmp::min(self.v.len(), self.chunk_size);
            let tmp = mem::replace(&mut self.v, &mut []);
            let (head, tail) = tmp.split_at_mut(sz);
            self.v = tail;
            Some(head)
        }
}

Я думаю, это просто опыт;другим должно быть очевидно, что итератор типа ChunksMut<T> из Vec<T> возвращает объекты типа [T].Это имеет смысл сейчас.Это просто было не очень понятно с промежуточной структурой.

pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T>
// ...
impl<'a, T> Iterator for ChunksMut<'a, T>

Читая это, выглядело, как итератор возвращал объекты типа T, такие же как Vec<T>.iter(), что не имело бы смысла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...