Как использовать std :: slice :: Chunks на Ar c >> Правильно между нитями в Rust? - PullRequest
0 голосов
/ 02 апреля 2020

Я бы хотел понять, почему в Rust не работает следующее.

Я бы хотел разделить вектор на части и дать каждому потоку фрагмент для работы с ним. Я попробовал это с комбинацией Ar c и Mutex, чтобы иметь взаимный доступ к моей ve c.

Это была моя первая (очевидная) попытка: объявить ve c, разделить на части, отправить кусок в каждую нить. В моем понимании это должно работать, потому что методы Chunk гарантируют неперекрывающиеся фрагменты.

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let data = Arc::new(Mutex::new(vec![0;20]));
    let chunk_size = 5;
    let mut threads = vec![];
    let chunks: Vec<&mut [u8]> = data.lock().unwrap().chunks_mut(chunk_size).collect();

    for chunk in chunks.into_iter(){
        threads.push(thread::spawn(move || {
                inside_thread(chunk)
            }));
    }

}
fn inside_thread(chunk: &mut [u8]) {
    // now do something with chunk
}

Ошибка говорит о том, что данные не живут достаточно. Глупый я, с помощью чанковки я создал указатели на массив, но не передавал ссылку Ar c в поток. Поэтому я изменил несколько строк, но это не имело бы никакого смысла, потому что в моем потоке была бы неиспользованная ссылка!?

for i in 0..data.lock().unwrap().len() / 5 {
        let ref_to_data = data.clone();
        threads.push(thread::spawn(move || {
                inside_thread(chunk, ref_to_data)
            }));
    }

Ошибка по-прежнему говорит о том, что данные не живут достаточно. 1012 * Следующая попытка тоже не сработала. Я думал, хорошо, я мог бы обойти это и разделить его на части в потоке и получить свой кусок по индексу. Но если бы это работало, код не был бы очень идиоматическим c: /

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let data = Arc::new(Mutex::new(vec![0;20]));
    let chunk_size = 5;
    let mut threads = vec![];

    for i in 0..data.lock().unwrap().len() / chunk_size {
        let ref_to_data = data.clone();
        threads.push(thread::spawn(move || {
                inside_thread(ref_to_data, i, chunk_size)
            }));
    }

}
fn inside_thread(data: Arc<Mutex<Vec<u8>>>, index: usize, chunk_size: usize) {
    let chunk: &mut [u8] = data.lock().unwrap().chunks_mut(chunk_size).collect()[index];
    // now do something with chunk
}

Ошибка говорит:

--> src/main.rs:18:72
   |
18 |     let chunk: &mut [u8] = data.lock().unwrap().chunks_mut(chunk_size).collect()[index];
   |                                                                        ^^^^^^^
   |                                                                        |
   |                                                                        cannot infer type for type parameter `B` declared on the method `collect`
   |                                                                        help: consider specifying the type argument in the method call: `collect::<B>`
   |
   = note: type must be known at this point

И когда я пытаюсь сделать вывод, это не ' тоже не работает. Так что сейчас я очень старался, и ничего не получалось, и у меня не было идей. Хорошо, что я всегда мог сделать, это "сделать порцию самостоятельно". Просто мутирование вектора внутри потоков работает нормально. Но это не идиоматизм c хороший способ сделать это (на мой взгляд).

Вопрос: есть ли способ решить эту проблему? Ржавчина идиомати c?

Подсказка: я знаю, что могу работать с пулом с ограниченным доступом или чем-то вроде этого, но я хочу получить эти знания для своей диссертации.

Большое спасибо, что уделили нам время на это!

...