NumPy中如何判断数组不同视图的索引是否指向同一内存?
问题背景
现有形状为(h,w)的数组in,给定常量s,可通过以下代码生成滑动窗口视图strided_in:
new_h = (h - k_h)//s + 1 new_w = (w - k_w)//s + 1 s_h, s_w = in.strides new_shape = (new_h, new_w,k_h,k_w) new_strides = (s_h * s, s_w * s, s_h, s_w) strided_in = np.lib.stride_tricks.as_strided(in,new_shape, new_strides)
该视图是将(k_h,k_w)形状的子数组以步长s在原数组上滑动得到的窗口矩阵。通过out = np.max(strided_arr, axis=(2,3))得到输出数组out后,已知与out形状一致的grad_out,需要计算和原数组in形状一致的grad_in,其元素计算逻辑如下:
grad_in[i,j] = 0 for m, row in enumerate(strided_in): for n, block in enumerate(row): grad_in[i,j] += grad_out[m,n] * (np.max(block) == in[i,j])
即当in[i,j]是某个窗口的最大值时,累加对应的grad_out[m,n]。但原数组中元素可能重复,会导致重复计数——比如基础数组arr1 = [1, 1]和其视图arr2 = [[1],[1]],需要明确区分arr1[0]和arr2[1,0]对应的内存位置。已知np.shares_memory可判断数组是否共享内存,但无法针对单个元素做判断。
核心问题
NumPy中是否有函数能判断不同数组视图的两个索引是否指向同一内存?
解决方案
NumPy没有直接提供针对单个元素的内存地址判断函数,但可以通过计算元素的内存偏移量来实现:
- 对于任意数组(或视图)
arr及其合法索引idx(多维索引用元组表示),先计算该元素相对于数组起始地址的偏移量:offset = arr.strides @ np.array(idx) - 获取数组的起始内存地址:
base_addr = arr.__array_interface__['data'][0] - 两个元素指向同一内存的充要条件是:它们的起始地址 + 偏移量完全相等。
以问题中的arr1和arr2为例:
import numpy as np arr1 = np.array([1, 1]) arr2 = np.lib.stride_tricks.as_strided(arr1, shape=(2,1), strides=(arr1.strides[0], 0)) # 计算arr1[0]的内存地址 addr_arr1_0 = arr1.__array_interface__['data'][0] + arr1.strides @ (0,) # 计算arr2[1,0]的内存地址 addr_arr2_10 = arr2.__array_interface__['data'][0] + arr2.strides @ (1, 0) # 判断是否指向同一内存 print(addr_arr1_0 == addr_arr2_10) # 输出False,因为arr2[1,0]实际指向arr1[1]
注意事项
- 该方法仅适用于共享同一基础内存的数组视图,若数组是拷贝生成的,起始地址会不同,直接比较即可排除。
- 必须确保索引是合法的,避免越界访问导致错误。
内容的提问来源于stack exchange,提问作者Andrew Lys
相关产品推荐
相关产品推荐

