Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 预测ufunc输出的内存布局_Python_Numpy_Memory Layout_Numpy Ufunc - Fatal编程技术网

Python 预测ufunc输出的内存布局

Python 预测ufunc输出的内存布局,python,numpy,memory-layout,numpy-ufunc,Python,Numpy,Memory Layout,Numpy Ufunc,使用numpyndarrays大多数时候,我们不必担心内存布局,因为结果并不依赖于它 除非他们这样做。例如,考虑这种稍微过度设计的方式设置3x2矩阵的斜率。 >>> a = np.zeros((3,2)) >>> a.reshape(2,3)[:,0] = 1 >>> a array([[1., 0.], [0., 1.], [0., 0.]]) 只要我们控制a的内存布局就可以了。但如果我们不这样做,这是一个错误

使用numpy
ndarray
s大多数时候,我们不必担心内存布局,因为结果并不依赖于它

除非他们这样做。例如,考虑这种稍微过度设计的方式设置3x2矩阵的斜率

>>> a = np.zeros((3,2))
>>> a.reshape(2,3)[:,0] = 1
>>> a
array([[1., 0.],
       [0., 1.],
       [0., 0.]])
只要我们控制
a
的内存布局就可以了。但如果我们不这样做,这是一个错误,更糟糕的是,这是一个令人讨厌的沉默的错误:

>>> a = np.zeros((3,2),order='F')
>>> a.reshape(2,3)[:,0] = 1
>>> a
array([[0., 0.],
       [0., 0.],
       [0., 0.]])
这足以说明内存布局不仅仅是一个实现细节

要掌握阵列布局,人们可能会合理地问的第一件事是,新阵列是什么样子的?工厂
为空
为一
为零
标识
等。默认情况下返回C-连续布局

但是,这条规则并不适用于numpy分配的每个新数组。例如:

>>> a = np.arange(8).reshape(2,2,2).transpose(1,0,2)
>>> aa = a*a
产品
aa
是由ufunc
np.multiply
分配的新数组。它是C-连续的吗?否:

>>> aa.strides
(16, 32, 8)
我的猜测是,这是一个优化的结果,该优化认识到该操作可以在平面线性阵列上完成,这将解释为什么输出与输入具有相同的内存布局

事实上,这甚至是有用的,不像下面的无意义函数。它展示了一种简便的习惯用法,可以在保持索引简单的同时实现axis参数

>>> def symmetrize_along_axis(a,axis=0):
...     aux = a.swapaxes(0,axis)
...     out = aux + aux[::-1]
...     return out.swapaxes(0,axis)
稍微令人惊讶但显然令人满意的是,只要输入是连续的,就会产生连续的输出

>>> a = np.arange(8).reshape(2,2,2)
>>> symmetrize_along_axis(a,1).flags.contiguous
True
这足以说明了解UFUNC返回的布局是非常有用的。因此,我的问题是:

给定ufunc参数的布局,是否有任何关于输出布局的规则或保证?

a=np.zeros((3,2),order='F')
情况下,
a.reformate(2,3)
创建副本,而不是视图。这就是分配失败的原因,而不是内存布局本身

请看相同形状的阵列:

In [123]: a = np.arange(6).reshape(3,2)                                                              
In [124]: a                                                                                          
Out[124]: 
array([[0, 1],
       [2, 3],
       [4, 5]])
In [125]: a.reshape(2,3)                                                                             
Out[125]: 
array([[0, 1, 2],
       [3, 4, 5]])
In [127]: a.reshape(2,3)[:,0]                                                                        
Out[127]: array([0, 3])
在[125]中,值仍按顺序C流动

和一个F阶数组:

In [128]: b = np.arange(6).reshape(3,2, order='F')                                                   
In [129]: b                                                                                          
Out[129]: 
array([[0, 3],                 # values flow in order F
       [1, 4],
       [2, 5]])
In [130]: b.reshape(2,3)                                                                             
Out[130]: 
array([[0, 3, 1],              # values are jumbled
       [4, 2, 5]])
In [131]: b.reshape(2,3)[:,0]                                                                        
Out[131]: array([0, 4])
如果我在形状中保持顺序F:

In [132]: b.reshape(2,3, order='F')                                                                  
Out[132]: 
array([[0, 2, 4],               # values still flow in order F
       [1, 3, 5]])
In [133]: b.reshape(2,3, order='F')[:,0]                                                             
Out[133]: array([0, 1])
与任务确认:

In [135]: a.reshape(2,3)[:,0]=10                                                                     
In [136]: a                                                                                          
Out[136]: 
array([[10,  1],
       [ 2, 10],
       [ 4,  5]])
In [137]: b.reshape(2,3)[:,0]=10                                                                     
In [138]: b                                                                                          
Out[138]: 
array([[0, 3],
       [1, 4],
       [2, 5]])
非转让:

In [135]: a.reshape(2,3)[:,0]=10                                                                     
In [136]: a                                                                                          
Out[136]: 
array([[10,  1],
       [ 2, 10],
       [ 4,  5]])
In [137]: b.reshape(2,3)[:,0]=10                                                                     
In [138]: b                                                                                          
Out[138]: 
array([[0, 3],
       [1, 4],
       [2, 5]])
但在这里,任务是有效的:

In [139]: b.reshape(2,3, order='F')[:,0]=10                                                          
In [140]: b                                                                                          
Out[140]: 
array([[10,  3],
       [10,  4],
       [ 2,  5]])
或者我们可以使用order
A
来维持秩序:

In [143]: b.reshape(2,3, order='A')[:,0]                                                             
Out[143]: array([10, 10])
In [144]: b.reshape(2,3, order='A')[:,0] = 20                                                        
In [145]: b                                                                                          
Out[145]: 
array([[20,  3],
       [20,  4],
       [ 2,  5]])
ufunc命令 我怀疑
ufunc
主要是用
nditer
(C版本)实现的,所以我检查了np.nditer`docs-可以在几个地方指定顺序。本教程演示了迭代的顺序效应

我没有看到
ufunc
order
文档,但是
kwargs
接受它

In [171]: c = np.arange(8).reshape(2,2,2)                                                            
In [172]: d = c.transpose(1,0,2)                                                                     
In [173]: d.strides                                                                                  
Out[173]: (16, 32, 8)
In [174]: np.multiply(d,d,order='K').strides                                                         
Out[174]: (16, 32, 8)
In [175]: np.multiply(d,d,order='C').strides                                                         
Out[175]: (32, 16, 8)
In [176]: np.multiply(d,d,order='F').strides                                                         
Out[176]: (8, 16, 32)
“…创建副本,而不是视图。这就是分配失败的原因,…”以及它创建副本的原因?因为内存布局不允许查看。@Panzer在“注释”部分对此进行了解释。但不确定它是否回答了你的问题。