添加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]:
即。我得到了不同的CUDA算法输出,具体取决于我是否在输入中添加了零。 如何(地狱)会发生什么?在加入numpy期间会隐含地发生什么?与np.ones
相乘也是如此。
答案 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的加法会隐含地将基础数据重新排序到任何适合它的数据?