转自: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. Hidden Markov Model

    Markov Chain 马尔科夫链(Markov chain)是一个具有马氏性的随机过程,其时间和状态参数都是离散的.马尔科夫链可用于描述系统在状态空间中的各种状态之间的转移情况,其中下一个状态仅依 ...

  2. github使用成长记

    学校里一直都有自己写一些网页,一方面为了学习熟练技能,另一方面也是兴趣所在.但是独乐乐不如众乐乐,一直向往有那么一个平台能把自己做得东西分享给广大网友,并且想借着分享的契机和各位程序猿交流学习心得(这 ...

  3. iOS 获取内存大小使用情况(进度条显示)

    一.获取设备内存大小方法 //返回存储内存占用比例 - (NSString *)getFreeDiskspaceRate{ float totalSpace; .f; NSError *error = ...

  4. mongoDB 插入数据 用java实现

    import java.net.UnknownHostException; import com.mongodb.BasicDBObject; import com.mongodb.DB; impor ...

  5. Mac Yosemite OS10.10 Apache 虚拟主机设置

    昨天睡觉前开始挂机下载OS10.10 Yosemite,早上6点半就很兴奋地起来安装新系统了.安装完成后打开界面,感觉真的大不一样了,很优很美,很喜欢. 在下载各种更新,体验各种新功能的同时,我也不忘 ...

  6. mysql由于外键关联无法删除数据

    在mysql中删除一张表时候,出现 Error No. 1451 Cannot delete or update a parent row: a foreign key constraint fail ...

  7. 如何用C表示排列组合?

    问题来自<Linux C一站式编程>,是个挺有意思的题目. 2.定义一个数组,编程打印它的全排列.比如定义: #define N 3 int a[N] = { 1, 2, 3 }; 则运行 ...

  8. 打印W图案

    一:规律 二维图形的展示都可以使用二维数组来解决,W图形x轴0,1,2,1,0,1,2.....在0到2直接来回的徘徊 y轴是在一直递增........ 二:代码 @Test /** * 测试打印w图 ...

  9. Java操作图片的工具类

    操作图片的工具类: import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.a ...

  10. [改善Java代码]强制声明泛型的实际类型

    Arrays工具类有一个方法asList可以把一个变长参数或数组变成列表,但是它有一个缺点:它所生成的List长度是不可改变的,而这在我们的项目开发中很不方便. import java.util.Ar ...