Python numpy 数组之间共享指针

标签 python arrays numpy pointers shared-ptr

请您帮忙解决以下问题。我希望按照方案构建 3 个 numpy 数组:

       +---+
       | a |
arr1 : +---+      +---+
       | b |  <-  | b |  
       +---+      |   |
                  +---+  : arr
       +---+      |   |
       | c |  <-  | c | 
arr2 : +---+      +---+
       | d |
       +---+

因此arr与其他数组共享其值。

arr1arr2 是由示例定义的经典 numpy 数组:

arr1 = np.array([1,2]); arr2 = np.array([3,4])

然后,我可以通过哪种方式构建 arr 以便具有行为

arr1[1] = 7  ### will give  arr1 = [1,7]   arr2 = [3,4]    arr = [7,3]
arr[1] = 13  ### will give  arr1 = [1,7]   arr2 = [13,4]   arr = [7,13]

我的测试

经过几个小时的网络测试,ctypes 功能似乎是模仿 Python 中 C 指针行为的解决方案。我已经尝试过这个:

import numpy as np
import ctypes

arr1 = np.array([1.0,0.2]).astype(np.float32)
arr2 = np.array([3.0,4.0]).astype(np.float32)
arr1_ptr = arr1.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
arr1bis = np.ctypeslib.as_array((ctypes.c_float * arr1.size).from_address(ctypes.addressof(arr1_ptr.contents)))
print(arr1bis)      ####   --> [ 1.   0.2]
arr1[0] = 7.0
print(arr1bis)      ####   --> [ 7.   0.2]
arr1bis[1] = 13.0
print(arr1)         ####   --> [ 7.   13.]

所以在这里我设法在同一个数组上有两个指针。但从多个内存位置构建一个数组似乎要困难得多。如果有人有想法......

感谢您的帮助。

编辑:我的测试 2 - 解决方案的开始

非常感谢您的回答。 大全局数组的想法是有用的,因为它比在每次修改副本时更新副本的双重存储的惰性解决方案更便宜。而且实现起来非常简单。以下性能测试代码

import numpy as np
from time import time

def benchmark(d_size,s_len):
      print("Interraction domain size: ",d_size,"   state length: ",s_len)

      arr_combined = np.arange(s_len*d_size**2).reshape((d_size,d_size,s_len))

      list_of_state = [ np.ndarray.view(arr_combined[i,j,:]) for i in range(d_size) for j in range(d_size) ]
      interraction_between_state = np.ndarray.view( arr_combined[:,:,0] )

      t0 = time()
      for state in list_of_state : state[0]+=1
      interraction_between_state*= -1
      for state in list_of_state : state[0]+=1
      print( "Exec time with np.ndarray.view: ", time()-t0 )

      list_of_state2 = [ np.arange(s_len)+s_len*(j+d_size*i) for i in range(d_size) for j in range(d_size) ]
      interraction_between_state2 = np.array( [ state[0] for state in list_of_state2 ] ).reshape((d_size,d_size))

      t0 = time()
      for state in list_of_state2 : state[0]+=1
      ### Update interraction_between_state2
      for i in range(d_size): 
          for j in range(d_size):
              interraction_between_state2[i,j]= list_of_state2[j+d_size*i][0]

      interraction_between_state2*= -1
      ### Update list_of_state2
      for i in range(d_size): 
          for j in range(d_size):
              list_of_state2[j+d_size*i][0] = interraction_between_state2[i,j]

      for state in list_of_state2 : state[0]+=1
      print("Exec time with array update:    ", time()-t0 )

benchmark(100,5)
benchmark(1000,5)
benchmark(100,50)

给出

Interraction domain size:  100    state length:  5
Exec time with np.ndarray.view:  0.00500103759765625
Exec time with array update:     0.011001110076904297
Interraction domain size:  1000    state length:  5
Exec time with np.ndarray.view:  0.5620560646057129
Exec time with array update:     1.1111111640930176
Interraction domain size:  100    state length:  50
Exec time with np.ndarray.view:  0.0060007572174072266
Exec time with array update:     0.01200103759765625

因此,即使np.ndarray.view给出的 View 生成非内存连续数据表示,与数据重复的解决方案相比,性能也更好。

但是

如果结构不一致(维度方面),如何将它们正确地放入全局数组中?例如,如果我回到第一个带有 arrarr1arr2 的简单示例,并将 arr2 替换为

arr2 = np.array([3,4,5])

为了构建全局数组,我想到了两种解决方案:

  • 将全局数组写在一行中。

global_arr = np.array([1,2,3,4,5])

如果arr1arr2是二维或三维的,就会丢失一些结构,并且强制提前知道全局数组和局部 View 之间索引的对应关系。此外,任何子数组都将是内存连续的,因此应该需要一些补充测试来了解这种情况下性能的实际增益。

  • 保留结构,并在被视为无效的单元格中添加 np.nan 值。

global_arr = np.array( [ [1,2,np.nan], [3,4,5]])

您对这两种解决方案有何看法?还有另一种方法可以巧妙地构建这个全局数组吗?

最佳答案

我认为解决您问题的最简单方法是创建一个大数组,其中包含您想要操作的所有数据,然后您可以以任何您想要分组的方式创建数据的 View 它:

import numpy as np

arr_combined = np.array([1,2,3,4])
arr1 = np.ndarray.view(arr_combined[:2])
arr2 = np.ndarray.view(arr_combined[2:])
arr = np.ndarray.view(arr_combined[1:3])

这并不完全是您所要求的,但它至少使您可以按照您在示例中编写的方式访问数据。此外,当然这不仅限于四个元素的小情况,还可以用于具有数千个元素的用例。

关于Python numpy 数组之间共享指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45736951/

相关文章:

python - Django:与 factory_boy 的一对一字段:UNIQUE 约束失败

arrays - 满足以下关系的数组中的最长序列 X[ i ] = X[ i-1 ] + X [ i-2 ]

arrays - firebase swift 观察者之外的空数组

python - 在 Python 进程之间共享内存中的大型数据结构?

javascript - django 提供静态文件/angularJS 应用程序

python - 根据数据帧中值的重复创建计数器

python - 你如何在 Numpy 中找到 IQR?

Python list reversed 不能被多次访问

python - 列表中接近重复的元素

c - 打印二维字符数组的镜像