【发布时间】:2015-03-24 00:38:41
【问题描述】:
我再次努力改善这段代码的执行时间。由于计算非常耗时,我认为最好的解决方案是并行化代码。
我首先按照this 问题中的说明使用地图,但后来我尝试了一种更简单的方法,认为我可以找到更好的解决方案。但是我还没有想出任何东西,所以由于这是一个不同的问题,我决定将它作为一个新问题发布。
我正在使用 Python 3.4 在 Windows 平台上工作。
代码如下:
similarity_matrix = [[0 for x in range(word_count)] for x in range(word_count)]
for i in range(0, word_count):
for j in range(0, word_count):
if i > j:
similarity = calculate_similarity(t_matrix[i], t_matrix[j])
similarity_matrix[i][j] = similarity
similarity_matrix[j][i] = similarity
这是calculate_similarity 函数:
def calculate_similarity(array_word1, array_word2):
denominator = sum([array_word1[i] + array_word2[i] for i in range(word_count)])
if denominator == 0:
return 0
numerator = sum([2 * min(array_word1[i], array_word2[i]) for i in range(word_count)])
return numerator / denominator
以及对代码的解释:
-
word_count是列表中存储的唯一单词的总数 -
t_matrix是一个矩阵,其中包含每对单词的值 - 输出应为
similarity_matrix,其维度为word_count x word_count,还包含每对单词的相似度值 - 可以将两个矩阵都保存在内存中
- 经过这些计算后,我可以轻松找到每个单词最相似的单词(或前三个相似的单词,根据任务可能需要)
-
calculate_similarity接受两个浮点列表,每个列表代表一个单独的单词(每个都是 t_matrix 中的一行)
我使用 13k 个单词的列表,如果我计算正确,我的系统上的执行时间将是几天。所以,任何能在一天内完成这项工作的东西都会很棒!
也许只在calculate_similarity 中并行化numerator 和denominator 的计算会带来显着的改进。
【问题讨论】:
-
作为风格问题,您可以通过将第二个循环中的范围更改为第一个循环的
i来迭代“三角形”而不是“正方形”。这样你不会得到太多的性能提升,但你会减少一层嵌套.. :) -
你能用不同的语言吗?也许是 c++ 和 openmp?
-
@wim 你的意思是
for j in range(i, word_count):?我已经尝试过了,但它几乎没有改变。 @Coder Hacker 如果我真的没有其他选择,我会翻译我们到目前为止编写的代码。你认为用 C++ 做这件事会很容易吗? -
@jmunsch:您的代码更快,因为它实际上并没有分配尽可能多的列表。如果您向其中一个内部列表添加一个值,您也会在所有副本中看到它,这可能是不可取的。
-
看看@Blckknght 的解决方案,它比我的有很大的改进。此外,您应该从
calculate_similarity的总和中删除方括号。例如denominator = sum(array_word1[i] + array_word2[i] for i in range(word_count))。在此处使用 generator 而不是列表推导式,可以避免您构建列表并存储大量值来总结它们并丢弃列表。
标签: python parallel-processing multiprocessing python-multithreading python-multiprocessing