<p>一般来说,重新设计算法通常比使用多处理更有价值</p>
<p>下面是代码的一个简短实现。我已经对usrList进行了硬编码,由于我无法访问您正在使用的字典文件,因此我使用MacOS附带的默认字典文件。我没有编写嵌套循环和检查重复索引,而是使用itertools模块生成给定长度的usrList的所有排列。这不会有意义地加快代码的速度,但会使演示可能的更改变得更容易:</p>
<pre><code>import itertools
usrList = ['P', 'Y', 'T', 'H', 'O', 'N', 'S']
storedList = []
with open('/usr/share/dict/words', 'r') as dict_file:
dicList = [word.strip().upper() for word in dict_file]
def possible_words(length):
for letter_permutation in itertools.permutations(usrList, length):
word = ''.join(letter_permutation) # itertools returns a tuple, not a string
if word in dicList: # This requires a linear search through the list
storedList.append(word)
for word_length in range(2, 8): # Note that the upper bound is 7 letters, not 8
possible_words(word_length)
</code></pre>
<p>在我的Macbook上运行大约需要47.4秒。为了加快速度,让我们按照您的建议添加多处理。有几种方法可以使用多处理,但最容易实现的可能是创建一个池并调用其<code>map()</code>函数</p>
<p>如果您不习惯使用将其他函数作为参数的函数,那么这种语法可能看起来有点奇怪。实际上,我们正在创建一个工作人员池,然后为该池提供一个函数和一系列用于该函数的参数。然后,各个函数调用在池中拆分,而不是按顺序调用:</p>
<pre><code>import itertools
import multiprocessing
usrList = ['P', 'Y', 'T', 'H', 'O', 'N', 'S']
storedList = []
with open('/usr/share/dict/words', 'r') as dict_file:
dicList = [word.strip().upper() for word in dict_file]
def possible_words(length):
for letter_permutation in itertools.permutations(usrList, length):
word = ''.join(letter_permutation)
if word in dicList:
storedList.append(word)
if __name__ == '__main__': # multiprocessing complains if this isn't isolated
with multiprocessing.Pool(6) as p: # Creates 6 worker processes
p.map(possible_words, range(2, 8)) # Each process calls possible_words() with a different input
</code></pre>
<p>这在我的Macbook上运行时间为32.3秒。我们缩短了四分之一的时间!也许有一些方法可以从这种方法中挤出更多的性能,但也值得研究一下算法,看看是否有其他方法可以加快速度</p>
<p>现在,您正在创建字典单词列表。当您检查列表中是否有潜在单词时,Python必须扫描整个列表,直到找到匹配项或到达末尾。我的内置字典有235K个单词,这意味着它必须对它生成的每个无意义字母组合进行235K字符串比较</p>
<p>如果从使用列表切换到使用集合,Python可以通过使用哈希函数在几乎恒定的时间内查找值,而不是一次扫描一个条目。让我们尝试一下,而不是多处理:</p>
<pre><code>import itertools
usrList = ['P', 'Y', 'T', 'H', 'O', 'N', 'S']
storedList = []
with open('/usr/share/dict/words', 'r') as dict_file:
dicSet = {word.strip().upper() for word in dict_file} # By changing [] to {}, this is now a set
def possible_words(length):
for letter_permutation in itertools.permutations(usrList, length):
word = ''.join(letter_permutation)
if word in dicSet: # This now only does 1 check, not 235,000
storedList.append(word)
for word_length in range(2, 8):
possible_words(word_length)
</code></pre>
<p>仅更改两个字符后,此版本将在<strong>0.005秒内运行</p>
<p>总之,多处理是一个有用的工具,但它可能不应该是您尝试的第一件事。通过仔细考虑您正在使用的数据结构和算法以及瓶颈可能在哪里,您通常会得到更好的结果</p>