multithreading - 我如何使用 Rayon 将大范围拆分为多个范围 block ,并让每个线程在一个 block 中找到?

标签 multithreading rust rayon

我正在制作一个通过并行化强制密码的程序。目前要破解的密码已经以纯文本形式提供,我只是想尝试暴力破解。

我有一个名为 generate_char_array() 的函数,它基于整数种子转换基数并返回一个 u8 字符切片以尝试检查。这首先通过字母表获取 1 个字符串,然后是 2 个,依此类推。

let found_string_index = (0..1e12 as u64).into_par_iter().find_any(|i| {
    let mut array = [0u8; 20];
    let bytes = generate_char_array(*i, &mut array);
    return &password_bytes == &bytes;
});

使用找到的字符串索引(或更确切地说是种子整数),我可以生成找到的字符串。

问题是 Rayon 为我并行化它的方式是将任意大整数范围拆分为 thread_count-large 切片(例如,对于 4 个线程,0..2.5e11、2.5e11..5e11 ETC)。这不好,因为范围的末尾是任意超大密码长度(10+,我不知道),而大多数密码(包括我倾向于尝试的固定“zzzzz”)要短得多,因此我得到的是第一个线程完成所有工作,其余线程只是浪费时间测试太长的密码和同步;结果实际上比单线程性能慢。

我怎么能拆分任意大范围(实际上不必有终点)成 block 范围并让每个线程在 block 中找到?这将使不同线程中的工作人员真正有用。

最佳答案

This goes through the alphabet first for 1 character strings, then 2

您希望对数据处理进行一些排序,但 Rayon 的全部意义在于并行处理。

相反,使用常规迭代器按顺序增加长度,然后在特定长度内使用并行迭代器快速处理该长度的所有值。

由于您没有为可运行的示例提供足够的代码,我做了这个粗略的近似以显示此类解决方案的一般形状:

extern crate rayon;

use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use std::ops::RangeInclusive;

type Seed = u8;

const LENGTHS: RangeInclusive<usize> = 1..=3;
const SEEDS: RangeInclusive<Seed> = 0..=std::u8::MAX;

fn find<F>(test_password: F) -> Option<(usize, Seed)>
where
    F: Fn(usize, Seed) -> bool + Sync,
{
    // Rayon doesn't support RangeInclusive yet
    let seeds: Vec<_> = SEEDS.collect();

    // Step 1-by-1 through the lengths, sequentially
    LENGTHS.flat_map(|length| {
        // In parallel, investigate every value in this length
        // This doesn't do that, but it shows how the parallelization
        // would be introduced
        seeds
            .par_iter()
            .find_any(|&&seed| test_password(length, seed))
            .map(|&seed| (length, seed))
    }).next()
}

fn main() {
    let pass = find(|l, s| {
        println!("{}, {}", l, s);
        // Actually generate and check the password based on the search criteria
        l == 3 && s == 250
    });

    println!("Found password length and seed: {:?}", pass);
}

这可能会在每个长度的末尾“浪费”一点时间,因为平行线程在旋转到下一个长度之前一个接一个地向下旋转,但这似乎不太可能成为主要问题。

关于multithreading - 我如何使用 Rayon 将大范围拆分为多个范围 block ,并让每个线程在一个 block 中找到?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50271746/

相关文章:

c# - 锁定字典对象的正确方法

c++ - C++中的多线程,从套接字接收消息

c# - 除特定情况外,阻止第二个实例运行

rust - 如何将ParallelIterator转换回顺序Iterator?

multithreading - 如何在self中使用方法使用函数进行线程化?

file-io - rayon::str::Lines <'_' > 不是迭代器

具有并发性的 Python 线程

rust - 如何删除 `let _ : () = ...` ?

rust - 在 actix-web 中处理异步处理程序中的错误最惯用的方法是什么?

rust - 工作区在 Rust 中提供两种不同的行为