Technical background
We've written a few articles about Cython before, such asCython calculates the resonance potential、Cython with C、Cython calls to CUDA Kernel functionsCython has a very Pythonic programming paradigm with performance close to that of C, so it is used for performance optimization in many performance-critical Python software.The basic workflow of Cython is to start by taking the*.pyx
The file is converted to*.c
C code, which is then compiled using gcc into a*.so
Dynamic link library files for Python or other language code to call.
Here we consider a more specific scenario: take a Numpy array, which is commonly used on the Python side, convert it to a C structure, and then perform the corresponding task or calculation.
Cython Structures
In Cython you can use thectypedef struct
to define a structure that can be generalized with C. For example, we can define a structure for atomic coordinates:
ctypedef struct CRD:
double x, y, z
This is an atomic coordinate in three-dimensional space, which in Python is equivalent to a shape of(3,)
of the array. If this were C++, then we could convert between arrays and structures through conversions such as dynamic_cast. C and Cython on the other hand convert directly by variable type, here is a complete Cython example:
ctypedef struct CRD:
double x, y, z
cpdef int trans(double[:] crd):
cdef:
CRD* crd_s = <CRD*>&crd[0]
print (crd_s.y)
return 1
In this example, we input to the functiontrans()
is a shape of(3,)
array in thecdef
The coordinates of this atom are converted to a structure in Cython, and finally the y-coordinate of the atom is printed out in Cython. After we compile this file in Cython, we can call it in Python:
In [1]: from trans import trans
In [2]: import numpy as np
In [3]: a = ([1,2,3], dtype=np.float64)
In [4]: trans(a)
2.0
Out[4]: 1
It is important to note thatThis conversion is not safe.
Here we just demonstrate the use of this conversion method.
polyatomic coordinate structure
In fact, from the perspective of the C language is quite understandable, we can define the spatial coordinates of an atom through a single structure, then with a pointer, you can define the spatial coordinates of multiple atoms. Here we define the structure for multiple atom coordinates as:
ctypedef struct PATH:
CRD crds
In fact, here still represents a single-atom spatial coordinates, but from one-dimensional pointing to two-dimensional pointing, at this time we can use PATH to construct a multi-atom coordinates of the pointer:
ctypedef struct CRD:
double x, y, z
ctypedef struct PATH:
CRD crds
cpdef int trans(double[:] crd, double[:, :] path):
cdef:
int atoms = [0]
int i
CRD* crd_s = <CRD*>&crd[0]
PATH* path_s = <PATH*>&path[0][0]
print (crd_s.y)
for i in range(atoms):
print (path_s[i]., path_s[i]., path_s[i].)
return 1
Similarly, we can call this trans function via Python after Cython compilation:
from trans import trans
import numpy as np
a = ([1,2,3], dtype=np.float64)
b = (12).reshape((4,3)).astype(np.float64)
print (trans(a, b))
The output result is:
2.0
0.0 1.0 2.0
3.0 4.0 5.0
6.0 7.0 8.0
9.0 10.0 11.0
1
Of course, a word of caution is still needed here.This type of pointer conversion is not safe
, needs to be used with caution.
Summary outline
This article describes a way to define structures in Cython and convert data between Python's Numpy arrays/MemoryView and custom structures.Cython has a very Pythonic programming paradigm with performance close to that of C, and is really a great tool for Python developers.
copyright statement
This article was first linked to:/dechinphy/p/
Author ID: DechinPhy
More original articles:/dechinphy/
Buy the blogger coffee:/dechinphy/gallery/image/