You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rayon find_any找到解后其余线程仍运行的优化问询

优化并行暴力破解离散对数的线程终止逻辑

首先翻译Rayon官方文档中关于find_any的描述:

在并行迭代器中搜索符合给定断言的元素并返回它。这个操作类似顺序迭代器上的find,但由于是并行搜索整个序列,返回的元素可能不是序列中第一个符合条件的。

一旦找到匹配项,我们会尽快尝试停止处理迭代器中的其余元素(就像find找到匹配项后立即停止迭代一样)。

你的问题核心在于:find_any只能停止迭代器中未开始执行的任务,但无法中断已经在运行的线程内部的循环。每个线程的while循环会一直执行到结束,直到自己的chunk遍历完,即使其他线程已经找到结果。

优化方案

  1. 使用**原子布尔值(AtomicBool)**作为全局终止标志,线程可以无锁快速检查是否已找到结果
  2. 优化幂次计算:避免每次调用modpow,改为逐步乘积累加,大幅提升计算效率

以下是修改后的代码:

use num_bigint::BigUint;
use num_traits::One;
use rayon::prelude::*;
use std::sync::{Mutex, atomic::{AtomicBool, Ordering}};

fn main() {
    let p = BigUint::parse_bytes("531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127"
        .as_bytes(), 10).unwrap();
    let g = BigUint::parse_bytes("743488989946216334211646350465118756727157777337013657445667148279632819469843031446430723942629760903918287800011367316376"
        .as_bytes(), 10).unwrap();
    let y = BigUint::parse_bytes("85300193795644893333630947242400469685524126293619036977651049331711403849653080708338436527820826037193273430333874138094661788038445049976895820193634304228963983382234907450594225"
        .as_bytes(), 10).unwrap();

    println!("g: {}", g);
    println!("y: {}", y);

    // Brute force y = g^x
    let size = BigUint::from(2u32).pow(20);
    let num_cores = 8 as usize;
    let chunk_size = &size / num_cores;

    let found = AtomicBool::new(false);
    let num = Mutex::new(None);

    (0..num_cores)
        .into_par_iter()
        .find_any(|&core_idx| {
            let start = chunk_size.clone() * core_idx;
            let end = if core_idx == num_cores - 1 {
                size.clone()
            } else {
                start.clone() + chunk_size.clone()
            };

            // 预计算当前chunk的起始幂次,之后逐步累加
            let mut current = g.modpow(&start, &p);
            let mut x = start.clone();
            
            while x < end && !found.load(Ordering::Relaxed) {
                if current == y {
                    found.store(true, Ordering::Relaxed);
                    *num.lock().unwrap() = Some(x.clone());
                    println!("Found x: {}", x);
                    return true;
                }
                // 逐步计算下一个幂次,比modpow高效得多
                current = (&current * &g) % &p;
                x += BigUint::one();
            }

            false
        });

    if let Some(x) = num.lock().unwrap().clone() {
        println!("Found num: {}", x);
    } else {
        println!("x not found in the specified range.");
    };
}

关键优化点说明

  • 原子终止标志:AtomicBool的load和store操作是无锁的,线程可以快速检查是否需要终止循环,避免不必要的计算
  • 幂次累加优化:每个线程只在起始位置调用一次modpow,之后每次迭代只做一次乘法和取模,计算效率提升几个数量级(modpow是O(log n)复杂度,累加是O(1))
  • 立即终止:一旦某个线程找到结果,会立即设置found为true,其他线程在下一次循环检查时就会退出,不会继续无效计算

内容的提问来源于stack exchange,提问作者m0ur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 16:45:43