ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python性能优化

2022-02-28 22:04:07  阅读:152  来源: 互联网

标签:解释器 需要 Python 性能 var 多线程 优化


Python性能优化

Python性能优化有两个方面:

  1. 绕过Python解释器
  2. 代码优化

绕过Python解释器

首先绕过Python解释器,大致有以下几个方法:

  1. 不使用默认的C解释器实现,使用Pypy,Jyhton等

  2. 编写C扩展,Numba等编译器

其他解释器实现

使用非默认的解释器实现,其实获得的好处并没有失去的多,因为使用非官方的解释器实现相当于意味着围绕着官方解释器所衍生出的各种 优化手段 生态!!都没用了。

同时非官方的解释器实现并不能支持最新的Python版本,甚至可能都不算是完整的Python。

现在可以看一下Jython还停留在2.7,然而当前Python正式发布的已经到了3.10

当然他会获得实现平台的类库,同时还没有GIL的限制。

编写C扩展

Python在执行C代码的时候是不受GIL的限制的,C语言的性能当然也不必说。

不过一个重要问题是编写C扩展是否有意义。因为就Web应用来说,大部分时候都在等待IO了,计算做的再快有什么用呢?尽快去等待IO吗?

当然本身目标就是科学计算,机器学习那么当然应该都需要使用C扩展了。

不过大多数时候C扩展都不需要我们来写,例如科学计算有Numpy,Pandas,深度学习有Tensorflow,Pytorch等。

使用Cython

当你实在无可奈何需要做自己编写C语言扩展,便可以使用Cython。以一种类似Python语言的方法来编写C扩展。不过缺点就是现在代码每到一个平台都需要编译了。

Numba

只需要加上一个小小的注解便能够启用jit,关闭gil(当然关闭后你不能够进行声明变量和调用函数等操作)

更多等待发现...(没怎么用过)

代码优化

讲过绕过解释器的优化手段,现在应该来讲一下代码层面的优化。

不过前面似乎遗漏了一个很重要的问题,就是你怎么是知道你应该优化哪一部分代码,一般应该先profile分析,然后再进行你的操作。

在代码层面上优化,除了做好本质工作写好代码以外,剩下其实很有限了,只能够从设计上面改进了。

这里提到一个很平常的改进,也就是将同步设计改进为异步设计。

异步

异步设计有很多方法,这里提及最常用的多进程,多线程,以及协程。

unix这一派推崇的是多进程设计比多线程设计更有伸缩性,然而多线程真的一无是处吗?

当然也不是这样,比如多线程相对于多进程之间通信就很容易,因为他们除了栈空间意外都是共享的,但是共享的内存空间似乎带来了更多问题,因为多个线程之间可能同时访问同一变量,然后该变量在他读取之后修改之前(指令)却改变了。

所以便需要对多线程程序进行协调竞争,也就是说竞争的部分势必是不能够同步的,所以多线程的处理能力势必要低于N*单个线程的处理能力,多线程的处理能够取决于程序中能够同步的部分,也就是说使更多的代码能够拆分并行,就可以得到越大的性能提升。

但是依赖手动拆分代码,管理并行,实在是麻烦并且不可靠。

这里实在不得不提函数式编程,以Java引入的Stream API举例。

public static void main(String... args) {
        var nums = collection(range(1, 101));
        var result = nums.stream().map(num -> Math.pow(num, 2)).toArray();  // 这里只需要将stream改为parallelStream便可改为并行操作
    // var result = nums.parallelStream().map(num -> Math.pow(num, 2)).toArray();
        for (var r : result) {
            System.out.println(r);
        }
    }

public static Collection<Integer> collection(Iterable<Integer> iterable) {
    var col = new LinkedList<Integer>();
    iterable.forEach(col::add);
    return col;
}

public static Iterable<Integer> range(int start, int end) {
    var iterator = new Iterator<Integer>() {
        private int nextNum = start;

        @Override
        public boolean hasNext() {
            return nextNum < end;
        }

        @Override
        public Integer next() {
            if (hasNext())
                return nextNum++;
            throw new NoSuchElementException();
        }
    };

    return () -> iterator;
}

由于并行的操作之间的结果互相不受影响,所以可以放心的并行,同时只需要更改一个函数便可以轻松的实现并行操作而不需要自己手动管理,杂务都交由语言去实现,岂不是十分方便。

有人说函数调用会带来额外的开销,然而这是否太不相信编译器&虚拟机的是实现者了呢?

是否偏离了主题。这里再来比较多线程和多进程.

多进程VS多线程

资源占用?多线程共享栈外的内存空间,较轻量;多进程空间独立,占用多(也不一定,如写时复制机制)

是否需要同步? 多线程需要; 多进程不需要

通信方式? 多线程不需要;多进程间通信方式大致分为两种IPC和套接字(这里不展开来讲)

协程

协程相比线程而言更为轻量,可以理解为可以暂停并在暂停位置重新开始的一个函数。

似乎并没有解释清楚协程是什么东西呢。本人水平有限只好读者自行搜索。

总结

似乎讲了一些Python性能提升的方法。然而却又并未说明具体应该怎么做。这是因为我觉得Python的性能优化实在是个伪命题。

我觉得当你觉得Python的性能需要优化的时候,有两种可能:

  1. 当前场景实际上应该用其他语言实现了
  2. 代码需要优化

Python或许是很慢,但是绝大多数的慢都不是由语言导致的,如果真的是由语言导致的慢,换个语言就好了

标签:解释器,需要,Python,性能,var,多线程,优化
来源: https://www.cnblogs.com/freesfu/p/15947788.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有