Cython将Numpy数组转为自定义结构体
技术背景
前面我们写过几篇关于Cython的文章,例如Cython计算谐振势、Cython与C语言的结合、Cython调用CUDA Kernel函数。Cython有着非常Pythonic的编程范式,又具备着接近于C语言的性能,因此在很多对于性能有要求的Python软件中都会使用到Cython的性能优化。Cython的基本工作流程是,先将*.pyx文件转换为*.c的C语言代码,然后再使用gcc编译成一个*.so动态链接库文件,供Python或者其他语言的代码调用。
这里我们考虑一个较为特殊的场景:将Python端常用的Numpy数组,转换为C语言的结构体,然后执行相应的任务或者计算。
Cython结构体
在Cython中可以使用ctypedef struct来定义一个可以跟C语言通用的结构体,例如,我们可以定义一个原子坐标的结构体:
ctypedef struct CRD:
double x, y, z
这是一个三维空间中的原子坐标,在Python中就相当于一个shape为(3,)的数组。如果这是C++,那我们可以通过dynamic_cast等转换方式在数组和结构体之间进行转换。而C语言和Cython则是直接通过变量类型来进行转换,以下是一个完整的Cython示例:
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
在这个示例中,我们输入给函数trans()的是一个shape为(3,)的数组,然后在cdef中将这个原子坐标转换为结构体的形式,最后在Cython中打印输出该原子的y坐标。我们用Cython编译这个文件之后,可以在Python中调用:
In [1]: from trans import trans
In [2]: import numpy as np
In [3]: a = np.array([1,2,3], dtype=np.float64)
In [4]: trans(a)
2.0
Out[4]: 1
需要注意的是,这种转换方式并不安全,这里我们仅仅演示一下这种转换方式的使用方法。
多原子坐标结构体
其实从C语言的角度还蛮好理解的,我们通过单个结构体可以定义一个原子的空间坐标,那么用一个指针,就可以定义多个原子的空间坐标。这里我们定义多原子坐标的结构体为:
ctypedef struct PATH:
CRD crds
其实这里还是表示一个单原子的空间坐标,但是从一维指向变成了二维指向,此时我们可以通过PATH来构造一个多原子坐标的指针:
ctypedef struct CRD:
double x, y, z
ctypedef struct PATH:
CRD crds
cpdef int trans(double[:] crd, double[:, :] path):
cdef:
int atoms = path.shape[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].crds.x, path_s[i].crds.y, path_s[i].crds.z)
return 1
同样的,我们可以在Cython编译之后,通过Python来调用这个trans函数:
from trans import trans
import numpy as np
a = np.array([1,2,3], dtype=np.float64)
b = np.arange(12).reshape((4,3)).astype(np.float64)
print (trans(a, b))
输出结果为:
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
当然,这里还是需要提醒一下,这种指针转换的方式并不安全,需要谨慎使用。
总结概要
这篇文章介绍了在Cython中定义结构体,并在Python的Numpy数组/MemoryView和自定义结构体之间进行数据转换的方法。Cython有着非常Pythonic的编程范式,又具有接近于C语言的性能,对于Python开发者而言确实是一个很棒的工具。
版权声明
本文首发链接为:https://www.cnblogs.com/dechinphy/p/cython-struct.html
作者ID:DechinPhy
更多原著文章:https://www.cnblogs.com/dechinphy/
请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html
Cython将Numpy数组转为自定义结构体的更多相关文章
- Solidity的自定义结构体深入详解
一.结构体定义 结构体,Solidity中的自定义类型.我们可以使用Solidity的关键字struct来进行自定义.结构体内可以包含字符串,整型等基本数据类型,以及数组,映射,结构体等复杂类型.数组 ...
- typedef和自定义结构体类型
在自定义结构体类型时会用到typedef关键字.大家都知道typedef是取别名的意思,在C语言中跟它容易混淆的有const,#define等,其区别不在本篇文章讨论之列. /*定义单链表结点类型*/ ...
- qsettings 保存自定义结构体(QVariant与自定义结构体相互转化)
参考博文:QVariant与自定义数据类型转换的方法. 这里摘取其关键内容: 1.将自定义数据类型使用Q_DECLARE_METATYPE宏进行声明,便于编译器识别. 2.在插入对象的时候,声明QVa ...
- iOS自定义结构体
一.提要 通过以官方的CGSize为例,自定义Objective-C中的结构体,并使用. 二.CGSize 1.系统定义的CGSize结构体 struct CGSize { CGFloat width ...
- Qt--信号槽传递自定义结构体参数
自定义结构体参数的信号槽连接 (1) 对于自定义的结构体参数,信号槽无法识别参数,导致信号槽连接不起作用.所以需要注册结构体参数.在结构体中声明结束的地方加上结构体注册. struct DealDet ...
- 传入的结构体指针强制转为实例化结构体*v
struct val *v = (struct val *)arg;//传入的结构体指针强制转为实例化结构体*v struct val{ int num1; int num2; }; void *te ...
- matlab学习笔记12_2创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段
一起来学matlab-matlab学习笔记12 12_2 结构体 创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段 觉得有用的话 ...
- MATLAB 单元数组 cell 和结构体 struct 的用法以及区别
1. 前言 Matlab单元数组cell和结构体struct都可以将不同类型的相关数据集成到一个单一的变量中,使得大量的相关数据的处理变得非常简单而且方便.但是,需要注意的是,单元数组和结构体只是承载 ...
- 用set、map等存储自定义结构体时容器内部判别各元素是否相同的注意事项
STL作为通用模板极大地方便了C++使用者的编程,因为它可以存储任意数据类型的元素 如果我们想用set与map来存储自定义结构体时,如下 struct pp { double xx; double y ...
- gin中绑定表单数据至自定义结构体
package main import "github.com/gin-gonic/gin" type StructA struct { FieldA string `form:& ...
随机推荐
- 三月二十一日 安卓app个人作业开发
已经完成了 登录 和 注册逻辑 目前还有 提交打卡记录 的 开始时间 和 结束时间没有弄好 还有个人打卡记录的显示问题 并且我希望增加 修改个人密码 显示个人信息 退出登录 返回页面 删除打卡记录 的 ...
- mybatis Selective动态判断属性值新增或修改操作,batch批量操作
mybatis Selective动态判断属性值新增或修改操作,batch批量操作 mybatis insert foreach批量添加https://www.cnblogs.com/oktokeep ...
- jwt 加密和解密demo
jwt 加密和解密demo JSON Web Token(JWT)是一个非常轻巧的规范.这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息.导入jar <dependency&g ...
- 加速鸿蒙生态共建,蚂蚁mPaaS助力鸿蒙原生应用开发创新
6月21日-23日,2024华为开发者大会(HDC 2024)如期举行.在22日的[鸿蒙生态伙伴SDK]分论坛中,正式发布了[鸿蒙生态伙伴SDK市场],其中蚂蚁数科旗下移动开发平台mPaaS(以下简称 ...
- EF Core并发控制
EF Core并发控制 并发控制概念 并发控制:避免多个用户同时操作资源造成的并发冲突问题. 最好的解决方案:非数据库解决方案 数据库层面的两种策略:悲观.乐观 悲观锁 悲观并发控制一般采用行锁 ,表 ...
- SpringMVC原理(1)-文件上传请求
我们文件上传接口只需要在方法参数上写MultipartFile类,mvc就可以帮我们把上传的文件封装为这个类的对 象供我们非常方便的操作,那它是怎么做的呢?我们一起来看看 我们发的请求默认都是由Dis ...
- 基于OMAPL138+FPGA核心板——MCSDK开发入门(下)
本文测试板卡为创龙科技 SOM-TL138F 是一款基于 TI OMAP-L138(定点/浮点 DSP C674x + ARM9)+ 紫光同创 Logos/Xilinx Spartan-6 低功耗 F ...
- Vue Element-UI 按需引入提示Cannot find module 'babel-preset-es2015'
1.我的开发环境和操作步骤 1.1.使用VUE-CLI创建 2.x 脚手架 1.2.安装 npm i element-ui(参照官网) 1.3.安装 npm install babel-plugin ...
- Python数据分析方法与技巧
背景介绍 数据分析是数据科学领域的核心技能之一,它涉及到数据的收集.清洗.处理.分析和可视化. 数据分析是指通过收集.清洗.处理.分析和可视化数据来发现隐藏的模式.趋势和关系的过程. 数据分析是数据科 ...
- css浅谈Flex布局
1.打开Flex布局 .box{ display: flex; } 2.容器的属性 flex-direction flex-wrap flex-flow justify-content align-i ...