用多进程程序求e超过gmpy2的exp() - l1t1/note GitHub Wiki
import numpy as np
import gmpy2
from gmpy2 import mpfr
# 设置位数
n = 1000000 #int(input("请输入位数:"))
gmpy2.get_context().precision =int( (n+1)*3.34)
# 平方根
#result = gmpy2.sqrt(mpfr(2))
result = gmpy2.exp(mpfr(1))
# 打印结果
print("平方根结果:", str(result)[:1000002])
vs
#多线程不会快,多进程才行,至少在Linux是的
import math
import time
import sys
import gmpy2
from gmpy2 import mpz, log, const_pi
import multiprocessing
from concurrent.futures import ProcessPoolExecutor
def get_max_threads():
"""获取系统核数并限制最大线程数"""
max_cpus = multiprocessing.cpu_count()
return max(1, min(max_cpus, 8)) # 限制不超过8线程
def find_required_terms(digits):
"""精确计算所需最小n使得n! > 10^digits"""
ln_10 = log(mpz(10))
n_low, n_high = 0, 2 * (digits + 1)
while n_low < n_high:
mid = (n_low + n_high) // 2
if mid <= 1:
stirling = mpz(0)
else:
mid_mpz = mpz(mid)
stirling = mid_mpz * log(mid_mpz) - mid_mpz + log(2 * const_pi() * mid_mpz) / 2
if stirling > digits * ln_10:
n_high = mid
else:
n_low = mid + 1
return n_low
def calculate_part(args):
"""计算部分区间并统计耗时"""
start, end, i = args
part_start = time.time()
coeff = numerator = mpz(1)
for k in range(1, end-start+1):
coeff *= (end - k + 1)
numerator += coeff
if i > 0:
numerator -= coeff
elapsed = time.time() - part_start
return numerator, coeff, elapsed
def calculate_e_parallel(digits, num_parts=2):
"""并行分块计算(带耗时统计)"""
m = find_required_terms(digits)
power = mpz(10)**digits
part_size = m // num_parts
# 计算各部分区间(动态调整负载)
ranges = []
for i in range(num_parts):
start = i * part_size
end = (i+1)*part_size if i < num_parts-1 else m
ranges.append((start, end, i))
# 并行计算各部分
max_threads = get_max_threads()
part_times = []
with ProcessPoolExecutor(max_workers=max_threads) as executor:
results = list(executor.map(calculate_part, ranges))
# 分离结果和耗时
parts = []
for numerator, coeff, elapsed in results:
parts.append((numerator, coeff))
part_times.append(elapsed)
# 合并结果
combined_num = 0
combined_den = 1
for num, den in reversed(parts):
combined_num += num * combined_den
combined_den *= den
total = (combined_num * power) // combined_den
return "2." + str(total % power), part_times
if __name__ == "__main__":
# 测试配置
digits = 1000000
test_cases = [
# ("单线程", 1),
# ("2线程", 2),
# ("4线程", 4),
("8线程", 8)
]
multiprocessing.freeze_support()
print("系统核数: ", multiprocessing.cpu_count())
print("计算e的", digits, "位近似值 (并行优化)\n")
# 基准测试
reference = None
for name, parts in test_cases:
if parts > get_max_threads():
print(name, " 跳过(超过最大线程限制)")
continue
start = time.time()
result, part_times = calculate_e_parallel(digits, parts)
total_time = time.time() - start
print(name, " 总耗时: ", "%.3f" % total_time, "s")
print("各部分耗时: ", ["%.3f" % t for t in part_times], "s")
print("前50位: ", result[:52])
if reference is None:
reference = result
else:
mismatch = next((i for i in range(len(reference)) if reference[i] != result[i]), None)
print("结果验证: ", '一致' if mismatch is None else '第'+str(mismatch)+'位不一致')
print("--------------------------------------------------")
print(result)
print(time.time() - start,"s")
#from multiprocessing import freeze_support
#do somthing
#if __name__ == "__main__":
# freeze_support() # Windows加上这一句,并要在上面一行下执行
测试结果
gmpy2.exp(1)
7694228188
Kernel Time = 0.140 = 28%
User Time = 0.375 = 77%
Process Time = 0.515 = 106% Virtual Memory = 509 MB
Global Time = 0.485 = 100% Physical Memory = 35 MB
gmpy2手工迭代+多进程
7694228188
Kernel Time = 0.078 = 19%
User Time = 0.140 = 35%
Process Time = 0.218 = 55% Virtual Memory = 19 MB
Global Time = 0.392 = 100% Physical Memory = 26 MB