Python 计算从1-N(N可以任何数)内的素数(算法优化、并行计算、多线程优化计算)
1、项目介绍
1.1研究背景
随着深度学习的高速发展,大数据技术的普及,尽管大数据处理越来越流行,但是少不了本地python处理大量数据的场景,这时候单线程处理效率较低。接下来紧接的会普及发展的想必就是硬件层面的配合,而GPU无疑是最重要的趋势。
1.2题目介绍
并行计算与GPU编程的大作业我选择的是质数运算方面的项目,通过Python实现查找N以内(N随意赋值)的质数个数的程序代码,因为质数统计运算一直是非常经典的问题,也通过这个问题深入优化算法代码去践行“简化计算,提高效率”的原则,进一步地去探究Python运算能力的多样性以及便利性。
2.项目优化过程
2.1 源代码
按照质数的定义,我编写的源代码如下:
通过引入时间模块定义并计算出程序的运行时间,以此与后面的优化做出对比,这里我简略地跳过了while循环的使用,直接使用效率较快的for循环,以此用了嵌套for循环实现基本的N以内质数查找运算。(这里统一给N赋值为200000)
运算情况如下:
可以看出基本的普通算法的效率并不高,共计用时162.300478s,这样的查找效率着实使人抓狂,下面我们对它进行优化。
2.2 优化1 - 数理的角度优化
我首先从数理的角度出发对代码进行优化,我们知道所有大于10的质数中,除了5以外,其余能被5整除的都是合数,加上这个排除条件之后效率有所提高,这样可以进一步简化代码,我们具体来看一下会有多少提升。
修改后的代码如下:
运行情况如下:
果然加入了限制条件,是有点起步,相对于源代码快了82s。
2.3 优化2 - 数理的角度优化
我们继续从数理层面入手去完善代码!因为偶数除了2都不是质数,去除偶数相当于去掉一半运算量,效率提高差不多一半,这样代码可以进一步被优化,修改后的代码如下:
运行情况如下:
这里面通过运行时间效率可以证实了我们的推断,共计用时80.789876s,效率相对于最初的源代码提升了一半还多!比优化1快了近2s。
2.4 优化3 - 引入列表
合数一定可以分解为几个质数的乘积;质数一定不能整除1和本身之外的整数;用列表实现,修改后的代码如下:
运行情况如下:
引入了列表的概念进行优化,通过在质数表中去除合数,留下质数,这个速度已经相对于前面有了质的飞跃,时间只用了13.643432s。所以Python里面的列表对于数据运算代码优化想比普通算法耗时都不是一个层次的。
2.5 优化4 - 加入列表后数理的角度优化
在引入列表后,我们继续结合数理方面的概念,因为合数一定可以分解为几个质数的乘积,质数一定不能整除1和本身之外的整数,我们构造一个列表,初值都是1,每发现一个素数,我们把所有它的倍数都置为False,直到发现下一个为1的数为素数。这就是书中提到的埃氏筛法。修改后的代码如下:
运行情况如下:
这里我们可以看出来,当数理层面的优化结合相应的Python列表,这样的话只需0.607469s,二十万内的质数统计计算已经是眨眨眼的功夫了。
2.6 优化5 - 数理的角度优化
进一步细化一下数理概念,看还有没有优化的空间,我的想法是例如像15、33、39等这样的数字被称为合数,合数是由两个质数相乘得出的所以只需要计算到一半就可以排除了,同理可知其他数字也适用这一条件;相当于去掉了一半的计算量,效率又一定程度上提高了。
修改后的代码如下:
运行情况如下:
当然,0.329552s,这已经十分细致了,在数理层面我也不想再深究下去,但是如果利用Python的一些密集计算的概念,看能不能帮助我的项目继续“加速”下去!
2.7 优化6 - 多线程优化
接下来,运用学习到的多线程基础对这两个新的判断质数代码进行测试,修改的代码如下:
运行结果如下:
好像单纯利用多线程计算起来是不是实现了“1”的突破,有迈步了一个台阶,但是代码仍需要改进,还需要更严谨一点,但基本肯定多线程的起步已经远远超越了最初的源代码,也一定意义上实现了代码优化的任务!但还需加深理解,进一步学习!
2.8 优化7 - jit技术优化
用pypy的jit技术实现
用时0.296242秒,比之前所有的优化都要优秀,已经十分厉害了
2.9 优化8 - Python cache缓存优化
使用Python cache 缓存,给需要缓存的函数加一个修饰器。 第一次调用时,正常执行,并缓存计算结果。 使用相同的参数,第二次调用时,不执行,直接加载计算结果
0.303995,速度比起原来的大幅提升
3.总结
通过三周的学习,我从课上学会了如何使用Numpy、Numba、多线程、集群和队列等一系列手段对代码进行优化,还懂得了用cProfile来查看代码的内存运行情况以及可视化输出,虽然这四周的内容很多,但通过不断的尝试和实验,我最终还是熟稔于心,也明白了高阶程序员究竟是如何优化算法的,对其原理也熟练的进行了掌握,总的来说受益匪浅。