CPython在CPU密集型应用下的并发

Python是解释型语言,根据不同的底层协议有很多种版本,最常见的是基于C的Cpython,默认情况下我们所说的Python就是Cpython。

Python的GIL(global interpreter lock):

  用于解决多线程之间的数据完整性和状态同步而存在,使得不管线程分布在多少个CPU上,解释器同一时刻只允许1个线程运行。

所以Python是thread_safe的。这样其实Python就几乎只能进行单线程编程了。

CPU密集型应用:(频繁计算)

从1开始累加,到1亿
1 def foo():
2     num = 0
3     for i in range(100000001):
4         num += i

现在进行一个任务,完成三次函数foo()的运行,计算总耗时,给出四种方案

1、单线程,1,2,3,4串行

2、多线程,1,2,3,4并行

3、单进程,1,2,3,4串行

4、多进程,1,2,3,4并行

通过实验验证在CPU秘籍应用下Python并发的最佳实现方式

测试电脑CPU:

intel_I7-4700(4核8线程)

方案1;

 1 if __name__ == "__main__":
 2     t_list = []
 3     start_time = time.time()
 4     for i in range(5):
 5         i = threading.Thread(target=foo)
 6         t_list.append(i)
 7         i.start()
 8         i.join()
 9     end_time = time.time()
10     print("Totally time:{}".format(end_time-start_time))

方案2;

 1 if __name__ == "__main__":
 2     t_list = []
 3     start_time = time.time()
 4     for i in range(5):
 5         i = threading.Thread(target=foo)
 6         t_list.append(i)
 7         i.start()
 8     for i in t_list:
 9         i.join()
10     end_time = time.time()
11     print("Totally time:{}".format(end_time-start_time))

方案3;

 1 if __name__ == "__main__":
 2     p_list = []
 3     start_time = time.time()
 4     for i in range(5):
 5         i = multiprocessing.Process(target=foo)
 6         p_list.append(i)
 7         i.start()
 8         i.join()
 9     end_time = time.time()
10     print("Totally time:{}".format(end_time-start_time))

方案4;

 1 if __name__ == "__main__":
 2     p_list = []
 3     start_time = time.time()
 4     for i in range(5):
 5         i = multiprocessing.Process(target=foo)
 6         p_list.append(i)
 7         i.start()
 8     for i in p_list:
 9         i.join()
10     end_time = time.time()
11     print("Totally time:{}".format(end_time-start_time))

方案与实践的对应:

方案1:——42.97582244873047

方案2:——44.63868308067322

方案3:——45.94909477233887

方案4:——15.7623131275177

总结:

这里multi_thread的效率竟然低于single_thread!所以,计算密集型应用,千万不要使用多线程,反而增加累赘!(GIL导致的)。

最能发挥性能的就是多进程!

				
时间: 2024-07-28 12:49:47

CPython在CPU密集型应用下的并发的相关文章

数据密集型 和 cpu密集型 event loop

Node.js在官网上是这样定义的:“一个搭建在Chrome JavaScript运行时上的平台,用于构建高速.可伸缩的网络程序.Node.js采用的事件驱动.非阻塞I/O模型使它既轻量又高效,是构建运行在分布式设备上的数据密集型实时程序的完美选择.”Web站点早已不仅限于内容的呈现,很多交互性和协作型环境也逐渐被搬到了网站上,而且这种需求还在不断地增长.这就是所谓的数据密集型实时(data-intensive real-time)应用程序,比如在线协作的白板,多人在线游戏等,这种web应用程序

Node.js异步处理CPU密集型任务

Node.js擅长数据密集型实时(data-intensive real-time)交互的应用场景.然而数据密集型实时应用程序并不是只有I/O密集型任务,当碰到CPU密集型任务时,比如要对数据加解密(node.bcrypt.js),数据压缩和解压(node-tar),或者要根据用户的身份对图片做些个性化处理,在这些场景下,主线程致力于做复杂的CPU计算,IO请求队列中的任务就被阻塞. Node.js主线程的event loop在处理所有的任务/事件时,都是沿着事件队列顺序执行的,所以在其中任何一

转:Node.js异步处理CPU密集型任务的新思路

原文来自于:http://www.infoq.com/cn/articles/new-idea-of-nodejs-asynchronous-processing-tasks?utm_source=infoq&utm_medium=popular_links_homepage Node.js擅长数据密集型实时(data-intensive real-time)交互的应用场景.然而数据密集型实时应用程序并不是只有I/O密集型任务,当碰到CPU密集型任务时,比如要对数据加解密(node.bcrypt

juc下的并发工具类和线程池

工具类 CountDownLatch 利用它可以实现类似计数器的功能.比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了. package com.yjc.juc; import java.util.concurrent.CountDownLatch; public class CountDownLatchDemo { public static void main(String[] args) throws Interrupt

数据库 IO密集型 与 CPU密集型

1.IO密集型: 数据库仅提供建立的查询插入等操作,复杂的业务逻辑依赖与程序的实现,需要程序与数据库的频繁交互 2.CPU密集型: 一些复杂的逻辑计算可以在数据库中进行处理,可以依赖与数据库端的存储过程,触发器等功能,减少了程序代码与数据库的交互,减轻访问数据 库带来的IO压力,对于装备有高速磁盘阵列的服务器来说,可以实现CPU密集型 对于目前,高并发,数据量大的动态网站来说,数据库应该为IO密集型. http://blog.chinaunix.net/uid-116213-id-3086203

Linux下高并发socket最大连接数所受的各种限制(详解)

1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄).可使用ulimit命令查看系统允许当前用户进程打开的文件数限制: [[email protected] ~]$ ulimit -n1024 这表示当前用户的每个进程最多允许同时打开1024个文件,这1024个文件中

Linux下高并发socket链接数测试

一.如何增大service进程的max open files ulimit -n 只能改小max open files,不能改大.需要按照以下步骤: 修改/etc/security/limits.conf文件,将"soft nofile 655360"和"hard nofile 655360"这两行的655360改成期望的值 退出,重新ssh该机器(否则无效) 修改对service的启动脚本,增加"ulimit -n 950000",其中9500

MySQL学习总结-演示不同隔离级别下的并发问题

演示不同隔离级别下的并发问题 1.当把事务的隔离级别设置为read uncommitted,会引发脏读.不可重复读和虚读A窗口set transaction isolation level read uncommitted;start transaction;select * from bank;----发现a账户是1000元,转到b窗口select * from bank; B窗口start transaction;update bank set money=money+100 where n

2017/9/5的学习内容___通过yield实现在单线程的情况下实现并发运算的效果

之前的学习内容,由于没有申请开通博客,就没有分享,今天想分享一下学习内容:通过yield实现在单线程的情况下实现并发运算的效果 采用的是经典的生产消费者模型 定义了两个函数 Consumer与Producer 关于生成器标志yield : 如果用__next__访问,只是单纯调用yield :如果是send访问,不仅可以访问yield,也可以给yield赋值! 需求:一个人造包子:两个人吃包子: 代码如下: 1 # -*- coding:utf-8 -*- 2 # Author : 何子辰 3