2012-07-04 56 views
1

我对Python非常陌生,因此没有完全意识到它的强大功能。我有下面这段代码,我认为它应该更快。我有一个感觉,它可以使用numpy/map完成,但不知道如何构建它。Python:如何更好地编写下面这段代码?

无论所讨论的字典这里有10,000个键与由7个元素,等列表形成值:

T_com ={0: [[1.2, 3,.65,.63, 3, 3 , 5.5]] 1:[[1.7, 2,.55,.13, 2, 8 , 5.5]] ...10,000th key:[[3.2, 9,.15,.23, 1, 3 , 2.5]]} 

对于这一点,我的当前代码(下面讨论)被拉伸成小时,我有一种感觉不好。基本上,我正在阅读与字典中每个键相关的列表,计算它们的分数,然后将分数附加到字典中,最后写入ZODB。以下是摘录(字典R_com在结构上T_com完全相似的上述定义。):

for tar_node,tar_community in T_com.iteritems(): # iterate over the key value pair of first dic 
    for i,(ref_node,ref_community) in enumerate(R_com.iteritems()): # iterate over second dictionary. Enumeration was required for some other operation 
     score = compute_score(T_com[tar_node],R_com[ref_node])  # calculate some score 
     bTree_container.setdefault(tar_node,PersistentList()).append([ref_node,score,priority.pop(),0]) #Builds a list of lists associated with every value of tar_node 
     if i % 2500 ==0:   # After every 2,500 values temporarily save the data to disk 
      transaction.savepoint(True) 
transaction.commit() # finally write all the data to disk 

如何减少运行时间任何建议/避免环路?在genereal中,python中处理这种情况的最佳实践是什么?

如所建议的一些结果从CPROFILE: -

200000000 3792.449 0.000 3792.449 0.000 {numpy.core.multiarray.array} 
100000000 51.033 0.000 51.186 0.000 {method 'setdefault' of 'BTrees.IOBTree.IOBTree' objects} 
+1

可能属于[codereview](http://codereview.stackexchange.com/)? – inspectorG4dget

+2

您正在循环100,000,000次 - 当然这很慢。 'compute_score'是做什么的? –

+0

compute_score是一个非常简单的函数,只需计算两个向量的点积,首先将它们转换为numpy array()。 –

回答

0

从它正在创建一棵树,并在每个你遍历字典中的每个元素的新节点的外观。

如果你需要检查字典中的每个元素来计算分数,你唯一的选择是有一个辅助资源,其中包含一些计算,这将阻止你必须重复每个字段。

同样,您可以保留每个字典的生成树的副本,然后简单地添加到每个字典,因为您获得更多信息并最终将它们链接在一起。

对不起,我早就离开这个作为一个评论,但我不发表评论或可能无法弄清楚如何...

无论如何,祝你好运!

0
score = compute_score(T_com[tar_node]tar_community,R_com[ref_node]ref_community)

这可以为您节省一些字典查找时间,但您的根本问题是x * y;如果你真的需要这个,并且关心运行时间,考虑使用cython或纯c代码来加速

+0

想过使用C,但是目前我正在寻找pythonic优化方法。 –

+0

pinkdawn:你能给出一些关于如何将上面的代码转换成Cython的线索吗?我在这个领域没有经验。 –

+0

@ R.Bahl检查教程在这里:http://docs.cython.org/src/userguide/tutorial.html; cython会自动为你生成c代码,并且调用gcc来编译它,如果你可以做c,你也可以修改cython生成的代码 – pinkdawn

0

即使compute_score的每次执行只需要1ms,如果T_com中有10k个元素,而R_com中有10k个元素,带你10k * 10k * 1ms,大概是27个小时。你提出的方式,这是一个O(n2)问题。你能简化你的逻辑吗?如果你不能,你需要其他技术 - 例如并行或分布式执行。

==编辑==

正如您在评论中所述,这是一个点积。你可以尝试减少到​​O(N)?例如:

scores = [] 
for index in T_com.keys(): 
    score = T_com[index] * R_com[index] 
dot_product = sum(scores) 
+0

其实compute_Score比它快,大概需要10^-4,所以这段代码占用3小时。您可以将逻辑看作计算存储在两个字典中的一组矢量的成对智慧点积,然后将结果存储在磁盘上。但我有一种感觉,有一种更好的方式来编写它在python中,可能使用numpy索引或地图,但不知道如何 –

+0

感谢您的建议。我不确定这会如何工作,但让我想一想。 –