0
点赞
收藏
分享

微信扫一扫

Cython—语言基础


文章目录

  • ​​1. 数据类型声明​​
  • ​​1.1 Cython里定义一个C变量​​
  • ​​1.2 使用C语言中 struct,union或enum类型​​
  • ​​1.3 cython声明变量与初始化​​
  • ​​2. 类型转换、预编译、for循环​​
  • ​​3. python-C-cython 变量对应关系​​
  • ​​4. jupyter notebook 调试​​
  • ​​5 其它​​

在官方文档中说的很明白,所有的python代码都是合法的cython代码。以下变量声明不再赘叙。
开发环境:jupyter notebook
开启 Cython 运行环境:​​​%load_ext Cython​

1. 数据类型声明

1.1 Cython里定义一个C变量

在Cython里定义一个C变量和C语言类似,不同的地方就是在声明的最前面要加上cdef,另外,末尾不用加分号";

%load_ext Cython

cdef int an[10] # 声明数组,数组大小:10
cdef int n = 123 # 声明同时初始化
cdef int *pn = &n

print("%d ",pn[0])

cdef int i, j, k # 声明整型:i,j,k
cdef float f, *h # 声明浮点型f,指针h

注意:以Cython里不能用类似*ptr这样代码来对指针变量进行取值,而必须用ptr[0]这样的形式,如上面的例子中,printf("%d\n",*pn)是编译通不过的。(在C语言中,*ptr与ptr[0]都是指针访问方式)

1.2 使用C语言中 struct,union或enum类型

简单的声明

%%cython --a

cdef struct Grail:
int age
float volume

cdef union Food:
char *spam
float *eggs

cdef enum CheeseType:
cheddar, edam,
camembert

cdef enum CheeseState:
hard = 1
soft = 2
runny = 3

enum 枚举类型

显然Cython支持C语言的指针取址运算符。输出的是一个字典形式

cdef struct AB:
int a
int b

def StructTest():
cdef AB ab
ab.a = 1
ab.b = 2
return ab

>>> import test
>>> test.StructTest()
{'a': 1, 'b': 2}

=========================================================

cdef struct AB:
int a
int b

def StructTest():
cdef AB ab
cdef AB *pAB = &ab
pAB.a = 1
pAB.b = 2
return pAB[0]

>>> import test
>>> test.StructTest()
{'a': 1, 'b': 2}

关于结构体,一般用于结构体数组中,​

1.3 cython声明变量与初始化

Python类型​​list​​​,​​dict​​​,​​tuple​​ 的定义与初始化。使用结构类型声明变量。

cdef int x,y,z             # 整型
cdef char *s # 字节
cdef str name # 字符串
cdef float x = 0.1 # 单精度 浮点型
cdef double x = 0.1 # 双精度 浮点型
cdef list list_num = [] # list 定义并初始化列表
cdef dict abc_dict # dict 字典
cdef tuple tuple1 # 元组
cdef object objec1t # 任意对象

cdef list cast_list = <list?>a # 安全定义传入列表数据,a为传入的列表数据
cdef (double, int) bar # 它们可以编译为 C结构,并且可以用作Python元组的有效替代方案。


cdef uint64_t binN # binN:8字节整型 (拓展:uint8_t的最大数=256)
cdef np.ndarray[np.uint64_t, ndim=2] images_array1 # images_array:多维数组
cdef np.ndarray[np.float32_t, ndim=2] images_array2
cdef int[:, :] array_view = array_1 # 声明整数的memoryview
cdef int[:, ::1] result_view = result_1 # 声明整数的连续化memoryview
=============================================================================
ctypedef struct mycpx: # 定义结构类型
float real
float imag

ctypedef union uu: # 定义联合类型
int a
short b, c

cdef mycpx zz

====== 初始化:=======
cdef mycpx a = mycpx(3.1415, -1.0)
cdef mycpx b = mycpx(real=2.718, imag=1.618034)
cdef mycpx zz
zz.real = 3.1415
zz.imag = -1.0

cdef mycpx zz = {'real': 3.1415, 'imag': -1.0} # 这个是我们常用的方式

也可以使用拓展类型定义:https://cython.readthedocs.io/en/latest/src/userguide/extension_types.html#extension-types uint8_t / uint64_t 详情

2. 类型转换、预编译、for循环

在Cython里用​​<>​​替代了()来进行类型转换,如:

cdef float a= 123.456
cdef int b

b = <int>a

=====================

cdef int n

a = 'hello,world'
n = <int>a

注意的是:​​n =<int>a​​ 把一个Python字符串对象指针强制转换成了一个整形变量,这在封装回调函数时经常会用到强制将一个Python对象指针强制转换成C类型的情况。

更多请查看:​​https://cython.readthedocs.io/en/latest/​​

Cython预编译
Cython有一个DEF关键字创建宏,是一个编译时符号,类似于C语言的#define,DEF常数必须在编译时被解析,而且只能是简单类型,它们可以是浮点数、整数或者字符串,如下:

DEF E = 2.718281828459045
DEF PI = 3.141592653589793
def feynmans_jewel():
return E ** (1j * PI) + 1.0

for循环

cdef unsigned int i, n = len(a) - 1

for i in range(1, n):
a[i] = (a[i-1] + a[i] + a[i+1]) / 3.0



cdef int y, half_S=0, height=50, S = 2 # 步长不为1 时
for y from half_S <= y < height by S:

3. python-C-cython 变量对应关系

python

C/C++

cython

a=True

bool a=1/True

cdef/cpdef bint a=1

a=”2”

char* a=’2’

cdef/cpdef char* a=’2’

a=”2123bc”

char* a=”2123bc”

cdef/cpdef char* a=”2123bc”

a=2

int a=2

cdef/cpdef int a=2

a=2

short int a=2

cdef/cpdef short int a=2

a=2.0

double a=2.0

cdef/cpdef double a=2.0

a=2.0

float a=2.0

cdef/cpdef float a=2.0

a=np.zeros(10)

double[] a=np.zeros(10)

cdef/cpdef double[:] a=np.zeros(10)

a=np.zeros(10,10)

double[,] a=np.zeros(10,10)

cdef/cpdef double[:,:] a=np.zeros(10,10)

4. jupyter notebook 调试

%load_ext Cython
%%cython --annotate

cdef int a = 0
for i in range(10):
a += i
print(a)

各位可以试一下。​​​

Cython—语言基础_python

5 其它

  1. github网址:https://github.com/cython
  2. Cython官网使用文档:https://cython.readthedocs.io/en/latest/
  3. cython加速关于循环的运算
    关于循环加速:https://stackoverflow.com/questions/40451203/cython-parallel-loop-problems
  4. Cython的C++库:https://github.com/cython/cython/tree/master/Cython/Includes/libcpp
    Cython中C++泛型算法的使用:https://github.com/cython/cython/blob/master/Cython/Includes/libcpp/algorithm.pxd
    案例:https://github.com/cython/cython/commit/05059e2a9b89bf6738a7750b905057e5b1e3fe2e
  5. python3中关于cython的使用(将函数指针转换为可调用对象):https://python3-cookbook.readthedocs.io/zh_CN/latest/c15/p12_turning_function_pointer_into_callable.html
  6. 使用感想
    我们用cython,都是想用C的循环来替换python的循环,以此来加速。
    在使用cython中,我们所作最多的是数据类型的申明与转换。
    在定义cython的cdef函数中,我们希望with nogil的运行代码,所有整个函数不要有python对象,numpy对象以及对象的返回。
    若是使用已知数组,尽量申明并初始化C数组或者cython数组等轻量级数组。注意:C语言必须指明数组长度个数。也就是是个定量。

编译命令:​​python setup.py build_ext --inplace​

特别鸣谢:
​​​ https://cython.readthedocs.io/en/latest/src/userguide/numpy_tutorial.html​​​
https://hatboy.github.io/archives/page/4/
类:https://hatboy.github.io/2017/08/10/%E7%AC%AC%E4%BA%94%E7%AB%A0-Cython%E5%92%8C%E6%89%A9%E5%B1%95%E7%B1%BB%E5%9E%8B/



举报

相关推荐

0 条评论