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

相关文章

JavaScript对象转数组的三种方法实现

《JavaScript对象转数组的三种方法实现》本文介绍了在JavaScript中将对象转换为数组的三种实用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录方法1:使用Object.keys()和Array.map()方法2:使用Object.entr

使用Java填充Word模板的操作指南

《使用Java填充Word模板的操作指南》本文介绍了Java填充Word模板的实现方法,包括文本、列表和复选框的填充,首先通过Word域功能设置模板变量,然后使用poi-tl、aspose-words... 目录前言一、设置word模板普通字段列表字段复选框二、代码1. 引入POM2. 模板放入项目3.代码

利用Python操作Word文档页码的实际应用

《利用Python操作Word文档页码的实际应用》在撰写长篇文档时,经常需要将文档分成多个节,每个节都需要单独的页码,下面:本文主要介绍利用Python操作Word文档页码的相关资料,文中通过代码... 目录需求:文档详情:要求:该程序的功能是:总结需求:一次性处理24个文档的页码。文档详情:1、每个

Python内存管理机制之垃圾回收与引用计数操作全过程

《Python内存管理机制之垃圾回收与引用计数操作全过程》SQLAlchemy是Python中最流行的ORM(对象关系映射)框架之一,它提供了高效且灵活的数据库操作方式,本文将介绍如何使用SQLAlc... 目录安装核心概念连接数据库定义数据模型创建数据库表基本CRUD操作创建数据读取数据更新数据删除数据查

Go语言中json操作的实现

《Go语言中json操作的实现》本文主要介绍了Go语言中的json操作的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录 一、jsOChina编程N 与 Go 类型对应关系️ 二、基本操作:编码与解码 三、结构体标签(Struc

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

Java 字符串操作之contains 和 substring 方法最佳实践与常见问题

《Java字符串操作之contains和substring方法最佳实践与常见问题》本文给大家详细介绍Java字符串操作之contains和substring方法最佳实践与常见问题,本文结合实例... 目录一、contains 方法详解1. 方法定义与语法2. 底层实现原理3. 使用示例4. 注意事项二、su

Java Stream流与使用操作指南

《JavaStream流与使用操作指南》Stream不是数据结构,而是一种高级的数据处理工具,允许你以声明式的方式处理数据集合,类似于SQL语句操作数据库,本文给大家介绍JavaStream流与使用... 目录一、什么是stream流二、创建stream流1.单列集合创建stream流2.双列集合创建str

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo