在numpy添加期间隐含发生了什么?

时间:2018-02-08 09:20:44

标签: python c++ arrays numpy

添加numpy数组时会发生什么?我用C ++编写了一个CUDA应用程序来计算平方距离,我使用cdll与Python接口。 Python包装器如下所示:

def sqdist(X: np.ndarray) -> np.ndarray:

    # Organize input and output
    N, D = X.shape
    X = X.astype(np.float32)
    Y = np.zeros((N, N)).astype(np.float32)

    # Prepare memory pointers
    dataIn = X.ctypes.data_as(cdll.POINTER(cdll.c_float))
    dataOut = Y.ctypes.data_as(cdll.POINTER(cdll.c_float))

    # Call the sqdist dll
    cdll.load(_get_build_default())
    cdll.computeSquaredEuclideanDistances(dataIn, N, D, dataOut)
    cdll.unload()

    # Return as numpy array
    return Y

注意转换为float32以使用numpy ctypes data_as(CUDA使用32位浮点数)。现在,将此方法的输出与scipy.spatial.distance.cdist(a,a,metric='sqeuclidean')的输出进行比较,我发现了一个奇怪的行为:

假设我有一些数据Xcl(numpy数组):

输入1

a = Xcl
b = Xcl + np.zeros(Xcl.shape)
print(a.dtype, type(a), a.shape)
print(b.dtype, type(b), b.shape)
print(np.all(a == b))

输出1

float32 <class 'numpy.ndarray'> (582, 115)
float64 <class 'numpy.ndarray'> (582, 115)
True

输入[2]:

scipydist = scipy.spatial.distance.cdist(a, a, metric='sqeuclidean')
cudadist1 = cuda.sqdist(a)
cudadist2 = cuda.sqdist(b)

plt.figure(figsize=(20, 5))
plt.subplot(131)
plt.imshow(scipydist, vmax=3000)
plt.colorbar()
plt.title("scipydist")
plt.subplot(132)
plt.imshow(cudadist1, vmax=3000)
plt.colorbar()
plt.title("cudadist1")
plt.subplot(133)
plt.imshow(cudadist2, vmax=3000)
plt.colorbar()
plt.title("cudadist2")
plt.show()

输出[2]:

enter image description here

即。我得到了不同的CUDA算法输出,具体取决于我是否在输入中添加了零。 如何(地狱)会发生什么?在加入numpy期间会隐含地发生什么?np.ones相乘也是如此。

1 个答案:

答案 0 :(得分:0)

好的。这似乎是由于某种内存布局。在我的包装器中使用np.astype,默认为order='K'

  

K表示尽可能接近数组元素在内存中出现的顺序

而CUDA应用程序期望数据按顺序排列C.将包装器更新为以下内容解决了问题:

X = X.astype(np.float32, order='C')
Y = np.zeros((N, N)).astype(np.float32, order='C')

因此,我认为numpy的加法会隐含地将基础数据重新排序到任何适合它的数据?