Windows命令行中的Python脚本行为方式太慢了?

时间:2016-12-14 10:37:05

标签: multithreading python-2.7 cmd word-frequency

我写了一个python类,它使用一个简单的函数来计算文本中的单字节频率:

for listIndex in range(len(words)):
                    uniGramDict[words[listIndex]] =  float(float(words.count(words[listIndex])) / float(len(words)))

我在 windows命令行中测试了包含6个令牌的语料库中的脚本,并取得了预期的结果:

{'a': 0.4, 'c': 0.2, 'b': 0.2, 'd': 0.2}

现在我在一个更大的语料库中运行这个脚本,在Windows命令行中有~750000个令牌,似乎需要花费太多时间,我现在等待40多分钟。

当我查看任务管理器中cmd.exe的CPU /内存使用情况时,我发现几乎没有使用任何资源:0.0%cpu,1.349K ram。

当我查看任务管理器中python.exe * 32的CPU /内存使用情况时,我发现使用的资源不多:25%cpu(我猜是4个核心中的一个)和43.544K ram。

我有什么办法可以加快任务吗?是import multithreading并正确使用我要找的东西吗?

谢谢,

2 个答案:

答案 0 :(得分:0)

您不需要多线程来加速该过程。只是一个更好的算法。 在您的代码中 - 为了计算每个单词 - 您进行50000 * 50000 = 2,500,000,000比较!每当你再次看到它时,你就会数字。 (想象一下你的语料库是50000单词“foo”。所以你计算50000次单词“foo”,只保留最后一个结果丢弃其他49999.)

这是二次增长。对于两倍的令牌,你需要4倍的时间。

而是通过您的列表一次并计算您在途中看到的每个字词:

from collections import defaultdict
def goodcount(words):
    wordcount = defaultdict(int)
    for word in words:
        wordcount[word] += 1
    return {word:float(wordcount[word])/len(words) for word in wordcount}

您可以使用标准词典以及defaultdict来执行此操作,但是您必须首先初始化每个条目:

def goodcount2(words):
    wordcount = dict()
    for word in words:
        if wordcount.has_key(word):
            wordcount[word] += 1
        else:
            wordcount[word] = 1
    return {word:float(wordcount[word])/len(words) for word in wordcount}

让我们进行比较:

tokens: 50000

yourcount:  69.432s
goodcount:   0.016s
goodcount2:  0.031s

不确定为什么要等20分钟,但16秒的工作70秒已经有点太多了。

修改

我看到你现在使用750,000令牌。这是以前的五倍(50,000)。所以你的代码应该是以前的225倍!

在我的机器上大约4小时22分钟。 线性方法应该需要大约。 15 * 0.016s = 0.24 s

答案 1 :(得分:0)

我愿意。

from __future__ import division
for listIndex in xrange(len(words)):
    try:
        uniGramDict[words[listIndex]] += 1
    except:
        uniGramDict[words[listIndex]] = 1

我使用xrange的原因是因为它比range快得多 以及我使用__future__导入的原因,因为它根本没有带您float功能,因为/现在代表真正的分割,而不是地板分割。
注意:__future__导入应位于程序的第一行