C桑(Cython)从入门到入土(2): np数组操作对比

2024-01-12 21:36

本文主要是介绍C桑(Cython)从入门到入土(2): np数组操作对比,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

C桑(Cython)从入门到入土

2. np数组操作对比

Node sc518 Copy has image data of type unsigned long long

实际上, 👆🏻这个错误是我探索Cython的缘起…

code1:

Form:

更现代的方法是使用内存视图而不是指针:

cdef np.uint32_t[:,:,::1] mv_buff = np.ascontiguousarray(im, dtype = np.uint32)

[:,;,::1] 语法告诉 Cython 内存视图在内存中是 3D 和 C 连续的。将类型定义为内存视图而不是 numpy 数组的优点是
它可以接受定义缓冲区接口的任何类型,例如内置数组模块或来自 PIL 成像库的对象。
Memoryviews 可以在不持有 GIL 的情况下传递,这对于并行代码很有用
要从内存视图获取指针,请获取第一个元素的地址:

cdef np.uint32_t* im_buff = &mv_buff[0,0,0]

这比 <np.uint32_t*>mv_buff.data 更好,因为它避免了强制转换,并且强制转换通常可以隐藏错误。

👇的内容是小度在这里插入图片描述的回答:

这段代码涉及到Cython中的内存视图和numpy数组的使用。Cython是一种用来编写C扩展的Python语言,它可以提高Python代码的执行效率。让我们逐步解释这段代码:

  1. cdef np.uint32_t[:,:,::1] mv_buff = np.ascontiguousarray(im, dtype = np.uint32):

    • cdef np.uint32_t[:,:,::1] mv_buff: 这定义了一个3D的内存视图mv_buff,其数据类型为np.uint32_t(无符号32位整数)。:表示这个维度是开放的,也就是说它的大小可以根据源数组im的大小来自动确定。
    • np.ascontiguousarray(im, dtype = np.uint32): 这个函数将输入的numpy数组im转换为连续的内存布局,并指定数据类型为np.uint32_t
  2. [:,;,::1] 语法告诉 Cython 内存视图在内存中是 3D 和 C 连续的。:

    • [:,;,::1]是Cython中的内存视图语法,它定义了数组的维度和连续性。这里它表示一个3D的数组,并且在内存中是C风格连续的(即行优先)。
  3. 将类型定义为内存视图而不是 numpy 数组的优点是:

    • 可以接受定义缓冲区接口的任何类型,例如内置数组模块或来自 PIL 成像库的对象。
    • Memoryviews 可以在不持有 GIL 的情况下传递,这对于并行代码很有用。
  4. 要从内存视图获取指针,请获取第一个元素的地址:

    • cdef np.uint32_t* im_buff = &mv_buff[0,0,0]: 这行代码获取了内存视图mv_buff中第一个元素的地址,并将其赋给指针im_buff。这意味着现在可以通过这个指针直接访问和修改mv_buff中的数据。

简而言之,这段代码的主要目的是将一个numpy数组转换为连续的内存布局(使用Cython的内存视图),并获取该内存视图的第一个元素的地址。这样做通常是为了提高数据访问的效率或与需要连续内存布局的C/C++代码进行交互。

code2

From

from cython.cimports.cython.view import array as cvarray
import numpy as np# Memoryview on a NumPy array
narr = np.arange(27, dtype=np.dtype("i")).reshape((3, 3, 3))
narr_view = cython.declare(cython.int[:, :, :], narr)# Memoryview on a C array
carr = cython.declare(cython.int[3][3][3])
carr_view = cython.declare(cython.int[:, :, :], carr)# Memoryview on a Cython array
cyarr = cvarray(shape=(3, 3, 3), itemsize=cython.sizeof(cython.int), format="i")
cyarr_view = cython.declare(cython.int[:, :, :], cyarr)# Show the sum of all the arrays before altering it
print(f"NumPy sum of the NumPy array before assignments: {narr.sum()}")# We can copy the values from one memoryview into another using a single
# statement, by either indexing with ... or (NumPy-style) with a colon.
carr_view[...] = narr_view
cyarr_view[:] = narr_view
# NumPy-style syntax for assigning a single value to all elements.
narr_view[:, :, :] = 3# Just to distinguish the arrays
carr_view[0, 0, 0] = 100
cyarr_view[0, 0, 0] = 1000# Assigning into the memoryview on the NumPy array alters the latter
print(f"NumPy sum of NumPy array after assignments: {narr.sum()}")# A function using a memoryview does not usually need the GIL
@cython.nogil
@cython.ccall
def sum3d(arr: cython.int[:, :, :]) -> cython.int:i: cython.size_tj: cython.size_tk: cython.size_tI: cython.size_tJ: cython.size_tK: cython.size_ttotal: cython.int = 0I = arr.shape[0]J = arr.shape[1]K = arr.shape[2]for i in range(I):for j in range(J):for k in range(K):total += arr[i, j, k]return total# A function accepting a memoryview knows how to use a NumPy array,
# a C array, a Cython array...
print(f"Memoryview sum of NumPy array is {sum3d(narr)}")
print(f"Memoryview sum of C array is {sum3d(carr)}")
print(f"Memoryview sum of Cython array is {sum3d(cyarr)}")
# ... and of course, a memoryview.
print(f"Memoryview sum of C memoryview is {sum3d(carr_view)}")
# 此代码应提供以下输出:NumPy sum of the NumPy array before assignments: 351
NumPy sum of NumPy array after assignments: 81
Memoryview sum of NumPy array is 81
Memoryview sum of C array is 451
Memoryview sum of Cython array is 1351
Memoryview sum of C memoryview is 451

👇的内容是小度在这里插入图片描述的回答:

这段代码主要是关于Cython的内存视图(memoryview)特性,以及如何使用Cython与NumPy、C数组和Cython数组进行交互。下面是对代码的详细解释:

  1. 导入相关模块:

    • from cython.cimports.cython.view import array as cvarray: 导入Cython的carray(C风格数组)作为cvarray。
    • import numpy as np: 导入NumPy库。
  2. 创建NumPy数组:

    • narr = np.arange(27, dtype=np.dtype("i")).reshape((3, 3, 3)): 创建一个形状为(3,3,3)的整数数组,并初始化其值。
  3. 声明Cython内存视图:

    • narr_view = cython.declare(cython.int[:, :, :], narr): 为NumPy数组创建一个Cython内存视图。
    • carr = cython.declare(cython.int[3][3][3]): 声明一个C风格的3x3x3整数数组。
    • cyarr = cvarray(shape=(3, 3, 3), itemsize=cython.sizeof(cython.int), format="i"): 创建一个Cython的carray。
  4. 显示数组和赋值:

    • print(f"NumPy sum of the NumPy array before assignments: {narr.sum()}"): 在赋值之前打印NumPy数组的总和。
    • carr_view[...] = narr_viewcyarr_view[:] = narr_view: 将NumPy数组的值复制到C风格数组和Cython数组中。
    • narr_view[:, :, :] = 3: 将NumPy数组的所有元素设置为3。
    • carr_view[0, 0, 0] = 100cyarr_view[0, 0, 0] = 1000: 分别设置C风格数组和Cython数组的特定元素值。
  5. 检查赋值后的总和:

    • print(f"NumPy sum of NumPy array after assignments: {narr.sum()}"): 在赋值之后打印NumPy数组的总和,由于所有元素都被设置为3,所以总和应为27。
  6. 定义一个使用内存视图的函数:

    • @cython.nogil@cython.ccall 是Cython的装饰器,它们允许函数在没有全局解释器锁(GIL)的情况下运行,并允许直接调用C函数。
    • sum3d 函数接受一个三维整数数组作为参数,并返回其所有元素的总和。
  7. 调用内存视图函数:
    使用先前定义的sum3d函数,分别对NumPy数组、C风格数组、Cython数组以及C风格的内存视图调用该函数,并打印结果。

总的来说,这段代码展示了如何使用Cython的内存视图来与NumPy、C风格数组和Cython数组进行交互,以及如何通过内存视图进行高效的数值计算。

小结

C桑 这种啰嗦的语言风格, 真是让Python🐶抓狂😖…

不过, 这种高效倒是真的…

我们现在比纯 Python 版本快 7558 倍,比 NumPy 快 11.1 倍!
以上
未完待续

这篇关于C桑(Cython)从入门到入土(2): np数组操作对比的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/599222

相关文章

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

Python 中的 with open文件操作的最佳实践

《Python中的withopen文件操作的最佳实践》在Python中,withopen()提供了一个简洁而安全的方式来处理文件操作,它不仅能确保文件在操作完成后自动关闭,还能处理文件操作中的异... 目录什么是 with open()?为什么使用 with open()?使用 with open() 进行

Linux ls命令操作详解

《Linuxls命令操作详解》通过ls命令,我们可以查看指定目录下的文件和子目录,并结合不同的选项获取详细的文件信息,如权限、大小、修改时间等,:本文主要介绍Linuxls命令详解,需要的朋友可... 目录1. 命令简介2. 命令的基本语法和用法2.1 语法格式2.2 使用示例2.2.1 列出当前目录下的文

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Python实现Microsoft Office自动化的几种方式及对比详解

《Python实现MicrosoftOffice自动化的几种方式及对比详解》办公自动化是指利用现代化设备和技术,代替办公人员的部分手动或重复性业务活动,优质而高效地处理办公事务,实现对信息的高效利用... 目录一、基于COM接口的自动化(pywin32)二、独立文件操作库1. Word处理(python-d