免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7730 | 回复: 6
打印 上一主题 下一主题

python 多进程队列 写文件速度问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-11-18 09:49 |只看该作者 |倒序浏览
生产者进程 消费者进程   通过队列保存中间结果  在消费者进程里面 取队列数据 进行写文件 速度一直起不来  2M/s


在消费者进程里面 不取数据 直接循环写 速度也起不来 ,不知道是不是python 队列锁机制的问题

不知道大牛们有没有好的解决办法

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
2 [报告]
发表于 2013-11-18 17:28 |只看该作者
本帖最后由 timespace 于 2013-11-18 17:28 编辑

除了Python的queue,有用其它的进程同步机制吗?还有写入频率和数据块大小?

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
3 [报告]
发表于 2013-11-19 16:05 |只看该作者
用gevent的queue

论坛徽章:
33
荣誉会员
日期:2011-11-23 16:44:17天秤座
日期:2014-08-26 16:18:20天秤座
日期:2014-08-29 10:12:18丑牛
日期:2014-08-29 16:06:45丑牛
日期:2014-09-03 10:28:58射手座
日期:2014-09-03 16:01:17寅虎
日期:2014-09-11 14:24:21天蝎座
日期:2014-09-17 08:33:55IT运维版块每日发帖之星
日期:2016-04-17 06:23:27操作系统版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-24 06:20:0015-16赛季CBA联赛之天津
日期:2016-05-06 12:46:59
4 [报告]
发表于 2013-11-19 16:19 |只看该作者
直接单线程写一下试试先

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
5 [报告]
发表于 2013-11-19 17:22 |只看该作者
还是从自己代码找问题吧,Queue的效率不至于那么低。

CPU:单核3.4GHz
内存:1GB
OS:CentOS 6.4
Python: 2.6.6
场景:在竞争条件下queue的效率,多个生产者进程(示例中为10个)写queue,每个记录为4KiB,每个生产者写100K个记录,一个消费者进程读queue,尽量消除IO的影响,使消费者写/dev/null
结论:平均数据写入速度高于50MiB/s

代码:
  1. #!/usr/bin/env python

  2. import io, os, sys
  3. from multiprocessing import Process, Queue
  4. from datetime import datetime

  5. def producer(q, no):
  6.     blk_data = bytearray(4096) # bytes
  7.     cnt = 0
  8.     while cnt < 10 ** 5:
  9.         q.put(blk_data)
  10.         cnt += 1

  11. def consumer(q):
  12.     begin_time = datetime.now()
  13.     blk_cnt = 0
  14.     with io.open(os.devnull, 'wb') as fp:
  15.         while True:
  16.             blk_data = q.get()
  17.             if not isinstance(blk_data, bytearray):
  18.                 break
  19.             fp.write(blk_data)
  20.             blk_cnt += 1
  21.     end_time = datetime.now()
  22.     print 'duration', end_time - begin_time
  23.     print 'data size', blk_cnt / 256 , 'MiB'

  24. def main():
  25.     if len(sys.argv) != 2:
  26.         sys.exit('{0} producers'.format(sys.argv[0]))

  27.     log_queue = Queue() # the queue of log record
  28.     proc_producer = [
  29.             Process(target=producer, args=(log_queue, i))
  30.             for i in range(int(sys.argv[1], 10))]
  31.     proc_consumer = Process(target=consumer, args=(log_queue,))
  32.     for p in proc_producer:
  33.         p.start()
  34.     proc_consumer.start()

  35.     for p in proc_producer:
  36.         p.join()
  37.     log_queue.put(None) # notify consumer to exit
  38.     proc_consumer.join()

  39. if __name__ == '__main__':
  40.     main()
复制代码
运行:
  1. $ ./mp_queue.py 10
  2. duration 0:01:07.505177
  3. data size 3906 MiB
复制代码

论坛徽章:
0
6 [报告]
发表于 2013-12-04 15:44 |只看该作者
blk_data = bytearray(4096)
如果是字符串  只有 10个字节左右  不用字节数组  速度就降下来了

是不是要把字符串连接起来存呢?  

论坛徽章:
4
白羊座
日期:2013-11-05 10:26:09冥斗士
日期:2015-11-17 14:19:55白银圣斗士
日期:2015-11-17 15:13:0815-16赛季CBA联赛之新疆
日期:2016-04-01 09:10:58
7 [报告]
发表于 2013-12-04 16:53 |只看该作者
回复 6# tjlizheng


    这里速度的关键是 bytearray 的大小和 IO 的速度。

    比如:你把 timespace 代码的 4096 改成 32,当然,对应的 size 计算的部分也从 /256 改成 /32768,就会发现两个运行的传输效果大约前者是后者的:16 倍 < 4096 / 32 = 128
    也就是说:在 buffersize (就是 bytearray )空间比较大的时候,时间主要是在花在传输和切换两方面上。 当 buffersize 比较小时,主要时间是在切换上。
    从比值可以猜测,当 buffersize 在 <256 的时候,效率可能是个正比与 buffersize的值,这时主要时间用在切换线程。

    基于 timespace 的代码实验的结果是: buffersize = 256 传输 244M 需要 22s => 244 / 22 ~ 11, buffersize = 32, 传输 30M 需要 20s => 30 / 20 ~ 1.5。速度比和 buffersize 的比值都接近 8,应当是切换影响大。

    但是:当 buffersize 继续上上升时,读取数据也会花时间:
    我实验的结果是:buffersize = 1024 传输 976M 需要 40s => 976 / 40 ~ 24.4, buffersize = 4096, 传输 3906M 需要 70s => 3906 / 70 ~ 56。
    速度比和 buffersize 比已经不是很一致了, buffersize 比是 4 倍, 但是速度比是 2.3 倍左右。

    所以,当数据少的时候,最好提升一次性传输的数据大小,可以在近乎相同的切换次数的情况下提升传输数据量,当数据多的时候,buffersize 仍然有效,但是 I/O 影响也开始上升,提升就没有那么明显了。

    就你的数据传输问题来说,因为字符串太小,建议先把一次性传输的内容数量提升,如果你的字符串只有 10 几个字节,最好把至少 256/10 大约 20 个左右的字符串一起传送会好些。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP