我最近尝试使用多处理模块(和它的工作池)加速一个小工具(它使用urllib2向(非官方的)twitter按钮计数url(>;2000 url)发送请求并解析其结果)。我在这里读了几篇关于多线程(与标准的、非线程的版本相比,这会减慢整个过程)和多处理的讨论,但是我找不到一个(可能非常简单)问题的答案:
你能用多处理来加速url调用吗?或者瓶颈不是网络适配器之类的东西?例如,我不知道urllib2 open方法的哪个部分可以并行化,也不知道它应该如何工作。。。
编辑:这是我想要加速的请求和当前的多处理设置:
urls=["www.foo.bar", "www.bar.foo",...]
tw_url='http://urls.api.twitter.com/1/urls/count.json?url=%s'
def getTweets(self,urls):
for i in urls:
try:
self.tw_que=urllib2.urlopen(tw_url %(i))
self.jsons=json.loads(self.tw_que.read())
self.tweets.append({'url':i,'date':today,'tweets':self.jsons['count']})
except ValueError:
print ....
continue
return self.tweets
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=4)
result = [pool.apply_async(getTweets(i,)) for i in urls]
[i.get() for i in result]
这要看情况!你是在联系不同的服务器,传输的文件是小文件还是大文件,你是否在等待服务器回复或传输数据时浪费了很多时间,。。。
通常,多处理涉及一些开销,因此您希望确保通过并行化工作获得的加速比开销本身更大。
另一点:网络和I/O绑定的应用程序在异步I/O和事件驱动体系结构中工作得更好,而不是线程或多处理,因为在这些应用程序中,大部分时间都花在等待I/O和不进行任何计算上。
对于您的特定问题,我将尝试通过使用Twisted、gevent、Tornado或任何其他不使用线程来并行连接的网络框架来实现解决方案。
看看gevent,特别是这个例子:concurrent_download.py。它将比多处理和多线程处理快得多,它可以轻松地处理数千个连接。
又来了一个关于吉尔的讨论。好吧,事情是这样的。使用urllib2获取内容将主要受的IO约束。当任务受IO限制时,本机线程和多处理都将具有相同的性能(只有当任务受CPU限制时,线程才成为问题)。是的,你可以加快速度,我已经用python线程和10个下载线程自己完成了。
基本上,您使用生产者-消费者模型,其中一个线程(或进程)生成要下载的url,而N线程(或进程)从该队列消费并向服务器发出请求。
下面是一些伪代码:
现在,如果您下载的是非常大的数据块(数百MB),并且一个请求完全饱和了带宽,那么运行多个下载是没有意义的。运行多个下载(通常)的原因是请求很小,并且具有相对较高的延迟/开销。
相关问题 更多 >
编程相关推荐