Python windows 命令行中的脚本运行速度太慢?
Python script in windows commandline behaving way too slow?
我写了一个python-class,它使用一个简单的函数从文本中计算一元词频率:
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/Memory 使用情况时,我发现几乎没有使用任何资源:0.0% cpu、1.349K ram。
当我查看任务管理器中 python.exe *32 的 CPU/Memory 使用情况时,我发现使用的资源不多:25% cpu(我猜其中之一4 核)和 43.544K 内存。
我可以做些什么来加快任务速度吗? import multithreading
及其正确用法是我要找的吗?
谢谢,
b.
你不需要多线程来加速这个过程。只是一个更好的算法。
在您的代码中 - 为了计算每个单词 - 您进行了 50000 * 50000 = 2,500,000,000 次比较!每次你再次看到它时,你都会数单词。 (假设你的语料库有 50000 个单词 "foo"。所以你计算 50000 次单词 "foo",只保留最后一个结果并丢弃其他 49999 个。)
这是二次方增长。对于两倍多的代币,您需要四倍长的时间。
而是 浏览您的列表一次 并计算您在途中看到的每个单词:
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 分钟,但是 70 秒对于 16µs 的作业来说已经有点太多了。
编辑:
我看你现在用了 750,000 个代币。这是以前(50,000)的 15 倍。所以你的代码应该是以前的 225 倍!
在我的机器上大约需要 4 小时 22 分钟。
线性方法应该需要大约。 15*0.016s = 0.24s
我愿意。
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__
导入应该在程序的第一行
我写了一个python-class,它使用一个简单的函数从文本中计算一元词频率:
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/Memory 使用情况时,我发现几乎没有使用任何资源:0.0% cpu、1.349K ram。
当我查看任务管理器中 python.exe *32 的 CPU/Memory 使用情况时,我发现使用的资源不多:25% cpu(我猜其中之一4 核)和 43.544K 内存。
我可以做些什么来加快任务速度吗? import multithreading
及其正确用法是我要找的吗?
谢谢,
b.
你不需要多线程来加速这个过程。只是一个更好的算法。 在您的代码中 - 为了计算每个单词 - 您进行了 50000 * 50000 = 2,500,000,000 次比较!每次你再次看到它时,你都会数单词。 (假设你的语料库有 50000 个单词 "foo"。所以你计算 50000 次单词 "foo",只保留最后一个结果并丢弃其他 49999 个。)
这是二次方增长。对于两倍多的代币,您需要四倍长的时间。
而是 浏览您的列表一次 并计算您在途中看到的每个单词:
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 分钟,但是 70 秒对于 16µs 的作业来说已经有点太多了。
编辑:
我看你现在用了 750,000 个代币。这是以前(50,000)的 15 倍。所以你的代码应该是以前的 225 倍!
在我的机器上大约需要 4 小时 22 分钟。 线性方法应该需要大约。 15*0.016s = 0.24s
我愿意。
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__
导入应该在程序的第一行