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

大区间素数求解器优化:非零起始区间素数生成加速问询

大区间素数生成优化问题

我需要生成从非零起始值的大区间素数,比如从2^64到2^64+1,000,000。由于不需要生成从0开始的所有素数,传统筛法速度更慢且占用内存更高。我已经实现了多线程版本,现在提供单线程代码以便优化,请问:

  1. 能否通过矩阵并行化来更快地检测素性?
  2. 还有哪些加速方法?

以下是我以2^32到2^32+1,000,000为例的单线程实现代码:

import gmpy2
import timeit

def primes_01(start, end):
    last_six_divisor_1 = start - (start % 6) + 1
    last_six_divisor_2 = start - (start % 6) + 5
    while last_six_divisor_1 < start:
        last_six_divisor_1 += 6
    while last_six_divisor_2 < start:
        last_six_divisor_2 += 6
    candidates_1 = [i for i in range(last_six_divisor_1, end, 6) if gmpy2.is_prime(i)]
    candidates_2 = [i for i in range(last_six_divisor_2, end, 6) if gmpy2.is_prime(i)]
    candidates = [i for i in [2, 3] if start <= i] + candidates_1 + candidates_2
    return candidates


if __name__ == '__main__':
    threads = 1
    min_p, max_p = 2 ** 32, 2 ** 32 + 1_000_000
    rep, num = 1, 1
    f_name = 'pyfilename'
    times = timeit.repeat(setup=f"from {f_name} import primes_01; start={min_p}; end={max_p}",
                          stmt="primes_01(start, end)", repeat=rep, number=num)
    print(sum(times)/(rep*num))

    # import time
    # start = time.time()
    # primes = primes_01(min_p, max_p)
    # print(f"Dur: {time.time()-start}\n{sum([len(primes[i]) for i in range(len(primes))])}")

编辑补充:
上述代码耗时0.148s,而使用分段埃氏筛的Pyprimesieve处理相同区间(2^32到2^32+1,000,000)耗时21.9s,后者时间复杂度表现更差,对应代码如下:

import timeit
min_p, max_p = 2**32, 2**32 + 1_000_000
rep, num = 1, 1
times = timeit.repeat(setup=f"import pyprimesieve; start={min_p}; end={max_p}",
                      stmt="pyprimesieve.primes(start, end)", repeat=rep, number=num)
print(sum(times)/(rep*num))

问题解答

一、矩阵并行化在素性检测中的应用

矩阵并行化可用于加速素性检测,但并非直接对单个素数检测做矩阵运算,而是针对批量候选数的并行调度:

  • 批量候选数的并行映射:将候选数列表拆分为多个子块,借助NumPy向量化、CuPy GPU加速等框架,对每个子块的候选数同时执行素性检测逻辑。不过gmpy2.is_prime本身是C实现的单线程函数,Python层面的矩阵并行框架可能无法完全释放硬件性能,需结合底层并行指令集或GPU加速库。
  • Miller-Rabin测试的并行化:Miller-Rabin算法的多轮基测试可并行执行,可通过矩阵式任务调度,同时处理多个候选数的多轮基测试,本质是把独立测试任务批量并行化。

注意:矩阵并行化更适合大规模批量候选数场景,当区间仅1e6个数时,额外调度开销可能抵消并行收益,需根据实际规模权衡。

二、其他加速方法

1. 优化候选数筛选逻辑

  • 扩展小素数过滤:在6k±1的基础上,提前排除5、7、11等更多小素数的倍数,用位掩码或预计算余数表快速判断,减少需调用gmpy2.is_prime的候选数数量。
  • 用生成器代替列表推导:避免一次性生成所有候选数占用内存,边生成边检测,适配更大区间的处理。

2. 并行化策略优化

  • 多进程替代多线程:Python的GIL会限制CPU密集型任务的多线程效率,改用multiprocessing或concurrent.futures.ProcessPoolExecutor,将候选数区间拆分为多个子区间,每个进程独立处理一个子区间,充分利用多核CPU。
  • 控制任务粒度:拆分区间时避免粒度过小(如每个进程仅处理几个数),减少进程间通信开销;也不要粒度太大,确保每个CPU核心都有任务可执行。

3. 高效素性检测算法选型

  • 指定Miller-Rabin测试基:对于2^64以内的数,仅需测试基[2, 325, 9375, 28178, 450775, 9780504, 1795265022]即可保证确定性,比默认测试更快,可通过gmpy2.is_prime(n, reps=...)指定这些基。
  • 概率测试+确定性验证结合:先对批量候选数做1-2轮快速概率性Miller-Rabin测试,过滤掉大部分合数,再对剩余数做确定性测试,减少总计算量。

4. 底层代码优化

  • 编译型语言/C扩展:将核心素性检测逻辑用C/C++实现后通过Python调用,或用Cython、Numba对Python代码编译优化,降低Python解释器开销。
  • 启用CPU指令集:确保编译时开启AVX、SSE等SIMD指令集,对批量候选数的模运算等操作做向量化加速,gmpy2本身可能已支持,但需确认编译优化是否开启。

5. 精简冗余操作

  • 提前判断start与3的大小:若start > 3,可直接跳过2和3的判断逻辑,减少分支。
  • 用数学公式替代循环:计算区间内第一个6k+1和6k+5的数时,可直接用last_six_divisor_1 = ((start + 5) // 6) * 6 + 1代替循环迭代,提升效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 02:07:11