这是我第一次用Python做这么大的事情,所以我需要一些帮助。在
我有一个mongodb(或python dict),其结构如下:
{
"_id": { "$oid" : "521b1fabc36b440cbe3a6009" },
"country": "Brazil",
"id": "96371952",
"latitude": -23.815124482000001649,
"longitude": -45.532670811999999216,
"name": "coffee",
"users": [
{
"id": 277659258,
"photos": [
{
"created_time": 1376857433,
"photo_id": "525440696606428630_277659258",
},
{
"created_time": 1377483144,
"photo_id": "530689541585769912_10733844",
}
],
"username": "foo"
},
{
"id": 232745390,
"photos": [
{
"created_time": 1369422344,
"photo_id": "463070647967686017_232745390",
}
],
"username": "bar"
}
]
}
现在,我想创建两个文件,一个包含摘要,另一个包含每个连接的权重。适用于小型数据集的循环如下:
^{pr2}$缩放问题:我有20000个位置,每个位置可能有多达2000个用户,每个用户可能有10张左右的照片。在
有没有更有效的方法来创建上述循环?可能是多线程,JIT,更多的索引? 因为如果我在一个线程中运行以上操作,最多可以得到20000^2*2000*10个结果。。。在
那么如何才能更有效地处理上述问题呢? 谢谢
瓶颈是磁盘I/O
当您合并结果并使用一个或多个
writerows
调用而不是多个writerow
时,它应该快得多。在@YuchenXie和@PaulMcGuire建议的微优化可能不是你的主要问题,那就是你循环超过20000×20000=400000000对条目,然后有一个2000×2000用户对的内部循环。那会很慢的。在
幸运的是,通过预缓存
i['users']
中的用户id的set
,并用一个简单的集合交集替换内部循环,可以更快地完成内部循环。这将Python解释器中的O(num_users^2)
操作更改为C中的O(num_users)
操作,这应该会有所帮助。(我只是用大小为2000的整数列表来计时;在我的电脑上,它从原来的156ms变为现在的41µs,速度提高了4000倍。)您还可以通过注意到关系是对称的,来切断对位置的主循环的一半工作,因此没有必要同时执行},
i = a[1]
,q = a[2]
和{q = a[1]
。在考虑到这些和@PaulMcGuire的建议,再加上一些其他风格上的变化,您的代码将变成(注意:前面未测试的代码):
希望这足够加速了。如果不是,那么@YuchenXie的建议可能会有帮助,尽管我对此表示怀疑,因为stdlib/OS在缓冲此类问题上相当出色。(您可以使用文件对象上的缓冲设置。)
否则,它可能会归结为尝试从Python(Cython或手写C)中获取核心循环,或者给PyPy一次机会。不过,我很怀疑这会给你带来巨大的加速。在
你也可以把计算重量的方法推到Mongo中,这可能更聪明;我从来没有真正使用过它,所以我不知道。在
折叠此循环:
下至:
^{pr2}$有什么帮助吗?在
你的体重计算:
还应可折叠为:
因为True等于1,所以求和所有布尔条件等于计算所有为True的值。在
相关问题 更多 >
编程相关推荐