关于迭代器的操作

2015-06-29 09:59:39 +08:00
 aragakiiyui
我想问一下各位大神有没有什么方法更快的去遍历一个迭代器。

我要处理的一个Iterators大概包含了将近900万个元素。如果直接用 for ... in ... 的方式去遍历,根本无法再规定的时间内完成需求。
我目前是用iteratool.islice去做,每个线程切1000个出来,转成列表来处理,但是几乎没什么提升。而且转换成list这个操作也很耗时间....有没有什么方法可以多线程去取里面的元素?或者有没有什么其他好的方法或者经验?
3175 次点击
所在节点    Python
27 条回复
hahastudio
2015-06-29 10:06:28 +08:00
这个,基本上,很难
因为一个 iterator 的当前值很有可能是会跟前几次迭代有关的,比如用 generator 写一个 Fibonacci 生成

不知道少开几个线程会怎么样,比如一个线程处理 100W 个这样的
实在不行,用 C/C++ 吧
neoblackcap
2015-06-29 10:10:39 +08:00
为什么要去遍历一个迭代器?要不说说你具体的需求?你是不是要查找某个元素,还是说必须对每个元素都进行某种操作?
bigtan
2015-06-29 10:12:40 +08:00
试试cython,不过还是要看你需要什么操作
echo1937
2015-06-29 10:22:34 +08:00
用generator去实现,然后多线程去遍历?
yuankui
2015-06-29 10:28:02 +08:00
知道有GIL这个东西吗?

CPU密集型的job基本多线程与单线程没啥区别...

如果机器cpu没跑满的话,可以试试[多线程](http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431927781401bb47ccf187b24c3b955157bb12c5882d000)

再不行,就分布式吧~
yuankui
2015-06-29 10:28:38 +08:00
笔误 [多线程]->[多进程]
aragakiiyui
2015-06-29 10:31:15 +08:00
@neoblackcap @bigtan 其实我程序的功能就是把es中某个表的所有元素取出来,然后对每个元素进行一些处理,最后放到一个新的表中。 拿的这个过程请忽略,反正就是拿出了一个包含800多万数据的迭代器。我想知道有没有什么方法,可以将这个迭代器拆成多个部分去多线程处理?如果直接跑一个for循环的话需要将近两个小时,完全没法完成需求。。。
mhycy
2015-06-29 10:31:22 +08:00
单线程遍历并异步分发,多线程处理。。。
aragakiiyui
2015-06-29 10:33:14 +08:00
@hahastudio 我测了一下,发现使用islice拆分的话,islice操作占到总时间的40%以上。线程开多了反而更慢。
aragakiiyui
2015-06-29 10:33:45 +08:00
@mhycy 嗯,我现在打算这么试试看,能改进一些么。
mhycy
2015-06-29 10:36:16 +08:00
@aragakiiyui
你没说清楚你的那个处理是做啥的能改善多少没法说清。。。
如果是CPU压力大的应用,写个C/C++扩展吧,多进程是必须的了。
如果是IO压力大的应用,改善IO才是最重要的。

关键是我们不知道你做的是啥操作。。。
说回来800W数据都在内存?
0bit
2015-06-29 10:37:35 +08:00
为啥不在取的时候处理呢,分发给多进程,用offset来取数据
seki
2015-06-29 10:59:19 +08:00
multiprocessing map 不知道管不管用
aragakiiyui
2015-06-29 11:00:06 +08:00
@mhycy 那我详细说一下吧,我要做的工作是把es中的3个表并作一个表。我要遍历其中三个表中主要的那个表然后结合另外两个表中对应的数据,把数据一条一条拼起来。最后将拼好的数据写到一个新的表中。写操作大概每次1000条效率最高。
使用es的接口取出的那个表是个迭代器,所以800w数据不直接放内存里的。
neoblackcap
2015-06-29 11:13:48 +08:00
@aragakiiyui 既然是从es里面拿的,为什么还有自己切分数据?根据条件筛选出来不就好了,然后就可以直接分布式。

比如client从redis或者rabbitmq里面提取要处理的数据主键范围(eg. 1-1000 或者2000-3000)然后根据这个条件从es里面筛选出结果,然后就自行进行处理,然后写入数据库。这样你看行不?
mhycy
2015-06-29 11:18:34 +08:00
@aragakiiyui
8000000/1000/3600=2.222222222
写入就两小时。。。囧
arbipher
2015-06-29 11:43:12 +08:00
原始数据是迭代器,"转换成list"的话,不是凭空多了很多内存复制?
mozartgho
2015-06-29 11:44:37 +08:00
写C/C++扩展吧,一般这种效率至上的考虑用C/C++
aragakiiyui
2015-06-29 12:04:33 +08:00
@neoblackcap 我来试试看。
aragakiiyui
2015-06-29 15:57:43 +08:00
@neoblackcap 我试过了,直接条件筛选后,整体更加慢了,这样还不如直接全部取出来切分,而且我试了一个队列从迭代器中读取数据,另外开五个线程执行写的任务,虽然快了一点,但是效率提升仍然不明显。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/201846

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX