Cython 系列,完结撒花(不是完结的完结)

简介: Cython 系列,完结撒花(不是完结的完结)

不知不觉几个月又过去了,关于 Cython 系列暂时就先告一段落,不知道我的文章有没有让你有所收获呢,要是有的话就太好了。

下面回顾一下我们都学习了哪些内容:

1)了解了 Cython 是什么?以及它存在的意义,为什么 Cython 会出现。

2)通过对比 Cython, C, C 扩展以及纯 Python 之间的性能差异,了解了 Cython 如何对 Python 进行加速,以及应该在何时使用 Cython。

3)了解了编译 Cython 代码的几种方式,因为 Cython 代码是要经过编译的,编译方式可以是手动编译、也可以是自动编译。

4)通过对比静态语言和动态语言、以及编译执行和解释执行之间的差异,进一步理解了 Cython 的定位以及作用。

5)然后就是 Cython 的基础语法,包括变量的静态声明、静态函数、静态类、类型转换、异常处理、魔法方法等等。

6)Cython 同时理解 C 和 Python,在 Cython 里面可以直接声明 C 一级的结构,比如数组、指针、结构体、共同体、枚举等等。此外一些 C 级结构和 Python 结构是可以相互转换的,但是要注意内存管理相关的问题。

7)如果代码量很大、功能很复杂的话,就需要多文件编程了,所以我们还学习了 Cython 的工程化,如何将多个文件组织起来。核心就在于定义一个和 .pyx 文件具有相同基名称的 .pxd 文件,将那些想要提供给别的文件使用的 C 级结构都写在里面,然后通过 cimport 导入。

8)然后是 Cython 最核心的特性,就是包装外部的 C 代码。假设你有现成的 C 源文件,那么 Cython 可以直接对其进行包装,外界调用 Python 函数,在 Python 函数内部调用 C 函数。这样调用者就不清楚,这个功能是我们自己实现的,还是已经存在的。

9)Cython 不光可以封装 C 源文件,还可以封装动态库和静态库,而 C 已经存在大半个世纪了,拥有非常多的库。并且库的话,也可以使用 Go, Rust 编写,然后封装给 Cython 使用。

10)Python 在科学计算领域大放异彩的原因就在于,它能和 C 进行非常好的交互,并且数据之间可以共享内存,而共享内存的实现得益于缓冲区协议。Python 底层有一个结构体叫 Py_buffer,它内部有一个 buf 字段指向了缓冲区,所有实现缓冲区协议的对象一律通过 Py_buffer 来操作缓冲区,这样就屏蔽了不同对象之间的类型差异。

数据拷贝的时候,可以只拷贝 Py_buffer 结构体,但是结构体内部的 buf 字段指向的缓冲区不拷贝,从而实现共享内存。而我们也学习了缓冲区协议的具体细节,以及不同对象之间是如何共享缓冲区的,并且还通过 Cython 和 Python/C API 手动实现了缓冲区协议。

11)Python 有一个内置类型 memoryview,它存在的目的是在 Python 级别表示 C 级的缓冲区。但 Cython 提供了一个 typed memoryview,它是专门为 C 风格的访问而设计的,并且功能更加强大。

12)Numpy 数组是使用最广泛的数组,不仅具有出色的性能,还提供了大量丰富的 API 供我们使用。而 typed memoryview 和 Numpy 数组之间也是可以共享内存的,而共享内存的方式我们提供了三种。

13)最后是并行计算,上面不管再怎么优化,都是基于单线程的。这样性能的提升幅度有限,而合理地利用硬件资源是最有效的办法。所以我们介绍了 GIL 到底是个什么东西?它为什么会存在,存在的意义是什么?如何通过 Cython 将 GIL 释放掉,真正实现并行?以及 Cython 释放 GIL 的原理是什么,我们应该在何时释放 GIL,释放 GIL 又有哪些注意事项?

14)虽然 Cython 可以释放 GIL,但对于 for 循环来说其实是不够方便的。所以我们又学习了 prange,它专门用于 for 循环的并行。只需要将 range 换成 prange,即可接入所有可用的 CPU 核心,非常方便,但这个特性并不是所有的 C 编译器都支持。

总的来说,Cython 还是非常值得我们去学习的,通过学习 Cython,你也能更加深刻地了解 Python。

然后再看一下文章标题,上面写着"不是完结的完结",这是什么意思呢?因为 Cython 不仅可以包装 C,还可以包装 C++,而我不懂 C++。所以这个系列暂时结束,我去学习一段时间 C++ 之后,再把内容补上去。

可能有人觉得我这么做有点奇怪,为了介绍 Cython 还专门去学习 C++,其实原因是有一个读者问过我几次关于 Cython 包装 C++ 的问题。后面我跟他说,我去学一段时间 C++,然后再来帮你解决,因此我要实现约定。

所以该系列虽然完结了,但又没有完结,敬请期待后续内容。

相关文章
|
2月前
|
编译器 C++
C++之类与对象(完结撒花篇)(上)
C++之类与对象(完结撒花篇)(上)
36 0
|
2月前
|
编译器 C++ 数据库管理
C++之类与对象(完结撒花篇)(下)
C++之类与对象(完结撒花篇)(下)
34 0
|
7月前
|
前端开发 API C++
完结撒花啦
完结撒花啦
|
7月前
|
算法 程序员 开发工具
代码随想录 学习记录(1)
代码随想录 学习记录(1)
175 0
|
7月前
|
存储 开发工具 文件存储
Python的核心知识点整理大全66(已完结撒花)
Python的核心知识点整理大全66(已完结撒花)
116 4
|
数据可视化 项目管理 C++
Axure快速入门(完结) -终章总结
Axure快速入门(完结) -终章总结
58 0
|
缓存 算法 安全
程序员写代码为什么要阅读源码?
阅读一篇技术文章,畅聊一个技术话题。本期文章推荐的是《Node 中的 AsyncLocalStorage 的前世今生和未来》,一起来聊聊开发者阅读源码的这件事。阅读源码的过程实质上是对软件构建技术和架构深度的一种持续学习和理解。阅读源码可以揭示代码的内在逻辑,可以对技术深度的理解,也能提高对技术的理解程度。然而,仅仅阅读源码并不能代替实践操作,因为通过实践,可以更加全面的理解代码的深度和进展。
153 1
|
计算机视觉
OpenCV图像处理汇总(已完结)
OpenCV图像处理汇总(已完结)
505 0
|
NoSQL MongoDB Python
不看官方文档,这个问题你可能会束手无策
不看官方文档,这个问题你可能会束手无策
109 0

相关实验场景

更多