首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

Cython与C函数的结合

编程知识
2024年07月25日 14:14

技术背景

在前面一篇博客中,我们介绍了使用Cython加速谐振势计算的方法。有了Cython对于计算过程更加灵活的配置(本质上是时间占用和空间占用的一种均衡),及其接近于C的性能,并且还最大程度上的保留了Python的编程语法特点,因此Cython确实是值得Python编程爱好者学习的一种加速手段。这里我们要介绍的是Cython与C语言相结合的一种方案,可以直接在pyx文件中加载C语言代码。

测试场景

我们测一个非常简单的场景————归约求和:

\[S=\sum_{i,j}A_{i,j} \]

当然了,像这种基本运算,在Numpy中已经优化的非常极致了。所以,这里我们并不是要展现Cython在性能上的优势,而是Cython对于C语言和Python语言两者的兼容性。首先我们用C语言实现一个归约求和的简单函数:

// array_sum.c
double reduce_sum(int arr_len, double* arr){
    double s=0.0;
    int i;
    for (i=0; i<arr_len; i++){
        s = s + *arr;
        arr++;
    }
    return s;
}

这里我们使用了一个指针数组,然后用for循环进行遍历计算。在Cython中,我们可以使用extern来直接加载C语言中的这个函数:

# test_pointer.pyx
import numpy as np
cimport numpy as np

cdef extern from "array_sum.c":
    double reduce_sum(int arr_len, double* arr)

cpdef rsum(int arr_len, np.ndarray[np.float64_t, ndim=2, mode="c"] arr):
    cdef:
        double* arr_ptr = <double *>arr.data
        double res = 0.0
    res = reduce_sum(arr_len, arr_ptr)
    return res

这里加载了C语言中的reduce_sum函数,然后以Cython中定义的rsum函数作为一个接口,将传入的numpy数组的内存地址作为指针传给C语言中写好的函数。然后需要对这个pyx文件进行编译构建:

$ cythonize -i test_pointer.pyx

编译完成后会在当前路径下生成*.c文件和*.so文件:

$ ll | grep test_pointer  
-rw-r--r-- 1 root root  374450 Jul 25 14:52 test_pointer.c
-rwxr-xr-x 1 root root  234848 Jul 25 14:52 test_pointer.cpython-37m-x86_64-linux-gnu.so*
-rw-r--r-- 1 root root     347 Jul 25 15:02 test_pointer.pyx

调用Cython函数

我们可以开启一个Ipython,或者直接在Python脚本文件中调用Cython函数:

In [1]: import numpy as np

In [2]: from test_pointer import rsum

In [3]: num=10000

In [4]: x=np.random.random((num,num))

In [5]: x.shape
Out[5]: (10000, 10000)

In [6]: %timeit s=np.sum(x)
38.3 ms ± 254 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [7]: %timeit rs=rsum(num*num,x)
51.7 ms ± 302 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [15]: np.sum(x)
Out[15]: 50003980.32921535

In [17]: rsum(num*num, x)
Out[17]: 50003980.32921728

经过测试,确实可以在Python中调用这个C语言实现的函数。当然,前面也提到过,Numpy对于这个简单的求和计算已经优化的非常好了,所以这里没有体现出性能上的优势,这里更多的是演示一个方法。

总结概要

这篇文章介绍了Python-Cython-C三种语言的简单耦合,以Cython为中间接口,实现Python数据传到C语言的后端执行相关计算。这就相当于可以在Python中调用C语言中的指针功能来进行跨维度的数组运算,至于性能依然存在优化空间,这里仅仅做一个简单的功能演示。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/cython-c.html

作者ID:DechinPhy

更多原著文章:https://www.cnblogs.com/dechinphy/

请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

From:https://www.cnblogs.com/dechinphy/p/18323048/cython-c
本文地址: http://www.shuzixingkong.net/article/420
0评论
提交 加载更多评论
其他文章 Nuxt.js 环境变量配置与使用
title: Nuxt.js 环境变量配置与使用 date: 2024/7/25 updated: 2024/7/25 author: cmdragon excerpt: 摘要:“该文探讨了Nuxt.js框架下环境变量配置的详细过程,涉及.env文件配置、运行时访问、安全性考量、在不同场景下的实践(
Nuxt.js 环境变量配置与使用 Nuxt.js 环境变量配置与使用
【最新最热】几何朗兰兹猜想终获破解!跨越30年研究,800余页证明论文问世,中国学者陈麟卓越贡献!
历经三十余载的潜心研究,九位杰出的数学家携手跨越了学术的崇山峻岭,通过五篇累计超过八百页的深邃论文,终于迎来了数学史上的一大盛事——几何朗兰兹猜想的壮丽证明! 这一里程碑式的成就,正是朗兰兹纲领几何化版本的璀璨绽放。朗兰兹纲领,作为现代数学研究的璀璨明珠,被誉为“数学的大统一理论”,它深刻地揭示了数
【最新最热】几何朗兰兹猜想终获破解!跨越30年研究,800余页证明论文问世,中国学者陈麟卓越贡献! 【最新最热】几何朗兰兹猜想终获破解!跨越30年研究,800余页证明论文问世,中国学者陈麟卓越贡献! 【最新最热】几何朗兰兹猜想终获破解!跨越30年研究,800余页证明论文问世,中国学者陈麟卓越贡献!
开源照片管理神器 PhotoPrism 安装和使用教程
如今我们每个人都积累了海量的照片和视频,做自媒体的 UP 主们积累的照片和视频数量可能更多。面对这么多的照片和视频,我们该如何管理呢? 之前我一直用谷歌相册,因为它有很多优势,比如无限空间,支持智能整理 (按时间线、地理位置、还支持人脸自动合并)。但去年 Google 开始对空间进行了限制,不再提供
开源照片管理神器 PhotoPrism 安装和使用教程 开源照片管理神器 PhotoPrism 安装和使用教程 开源照片管理神器 PhotoPrism 安装和使用教程
入门Vue+.NET 8 Web Api记录(一)
做自己感觉有意思的或者能解决自己需求的项目作为入门,我觉得是有帮助的,不会觉得那么无聊。 一个最简单的前后端分离项目应该是怎么样的? 我觉得就是前端有个按钮,点击向后端发送一个get请求,获取到数据后,将数据显示在前端上。 结合最近感兴趣的SemanticKernel,有了做这样的Demo学习的想法
入门Vue+.NET 8 Web Api记录(一) 入门Vue+.NET 8 Web Api记录(一) 入门Vue+.NET 8 Web Api记录(一)
整段 html实现其中的每一个 a 标签跨域下载操作 window.URL.createObjectURL(blob)
window.URL.createObjectURL(blob) a 标签下载问题,通常在 a 标签中加上download属性,就可完成对href属性链接文件的下载,但仅仅是限于同源文件,如果是非同源,download 属性就会失效 第一种情况,单独的一个标签实现下载,可以使用 span 标签+cl
Rust 中 *、&、mut、&mut、ref、ref mut 的用法和区别
*:解引用操作符,用于访问指针或引用指向的值的类型。 &:借用操作符,用于创建不可变引用的类型,允许只读访问。 mut:关键字,用于声明可变变量或参数的类型,允许其值被修改。 &mut:借用操作符,用于创建可变引用的类型,允许读写访问。 ref:模式匹配中的关键字,用于创建不可变引用的类型,避免所有
LeetCode513. 找树左下角的值
题目链接:https://leetcode.cn/problems/find-bottom-left-tree-value/description/ 题目叙述: 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: roo
LeetCode513. 找树左下角的值 LeetCode513. 找树左下角的值
三星app移植修复(app反编译修改)
工具: apktool ADT 命令: 反编译 java -jar apktool.jar d test.apk 重打包 java -jar apktool.jar b test 签名使用ADT smail语言粗略理解(其实对于修改来说, 大概熟悉就就ok) 类定义 .class public Lc
三星app移植修复(app反编译修改) 三星app移植修复(app反编译修改) 三星app移植修复(app反编译修改)