[Python] 提高Python运行速度(大方向)

3.2 提高Python运行速度(大方向)

现在我们已经知晓如何计算Python代码的运行时间了,接下来就是要想办法提高Python运行速度。一般要提高Python代码的运行速度遵循以下几点:

3.2.1 尝试通过多线程运行

多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。
在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。利用多线程技术可以显著提高某些特定的代码运行速度。
现在一般普通的计算机硬件都支持多线程技术,如果一个程序任务可以分解成多线程形式,那么运行速度将会得到极大的提升。
在以后的教程中将会介绍这种技术。

3.2.2 优化循环处理

循环处理是编写代码时经常遇到的情况,由于大循环一般会运行上成千上万次以上,于是在循环结构中,每一个小小的代码片段进行优化处理后都将会大大提高代码的运行速度。
后面将会详细介绍一些比较实用且常见的优化小技巧。

3.2.3 使用内置模块、函数和数据类型

Python内置的模块和函数是在安装Python时已经定义和安装好的,不仅导入方便,而且运行速度要比个人编写的代码快很多。
速度对比_内置模块

from math import factorial
from time import time
from timeit import timeit

def slow(n=100):
    if n == 0 or n == 1:
        return 1
    else:
        return n * slow(n - 1)

def fast():
factorial(100)

b1 = time()
timeit(slow, number=10_0000)
e1 = time()
print(f'函数 slow 运行 10 万次的时间为:{
      
      e1 - b1}')
b2 = time()
timeit(fast, number=10_0000)
e2 = time()
print(f'函数 fast 运行 10 万次的时间为:{
      
      e2 - b2}')

函数 slow 运行 10 万次的时间为:1.9230999946594238
函数 fast 运行 10 万次的时间为:0.1594223976135254

速度对比_内置函数

from mdTools import ftDecTimeIt  # 小编自己编写的一个计时装饰器

@ftDecTimeIt(100_0000)
def slow():
    new_list = []
    word_list = ["i", "am", "a", "bad", "boy"]
    for word in word_list:
        new_list.append(word.capitalize())

@ftDecTimeIt(100_0000)
def fast():
    word_list = ["i", "am", "a", "bad", "boy"]
new_list = list(map(str.capitalize, word_list))

slow()
fast()

函数 slow 运行 1000000 次的总耗时为:0.9304 秒
函数 fast 运行 1000000 次的总耗时为:0.8292 秒

速度对比_内置方法

from mdTools import ftDecTimeIt

@ftDecTimeIt(100_0000)
def slow():
    new_list = ""
    word_list = ["i", "am", "a", "bad", "boy"]
    for word in word_list:
        new_list += word.capitalize()

@ftDecTimeIt(100_0000)
def fast():
    word_list = ["i", "am", "a", "bad", "boy"]
new_list = ''.join(word_list)

slow()
fast()

函数 slow 运行 1000000 次的总耗时为:1.0097 秒
函数 fast 运行 1000000 次的总耗时为:0.2878 秒

3.2.4 使用较新的Python版本

Python版本是在不停迭代更新的,每次更新都会包含优化内容,这其中不但会优化内置函数、内置方法、更新模块,增加新的语法、模块等,还会优化运行速度,截止目前,最新的Python11某些方便运行速度相较于旧版本更是提升30%左右。

3.2.5 使用lru_cache缓存数据

当你可以把需要计算出来的数据保存下来的时候,千万不要重复的去计算它。如果你有一个经常需要使用的函数,而且返回的是可预测的结果,最好是能将其缓存到内存中。后续的函数调用如果是一样的,将立即返回结果。
Python本地库functools中的装饰器:@functools.lru_cache,它就能够缓存函数最近的调用,当缓存的值在特定时间内保持不变的时候这个非常好用,比如递归调用问题。
速度对比_缓存数据

from functools import lru_cache
from time import time
from timeit import timeit

def slow(n=10):
    if n == 1:
        return 1
    if n == 2:
        return 2
    else:
        return slow(n-2) + slow(n-1)

@lru_cache()
def fast(n=10):
    if n == 1:
        return 1
    if n == 2:
        return 2
    else:
        return slow(n - 2) + slow(n - 1)

b1 = time()
timeit(slow, number=10_0000)
e1 = time()
print(f'函数 slow 运行 10 万次的时间为:{
      
      e1 - b1}')
b2 = time()
timeit(fast, number=10_0000)
e2 = time()
print(f'函数 fast 运行 10 万次的时间为:{
      
      e2 - b2}')

函数 slow 运行 10 万次的时间为:1.344538927078247
函数 fast 运行 10 万次的时间为:0.007016420364379883

3.2.6 使用专门的第三方库

我们都知道,专业的人做专业的事,因为他们往往比一般人更了解,也更有经验,处理起来也更加得心应手。同样的,在Python编程中,如果有专门的库,那么处理起来也事半功倍,而且效率也高。
速度对比_numba库
numba中提供了jit装饰器,它可以将其装饰的函数JIT编译成机器码函数,并返回一个可在Python中调用机器码的包装对象。

from mdTools import ftDecTimeIt
from numba import jit

@ftDecTimeIt(1)
def slow(x=1, y=1_0000_0000):
    s = 0
    for i in range(x, y):
        s += i
return s

@ftDecTimeIt(1)
@jit
def fast(x=1, y=1_0000_0000):
    s = 0
    for i in range(x, y):
        s += i
return s

slow()
fast()

函数 slow 运行 1 次的总耗时为:5.2450 秒
函数 fast 运行 1 次的总耗时为:0.2750 秒

速度对比_numpy库
如果你要处理非常庞大的数据,并且希望能高效的对它们进行计算,那么numpy库是一个非常好的选择。numpy在一些关键代码上使用了C来代替,比原生Python更快处理数组,也能更高效的存储数据。
使用numpy也能更方便也更快的创建出大数据。让我们来看下面的例子:

from mdTools import ftDecTimeIt
import numpy as np

array = np.random.random(1_0000_0000)

@ftDecTimeIt(1)
def slow():
sum(array)

@ftDecTimeIt(1)
def fast():
np.sum(array)

slow()
fast()

函数 slow 运行 1 次的总耗时为:8.1115 秒
函数 fast 运行 1 次的总耗时为:0.1173 秒

猜你喜欢

转载自blog.csdn.net/crleep/article/details/131163229