【问题标题】:Threaded DES slower than not threaded线程化 DES 比非线程化慢
【发布时间】:2026-01-11 17:45:01
【问题描述】:

我无法通过并行化 DES 加密算法来提高性能。

这是我的尝试:

fn des(message: &[u8], subkeys: Vec<u64>) -> Vec<u8> {
    let mut pool = Pool::new(THREAD_COUNT);
    let message = message_to_u64s(message);

    crossbeam::scope(|scope| {
        pool.map(scope, message.iter().enumerate(), |(i, &block)| {
            let permuted = ip(block);
            let mut li = permuted & 0xFFFFFFFF00000000;
            let mut ri = permuted << 32;

            for subkey in &subkeys {
                let last_li = li;
                li = ri;
                ri = last_li ^ feistel(ri, *subkey);
            }

            let r16l16 = ri | (li >> 32);
            to_u8_vec(fp(r16l16))
        }).collect::<Vec<_>>()
    }).concat()
}

(这使用板条箱 crossbeamsimple_parallel 但我会接受不使用这些的解决方案)

不幸的是,这个实现比没有线程的版本慢:

fn des(message: &[u8], subkeys: Vec<u64>) -> Vec<u8> {
    let message = message_to_u64s(message);

    let mut cipher = vec![];

    for block in message {
        let permuted = ip(block);
        let mut li = permuted & 0xFFFFFFFF00000000;
        let mut ri = permuted << 32;

        for subkey in &subkeys {
            let last_li = li;
            li = ri;
            ri = last_li ^ feistel(ri, *subkey);
        }

        let r16l16 = ri | (li >> 32);
        let mut bytes = to_u8_vec(fp(r16l16));
        cipher.append(&mut bytes);
    }

    cipher
}

我相信collectconcat 是问题所在,但我不知道如何在不使用不安全代码的情况下避免它们。

那么我怎样才能使用安全代码来提高这个算法的性能(通过使用线程)? (不安全代码的解决方案也很有趣,但我相信必须有一个没有不安全代码的解决方案)

【问题讨论】:

  • 这是每字节 1 个线程吗?我可以想象线程旋转的开销是导致基于输入减速的原因。
  • 似乎在任何地方使用&amp;[u8]&amp;[u64] 比使用Vec 更简单。

标签: multithreading rust


【解决方案1】:

使用分析器。您可以尝试猜测减速的位置,但无论如何您可能找不到正确的位置。

但出于有根据的猜测...我会尝试将消息拆分为THREAD_COUNT 部分并将这些部分提供给线程池。如果您单独发送 8 字节的片段,您将花费更多的时间来管理它而不是 DES 本身。

【讨论】:

  • 感谢您的回答。你是对的:我不得不拆分消息。我尝试valgrind 来分析应用程序,但它只说明大部分时间都花在了线程的关闭上:我怎么能从这样的分析结果中猜出你的解决方案?
  • 有趣...我还没有尝试分析螺纹锈。如果您只列出了关闭,而不是收集等,这本身可能是一个很好的问题。理想情况下,每行配置文件在这里会很有用。
  • viraptor:我没有用调试符号编译。有了它们,我看到了更多的函数调用,但我仍然不确定如何猜测这个问题。我在两个valgrind 输出之间看到的一个显着区别是,在我的初始版本中,闭包被调用了很多时间。我认为这是说明使用了太多线程的方法,对吧?谢谢。