【发布时间】:2016-12-29 10:30:35
【问题描述】:
我构建了一个算法 (sieve of Eratosthenes) 来查找素数,但它会消耗大量内存。目前,我的代码使用装饰器来监控时间黯然失色。你能想出一个类似的装饰器来评估我的程序消耗的内存吗?
import math
import time
def time_usage(func):
def wrapper(*args, **kwargs):
beg_ts = time.time()
result = func(*args, **kwargs)
end_ts = time.time()
print("[INFO] elapsed time: %f" % (end_ts - beg_ts))
return result
return wrapper
@time_usage
def find_prime(n):
is_composite = [False for _ in range(n + 1)]
# Cross out multiples of 2
for i in range(4, n, 2):
is_composite[i] = True
# Cross out multiples of primes found so far
next_prime = 3
stop_at = math.sqrt(n)
while next_prime < stop_at:
# Cross out multiples of this prime
for i in range(next_prime * 2, n, next_prime):
is_composite[i] = True
# Move the next prime, skipping the even number
next_prime += 2
while next_prime <= n and is_composite[next_prime]:
next_prime += 2
# Copy the primes into a list
primes = []
for i in range(2, n):
if not is_composite[i]:
primes.append(i)
return primes
if __name__ == '__main__':
print(find_prime(100000))
一个建议是使用第三方库来分析内存使用情况。我使用了memory_profiler,因为它提供了一个很好的装饰器实现,但是我不能同时使用time_usage 装饰器和内存配置文件。
这里我可以看到@profile实际上是在分析time_usage的内存。
import math
import time
from memory_profiler import profile
def time_usage(func):
def wrapper(*args, **kwargs):
beg_ts = time.time()
result = func(*args, **kwargs)
end_ts = time.time()
print("[INFO] elapsed time: %f" % (end_ts - beg_ts))
return result
return wrapper
@profile
@time_usage
def find_prime(n):
is_composite = [False for _ in range(n + 1)]
# Cross out multiples of 2
for i in range(4, n, 2):
is_composite[i] = True
# Cross out multiples of primes found so far
next_prime = 3
stop_at = math.sqrt(n)
while next_prime < stop_at:
# Cross out multiples of this prime
for i in range(next_prime * 2, n, next_prime):
is_composite[i] = True
# Move the next prime, skipping the even number
next_prime += 2
while next_prime <= n and is_composite[next_prime]:
next_prime += 2
# Copy the primes into a list
primes = []
for i in range(2, n):
if not is_composite[i]:
primes.append(i)
return primes
if __name__ == '__main__':
print(find_prime(100000))
制作这个:
Line # Mem 使用增量行内容
7 27.4 MiB 0.0 MiB def wrapper(*args, **kwargs): 8 27.4 MiB 0.0 MiB beg_ts = time.time() 9 28.3 MiB 0.9 MiB result = func(*args, **kwargs) 10 28.3 MiB 0.0 MiB end_ts = time.time() 11 28.3 MiB 0.0 MiB print("[INFO] elapsed time: %f" % (end_ts - beg_ts)) 12 28.3 MiB 0.0 MiB return result[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67、71、73、79、83、89、97、101、103、107、109、113、127、131、137、 ..., 99989, 99991]
【问题讨论】:
-
编写自己的初筛是一个很好的练习,但您可能有兴趣查看Fastest way to list all primes below N 的代码。该页面相当旧,因此有很多 Python 2 的代码,但它仍然值得研究,恕我直言。 Robert William Hanks 的脚本非常好,而且很容易转换为 Python 3。
-
谢谢,我会明确地研究这个选项,但是,在这个问题中,我有兴趣以一种简单的方式监控内存和时间,以便我可以对各种算法实现进行基准测试并查看不同算法的实际影响运行。例如,这段代码有一个
O(N log(log N)),但是当数字太大时使用了不合理的内存量。 -
明白。我的评论没有解决您的分析问题,我只是想您可能想查看其他主要筛分策略。 :) 另外,要在不消耗太多 RAM 的情况下处理大量数据,分段筛可能很有用,例如 this one I wrote a few years ago。要测试非常大的单个数字的素数,请查看Miller-Rabin algorithm。
-
感谢这些链接。很有趣!
标签: python python-2.7 python-3.x memory memory-management