码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 使用Cython对Python进行提速优化


    因为常常使用Python,经常能感觉到和C,Java来说Python的速度太慢了。其中很大程度上是因为Python的类型是动态的,在解释类型方面花了较长时间。在调研过程中,发现给Python提速一个比较可行的方案是用Cython改写。

    Cython的原理,短板,和Cpython的比较,这篇知乎写的非常详细
    Python是不是被严重高估了? - 铁甲万能狗的回答 - 知乎
    https://www.zhihu.com/question/266096929/answer/2383570933

    首先是Cython的安装,pip install Cython
    然后还需要下载Visual Stdio编译C的软件工具,我在Windows上的下载链接如下
    https://visualstudio.microsoft.com/zh-hans/visual-cpp-build-tools/
    需要勾选两个工具,SDK和MSVC,缺少的话会提示找不到io.h文件

    C:\ProgramData\Anaconda3\include\pyconfig.h(59): fatal error C1083: 无法打开包括文件: “io.h”: No such file or directory
    error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\VC\\Tools\\MSVC\\14.37.32822\\bin\\HostX86\\x64\\cl.exe' failed with exit code 2
    
    • 1
    • 2

    在这里插入图片描述
    Cython官方文档:
    http://docs.cython.org/en/latest/src/tutorial/cython_tutorial.html#the-basics-of-cython
    中文版文档:
    https://www.kancloud.cn/apachecn/cython-doc-zh/1944774

    一些注意事项:
    https://www.codenong.com/dc7854776e4cf62deb76/

    现有一段测试性能的Python运行代码如下:

    def integrate_f(a, b, N):
        s = 0
        dx = (b-a) /N
        for i in range(N):
            s += 2.71828182846**(-(a+i*dx)**2)
        return s*dx
    
    def test_func():
        return integrate_f(1, 10, 100000000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Java版本

    package org.example;
    
    import java.lang.Math;
    
    public class Test {
        public static double integrate_f(double a, double b, int N) {
            double s = 0;
            double dx = (b-a)/N;
            for(int i =0; i <N; i++) {
                s += Math.pow(2.71828182846, -Math.pow(a+i*dx, 2));
            }
            return s*dx;
        }
        public static void main(String args[]) {
            long stime = System.nanoTime();
            double result = integrate_f(1,10, 100000000);
            long etime = System.nanoTime();
            System.out.println(result);
            System.out.printf("执行时长:%d 纳秒.", etime - stime );
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    则它的Cython改写版本为:
    (test_cython.pyx)

    cimport cython
    
    @cython.boundscheck(False)
    @cython.wraparound(False)
    
    cdef integrate_f(double a, double b, int N):
        cdef double s = 0
        cdef int i
        cdef double dx = (b-a) /N
        for i in range(N):
            s += 2.71828182846**(-(a+i*dx)**2)
        return s*dx
    
    def test_func():
        return integrate_f(1, 10, 100000000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    可以看到比较典型的是多了两个注解,还有就是变量前通过cdef申明了类型
    这样的Cython代码是不能直接在Pycharm里运行的,会提示invalid syntax。
    需要进行编译后才能作为C扩展模块才能加入Python运行,这部分可以参考之前提到的官方文档,需要写一个类似于打包的setup程序。这里暂时使用的是一个简单的版本,name就是打包编译后的模块名,ext_modules就是需要进行编译的文件
    (setup.pyx)

    from setuptools import setup
    from Cython.Build import cythonize
    
    setup(
        name='test_cython',
        ext_modules=cythonize("test_cython.pyx"),
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    之后再通过命令行在当前目录生成编译的C文件,之后会发现多了.c文件和.pyd文件

    python setup.pyx build_ext --inplace
    
    • 1

    再编写一个测试代码进行速度测试

    import test_cython
    import time
    start_time=time.time()
    result=check.test_func()
    print(result)
    print("用时:",time.time()-start_time)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试的结果如下,
    Python(3.9)用时24-26秒,Cython稳定在7.2秒,Java则是在7-10秒左右波动

    附:boundscheck和wraparound两个注解的作用
    https://zhuanlan.zhihu.com/p/657040768
    Python 的列表和数组通常会在访问元素时执行边界检查,以确保不会访问超出范围的元素。这会导致额外的性能开销。在 Cython 中,你可以使用数组的 “boundscheck” 属性和 “wraparound” 属性来控制边界检查

  • 相关阅读:
    【ARMv8/v9 GIC- 700 系列 2 -- GIC-700 上电控制寄存器 GICR_PWRR】
    DeepBI实现AI结合数据仓库做智能数据分析VS传统BI工具
    Python性能优化实录
    制作MySQL8绿色版&轻量版
    git如何将master分支合并到自己创建的分支
    Javascript【触屏事件、移动端常见特效、移动端常用开发插件、移动端常用开发框架】
    C#【疑难杂症篇】CS0012:必须添加对程序集“netstandard, Version=2.0.0.0, Culture=neutral...”的引用
    [面试直通版]操作系统之编程语言与运行原理(上)
    三菱FX5U系列PLC更改运动轴脉冲输出方向控制点的具体方法和步骤详解
    Springcloud服务调用Feign组件以及负载均衡
  • 原文地址:https://blog.csdn.net/qq_43199509/article/details/133860665
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号