【问题标题】:How to monitor the memory consumed by a program with decorators如何使用装饰器监视程序消耗的内存
【发布时间】: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


【解决方案1】:

有很多 Python 的内存分析器。 This answer 列出了其中的一些。

您可以创建一个装饰器,在函数调用之前、函数调用之后检查内存使用情况并显示差异。只要你在单线程中运行,你就应该得到你想要的结果。

【讨论】:

  • 好的,我将研究 memory_profiler,但我认为它会存在一种简单的方法来显示内存差异而不涉及任何第三方库。但是,请记住您对单线程的评论很有趣。谢谢
猜你喜欢
  • 2013-07-17
  • 2017-08-14
  • 2012-10-25
  • 2020-04-21
  • 2015-08-11
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 2022-06-14
相关资源
最近更新 更多