首页 > 编程语言 >加速Python的几种方法

加速Python的几种方法

时间:2024-04-02 23:12:38浏览次数:21  
标签:cython return Python 几种 fib python time dll 加速

加速Python的几种方法

前言

注意以下内容均为本人主观操作感受,运行环境为Win10+python3.7_32位,仅供本人日后查阅

众所周知,python是一门优美而简洁的编程语言,其最大的不足在于运行速度过于感人,而C语言作为最接近底层的高级语言,速度快是他最大的优势。python被誉为胶水语言,应该有办法和C语言胶和起来,我查阅资料发现python调用C语言最普遍的方式大概有三种:

  1. 将C语言的函数编译成dll动态链接库,然后通过python的ctypes模块对dll进行调用。
  2. 借由cython先将python代码编译成C语言代码,然后再讲C代码编译成.pyd文件直接在python中导入进行调用,cython本身有一定语法,不过不会一般也不太影响使用。
  3. 使用Swig可以将C代码直接封装成python代码,过程略为复杂,优点是可以为多种语言提供接口。

以上几种方法的原理和过程下图很好的解释了:

图片来自网络

本文以斐波拉契函数为例,探究python和C的合璧之法。

import time

def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)
    
start=time.time()
print("计算结果:%d" % fib(40))
end=time.time()
print('python time cost:',end-start)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int fib(int n)
{
	if (n == 0)
	{
		return 0;
	}
	else if (n == 1)
	{
		return 1;
	}
	else
	{
		return fib(n - 1) + fib(n - 2);
	}
}

int main()
{
	clock_t start, end;
	start = clock();
	printf("计算结果:%d\n", fib(40));
	end = clock();
	printf("C cost time:%f", (double)(end - start) / CLOCKS_PER_SEC);
	system("pause");
	return 0;
}

通过运行上面的代码可以得到运行时间:

  • 纯python:
    计算结果:102334155
    python time cost: 87.49325394630432
  • 纯C语言:
    计算结果:102334155
    C cost time:0.863000

差不多差了两个数量级吧。。。

1. 通过ctypes调用dll

首先得先生成一个dll,你可以在ide里新建一个dll工程进行创建。更简单的做法是利用下面的gcc命令直接在cmd里进行编译,但前提是你已经装了Mingw或者并Mingw-w64且设置了环境变量,其中有个比较坑的地方就是你编译出来的dll位数要和你的python位数要匹配,像我笔记本上装的是Mingw-w64,而pyhton是32位的,32的python无法调用64位的dll,而这位Mingw-w64虽说同时支持64位和32位,但是前提是安装时勾选的是sjlj而不是seh,seh不支持32位!

用于编译dll的c语言代码只需给出函数就好了:

int fib(int n)
{
	if(n == 0)
	{
		return 0;
	}
	else if(n == 1)
	{
		return 1;
	}
	else
	{
		return fib(n-1) + fib(n-2);
	}
}

下面是cmd中将C原文件编译成dll的命令:

gcc -fPIC -shared name.c -o name.dll

如果是sjlj的Mingw-w64加上-m32可以编译出32位dll:

gcc -fPIC -shared -m32 name.c -o name.dll

然后在python中导入ctypes模块就可以调用dll了:

import ctypes
import time

start=time.time()
fibpy=ctypes.CDLL('fibpy.dll')
print("计算结果:%d" % fibpy.fib(40))
end=time.time()
print('dll time cost:',end-start)

ctype调用dll运行时间:

  • 计算结果:102334155
  • dll time cost: 0.9999649524688721

因为只有一个函数,还调用的是C语言的,所以速度和纯C差不多。

2. cython

先给出官方的一个教程:官方教程

使用cython首先要安装cython模块:

pip install Cython

然后你需要安装Mingw进行一番配置或者直接下载安装Visual Studio安装C++环境,因为我用的是Mingw-win64,所以自然就先抛弃后面那个巨无霸选用前者,一番尝试后发现还是Visual Studio真香。当然可能单纯的是因为Mingw-win64不支持而已,用Mingw的话应该是可以的(但愿)。

安装完环境后就可以直接把之前的纯python代码中的函数部分进行cython转换,不过需要现将其后缀名改为.pyx,然后需要再创建一个setup.py文件,其中写入代码:

from distutils.core import setup
from Cython.Build import cythonize
setup(
    ext_modules = cythonize("fibcy.pyx")
)

然后还是cmd中执行:

python setup.py build_ext --inplace

这时应该会生成一个.pyd文件,这个文件本质和前面的dll应该差不多,可以通过import在python中使用:

import time
import fibcy
    
start=time.time()
print("计算结果:%d" % fibcy.fib(40))
end=time.time()
print('cython time cost:',end-start)

运行结果:

  • 计算结果:102334155
  • cython time cost: 15.108871698379517

可以看到即使是在没有使用任何cython语法的情况下,cython的加速能力也是令人惊叹的,运行速度提高了一个数量级左右!

3. Swig

同样先给出一个教程参考:Swig教程

其实swig的原理和前面也差不多,但是过程更为复杂。首先当然要安装swig,下载解压后同样添加到系统环境变量。

然后要准备的有C语言源文件,一个.i文件,还有一个setup.py文件。

#include <stdio.h>

int fib(int n)
{
	if (n == 0)
	{
		return 0;
	}
	else if (n == 1)
	{
		return 1;
	}
	else
	{
		return fib(n - 1) + fib(n - 2);
	}
}
%module fib
%{
#include <stdio.h>
%}
extern int fib(int n);
from setuptools import setup,Extension
setup(  name='fib',
	version='1.0',
	ext_modules=[Extension('_fib', ['fib.c', 'fib.i'])]
	)

最后在命令行运行setup.py:

python setup.py build_ext --inplace

最后生成的文件中应该有一个python文件,可以直接进行调用,除此之外我发现还有一个.pyd文件,果然和前面的方法都差不多呢,导入运行方法也和之前相同。

运行结果:

  • 计算结果:102334155
  • swig time cost: 0.6825790405273438

居然比纯C语言还要快!大概是因为去掉了计时模块的缘故,可能python的计时模块比C的要快?结果还是很匪夷所思呢?

4. namba的@jit加速

namba加速不同于以上3种方法,上面3种方法多多少少会和C语言扯上点关系。numba则是直接在python源文件里通过加上一些代码直接运行并获得加速效果,本质原理也是使数据向静态靠拢,但是实现过程与上面3种方法相比更简单,可以参考官方入门教程

下面具体看一下实现过程:
首先肯定是要先安装numba包

pip install numba

然后只需在Python代码中导入numba并用jit修饰相应的函

import time
from numba import jit

@jit(nopython=True)
def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)
    
start=time.time()
print("计算结果:%d" % fib(40))
end=time.time()
print('numba@jit time cost:',end-start)

运行结果:

  • 计算结果:102334155
  • numba@jit time cost: 1.2832109928131104

加速效果可以说是相当惊人的,比cython要快,而且操作也特别简单,不用导来导去,和numpy相配合使用可以使运行速度得到极大的提升。

总结

方案 运行时间
纯Python 87.49325394630432
纯C语言 0.863000
ctypes 0.9999649524688721
cython 15.108871698379517
swig 0.6825790405273438
numba 1.2832109928131104

python结合c语言的三种方法中ctypes方法最简单,将C代码直接编译成dll即可使用,cython可以为现有的python代码加速,swig可以直接将C转换为python,就是有点麻烦,但速度是最快的。numba的jit加速比上面三种方法都要更简单,只需在python源码里加几句就行了,而且速度也很可观。

标签:cython,return,Python,几种,fib,python,time,dll,加速
From: https://www.cnblogs.com/kizx/p/18111702

相关文章

  • Python套索回归lasso、SCAD、LARS分析棒球运动员薪水3个实例合集|附数据代码
    全文链接:https://tecdat.cn/?p=35585原文出处:拓端数据部落公众号在数据科学和机器学习领域,回归分析是一种强大的工具,用于探索变量之间的关系并预测未来的结果。其中,套索回归(LassoRegression)是一种线性回归方法,特别适用于解决高维数据和过拟合问题。它通过引入正则化项来限制模......
  • Python命名规范
    ★类属性命名规范类属性通常采用大写字母、下划线分隔的方式命名,遵循以下规范:1.如果类属性是常量,通常使用全大写的字母表示,多个单词之间用下划线分隔,例如:MAX_SIZE。2.如果类属性表示一个布尔值或状态,通常使用is或has开头,例如:is_running、has_finished。3.如果类属性表示......
  • 几种常见的路径规划算法
    几种常见的路径规划算法路径规划是机器人、自动驾驶车辆、无人机等领域中的关键技术之一,它涉及到如何为移动实体找到从起点到终点的最优或可行路径。随着技术的不断发展,路径规划算法也在不断进步和优化。下面将介绍几种常见的路径规划算法。1.Dijkstra算法Dijkstra算法是一......
  • 几种嵌入式中常见的滤波算法
    在嵌入式系统开发中,滤波算法是不可或缺的一部分,用于从带有噪声的数据中提取有用信息,提高数据质量,并减少错误决策的可能性。下面将介绍几种在嵌入式系统中常见的滤波算法。1.移动平均滤波(MovingAverageFilter)移动平均滤波是一种简单的滤波算法,通过计算一定窗口内数据点的平......
  • 嵌入式工程师常用的几种算法
    嵌入式工程师常用的几种算法嵌入式系统在现代电子设备中无处不在,从简单的家电到复杂的工业控制系统,都离不开嵌入式技术的支持。作为嵌入式工程师,掌握一些常用的算法对于提高系统性能和优化资源利用至关重要。本文将介绍几种嵌入式工程师常用的算法。1.排序算法排序算法在嵌......
  • 10秒钟用python接入讯飞星火API(保姆级)
    正文:        科大讯飞是中国领先的人工智能公众公司,其讯飞星火API为开发者提供了丰富的接口和服务,以支持各种语音和语言技术的应用。步骤一:注册账号并创建应用首先,您需要访问科大讯飞开放平台官网,注册一个账号。注册完成后,登录账号,在控制台中创建一个新应用。创建......
  • C#数据去重的5种方式,你知道几种?
    前言今天我们一起来讨论一下关于C#数据去重的的5种方式,每种方法都有其特点和适用场景,我们根据具体需求选择最合适的方式。当然欢迎你在评论区留下你觉得更好的C#数据去重的方式。使用HashSet去重C#中的HashSet是一种集合类型,它确保其中的元素是唯一的,不允许重复值的存在。当......
  • Python控制安卓模拟器——uiautomator2模块
    Python控制安卓模拟器——uiautomator2模块目录Python控制安卓模拟器——uiautomator2模块介绍【1】安装python【2】安装adb1]下载[adb:[2]配置环境变量【3】安装uiautomator2【4】连接设备(安卓模拟器)【5】u2指令控制设备常用指令【6】安装weditor【7】元素操作元......
  • 就业班 第二阶段(python) 2401--4.2 day1 python初识
    一、Python语言介绍1、Python发展历史2、Python简介3、Python特点4、Python的能力二、Linux编译安装Python31、源码安装1、安装依赖软件包2、下载3、解压安装4、配置共享库文件5、测试python36、测试pip32、配置使用国内源安装第三方模块1、创建配置文件补充内容四、......
  • python变量和简单的数据类型[第 2 章(上)]
    2.1运行解释文件扩展名:结尾的.py用于指出文件内容是Python代码Python解释器:读取整个文件,确定其中每一行的含义并执行例如,当解释器看到print,就会将括号中的内容打印到屏幕上。语法高亮:用不同的颜色,区分出程序代码中的不同部分 2.2变量修改我们在上一章中写的代......