2

以下代码在工作线程中执行,并且很高兴地旋转,接收暂停/报告命令等。我认为它们是软故障,因为我没有 RAM 使用问题并且我的硬盘驱动器没有在周末融化,这与我让结果累积多长时间有关,因为我几天前启动它时只收到约 50 个页面错误。

“计数器”属性当前为 22,496,115,“结果”有 1,418,641 个元素。之所以选择“结果”部分是因为我感到相反,因此从 1 开始。

def run(self):
    while self.keep_running:
        self.lock.acquire()

        is_prime = True
        self.counter += 1
        cutoff_val = pow(self.counter,.5)
        for number in self.results[1:]:
            if number > cutoff_val:
                break

            if self.counter % number == 0:
                is_prime = False
                break

        if is_prime:
            self.results.append(self.counter)

        self.lock.release()

注意:我知道我可以使用Eratosthenes 的筛子来优化算法并可能减少页面错误,但这不是重点:我试图找出确切的原因 - 或者至少是最严重的违规者 - 背后页面错误,这样我就可以避免将来做同样的事情。当我需要一个“极其昂贵、简单的工作线程”时,该算法仅用于测试 UI 响应能力。

根据要求的附加设置:

def __init__(self):
    self.counter = 0
    self.keep_running = False;
    self.lock = threading.Lock()
    self.results = list()

def __call__(self, *args):
    if not self.keep_running:
        self.keep_running = True
        self.run()
4

2 回答 2

4

我认为@John Gaines Jr. 指出了一些你需要改变的地方。如果你的列表真的很大,你不想像那样复制它。

这是一种循环遍历相同值self.results[1:]但不复制的好方法:

res = iter(self.results)  # get an iterator for the list values
next(res)  # iterate once to throw away first value
for number in res:
    # same code you already have goes here
    ...

编辑:上面的代码是正确和简单的,但不能很好地扩展。我想了想,认为这其中一定有一些东西itertools,果然有:

import itertools as it
res = it.islice(self.results, 1, None)
for number in res:
    # same code you already have goes here
    ...

None编辑:感谢@John Gaines Jr. 指出您可以len(self.results)在调用it.islice().

于 2012-09-10T17:26:57.593 回答
3

从 Python 教程列表部分:

所有切片操作都会返回一个包含请求元素的新列表。这意味着以下切片返回列表 a 的浅表副本:

>>> a[:]
['spam', 'eggs', 100, 1234]

因此,在您的 for 循环中,该位self.results[1:]会生成结果列表的副本。如果这个例程被一遍又一遍地调用,它很容易导致内存抖动。

于 2012-09-10T17:20:36.033 回答