转自:http://www.redicecn.com/html/Python/20111223/355.html

Python发挥不了多核处理器的性能(据说是受限于GIL,被锁住只能用一个CPU核心,关于这个,这里有篇文章),但是可以通过Python的multiprocessing(多进程)模块或者并行运算模块(例如,pprocess)来使用到多核。

测试代码如下,程序先后分别测试了串行运算、并行运算以及多线程和多进程执行同一个函数所花费的时间。

  1. #! /usr/local/bin/python2.7
  2. # test.py
  3. import time
  4. import pprocess # 该模块只能在linux下使用
  5. import threading
  6. from multiprocessing import Process
  7. def takeuptime(n):
  8. chars = 'abcdefghijklmnopqrstuvwxyz0123456789'
  9. s = chars * 1000
  10. for i in range(10*n):
  11. for c in chars:
  12. s.count(c)
  13. if __name__ == '__main__':
  14. list_of_args = [1000, 1000, 1000, 1000]
  15. # Serial computation
  16. start = time.time()
  17. serial_results = [takeuptime(args) for args in list_of_args]
  18. print "%f s for traditional, serial computation." % (time.time() - start)
  19. # Parallel computation
  20. nproc = 4 # maximum number of simultaneous processes desired
  21. results = pprocess.Map(limit=nproc, reuse=1)
  22. parallel_function = results.manage(pprocess.MakeReusable(takeuptime))
  23. start = time.time()
  24. # Start computing things
  25. for args in list_of_args:
  26. parallel_function(args)
  27. parallel_results = results[:]
  28. print "%f s for parallel computation." % (time.time() - start)
  29. # Multithreading computation
  30. nthead = 4 # number of threads
  31. threads = [threading.Thread(target=takeuptime, args=(list_of_args[i],)) for i in range(nthead)]
  32. start = time.time()
  33. # Start threads one by one
  34. for thread in threads:
  35. thread.start()
  36. # Wait for all threads to finish
  37. for thread in threads:
  38. thread.join()
  39. print "%f s for multithreading computation." % (time.time() - start)
  40. # Multiprocessing computation
  41. process = []
  42. nprocess = 4 # number of processes
  43. for i in range(nprocess):
  44. process.append(Process(target=takeuptime, args=(list_of_args[i],)))
  45. start = time.time()
  46. # Start processes one by one
  47. for p in process:
  48. p.start()
  49. # Wait for all processed to finish
  50. for i in process:
  51. p.join()
  52. print "%f s for multiprocessing computation." % (time.time() - start)

运行结果如下:

[root@localhost test]# python test.py

62.452934 s for traditional, serial computation.

20.665276 s for parallel computation.

64.835923 s for multithreading computation.

18.392281 s for multiprocessing computation.

从测试结果可以明显看出并行运算和多进程计算速度明显要快于串行计算和多线程计算。

这里有个问题,为什么多线程的所花的时间不比串行单线程的少呢(64.873760 > 62.452934)?

根据我们的常规经验,多线程肯定要比单线程要快,为什么测试结果却不是这样呢?

前面已经提到了,Python只能用到一个CPU核心,因此即便是多线程,在同一时间CPU也只能处理一个线程运算,多个线程并不能并行的运行,他们是轮流切换执行的。

因此,只有当线程中会出现阻塞时,多线程才有意义,比如线程中有数据下载,在等待数据返回时线程阻塞了,此时CPU就可以来处理其它线程的运算。

上面测试程序中的takeuptime()函数没有阻塞,它不停地在进行着运算,所以多线程和单线程的效果是一样的(线程切换也会花费时间,所以此时多线程花费的时候甚至比单线程多一些)。

并行运算和多进程运算之所以快,就是因为他们能同时利用多个CPU核心,多个数据运算能同时进行。

我们把takeuptime()函数改成有阻塞的,再测试一下:

  1. def takeuptime(n):
  2. def download(url):
  3. # simulate downloading
  4. time.sleep(2)
  5. for i in range(5):
  6. html = download('http://www.redicecn.com/page%d.html' % i)

新的运行结果如下:

[root@localhost test]# python test.py

39.996438 s for traditional, serial computation.

10.003863 s for parallel computation.

10.003480 s for multithreading computation.

10.008936 s for multiprocessing computation.

可以看到在有阻塞的数据处理过程中,多线程的作用还是很明显的。

感谢Richard, 和老吴。

Python串行运算、并行运算、多线程、多进程对比实验的更多相关文章

  1. python学习之多线程多进程

    python基础 进程&线程 进程是一组资源的集合,运行一个系统就是打开了一个进程,如果同时打开了两个记事本就是开启了两个进程,进程是一个笼统的概念,进程中由线程干活工作,由进程统一管理 一个 ...

  2. 011_Python中单线程、多线程和多进程的效率对比实验

    Python是运行在解释器中的语言,查找资料知道,python中有一个全局锁(GIL),在使用多进程(Thread)的情况下,不能发挥多核的优势.而使用多进程(Multiprocess),则可以发挥多 ...

  3. python之路-----多线程与多进程

    一.进程和线程的概念 1.进程(最小的资源单位): 进程:就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成. 程序:我们编写的程序用来描述进程要完成哪些功能以 ...

  4. Python有了asyncio和aiohttp在爬虫这类型IO任务中多线程/多进程还有存在的必要吗?

    最近正在学习Python中的异步编程,看了一些博客后做了一些小测验:对比asyncio+aiohttp的爬虫和asyncio+aiohttp+concurrent.futures(线程池/进程池)在效 ...

  5. 第十章:Python高级编程-多线程、多进程和线程池编程

    第十章:Python高级编程-多线程.多进程和线程池编程 Python3高级核心技术97讲 笔记 目录 第十章:Python高级编程-多线程.多进程和线程池编程 10.1 Python中的GIL 10 ...

  6. Python系列之多线程、多进程

    线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程. Python的标准库提供 ...

  7. 为什么在Python里推荐使用多进程而不是多线程

    转载  http://bbs.51cto.com/thread-1349105-1.html 最近在看Python的多线程,经常我们会听到老手说:"Python下多线程是鸡肋,推荐使用多进程 ...

  8. 为什么在Python里推荐使用多进程而不是多线程?

    最近在看Python的多线程,经常我们会听到老手说:“Python下多线程是鸡肋,推荐使用多进程!”,但是为什么这么说呢?   要知其然,更要知其所以然.所以有了下面的深入研究: 首先强调背景: 1. ...

  9. 为什么在Python里推荐使用多进程而不是多线程?(为什么python多线程无法增加CPU使用率?)

    最近在看Python的多线程,经常我们会听到老手说:“Python下多线程是鸡肋,推荐使用多进程!”,但是为什么这么说呢? 要知其然,更要知其所以然.所以有了下面的深入研究: 首先强调背景:     ...

随机推荐

  1. php生成excel或php生成csv

    一.php生成excel 使用phpexcel类文件生成 二.php生成csv <?php$action ="make";if ($action=='make'){ $fp ...

  2. Ping pong

    Ping pong Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  3. python--json & pickle 模块

    用于序列化的两个模块 json,用于字符串 和 python数据类型间进行转换 pickle,用于python特有的类型 和 python的数据类型间进行转换 Json模块提供了四个功能:dumps. ...

  4. css笔记07:通配符选择器

    通配符选择器: * { margin:10px ;//默认四个位置参数全为零 margin-top:10px;//分别设置四个参数 margin-left:10px; margin-right:0px ...

  5. Android AdapterView 源码分析以及其相关回收机制的分析

    忽然,发现,网上的公开资料都是教你怎么继承一个baseadapter,然后重写那几个方法,再调用相关view的 setAdpater()方法, 接着,你的item 就显示在手机屏幕上了.很少有人关注a ...

  6. Clover:让Windows下的资源管理器具有Chrome一样的标签页

    这个小巧实用的插件第一次激发了我给人捐款的冲动. 不多说,上图看效果: 具有和Chrome一样的书签功能,以网页的形式保存本地位置,将常用目录放在书签上十分方便. 多标签相比多窗口的优势不需要我多说, ...

  7. 编写SASS的一些技巧

    更好的为变量命名 变量是Sass中最简单的特性之一,但有时候也会使用不当.创建站点范围内有语义化的变量,是不可或缺的工作.如果命名不好,他会变得难以理解和重复使用. 这里有一些命名变量的小技巧,提供参 ...

  8. Android平台使用SQLite数据库存储数据

    创建一个DataBaseHelper的类,这个类是继承SQLiteOpenHelper类的,这个类中包含创建数据库.打开数据库.创建表.添加数据和查询数据的方法.代码如下: package com.e ...

  9. [Jquery] 获取地址栏参数的方法 备忘

    <script type="text/javascript"> (function ($) { $.getUrlParam = function (name) { va ...

  10. JAVA之经典Student问题1

    通过“三目运算符”求最大值与最小值. class student { //定义学生编号 private String stu; //学生姓名 private String name; //学生书信成绩 ...