【发布时间】:2013-01-24 15:12:14
【问题描述】:
我需要帮助来了解我的块和网格的大小。 我正在构建一个 python 应用程序来执行基于 scipy 的度量计算:欧几里德距离、曼哈顿、皮尔森、余弦、加入其他。
项目是PycudaDistances。
它似乎适用于小型数组。当我进行更详尽的测试时,不幸的是它没有用。我下载了movielens set (http://www.grouplens.org/node/73)。
使用Movielens 100k,我声明了一个形状为 (943, 1682) 的数组。即用户对943部和1682部影片进行评价。不是分类器用户的电影我将值配置为 0。
使用更大的数组算法不再有效。我面临以下错误:
pycuda._driver.LogicError: cuFuncSetBlockShape 失败:值无效。
研究这个错误,我找到了一个解释,告诉 Andrew 支持 512 个线程加入和处理更大的块,必须使用块和网格。
我需要帮助来调整欧几里得距离数组算法,使其适用于从小型数组到巨型数组。
def euclidean_distances(X, Y=None, inverse=True):
X, Y = check_pairwise_arrays(X,Y)
rows = X.shape[0]
cols = Y.shape[0]
solution = numpy.zeros((rows, cols))
solution = solution.astype(numpy.float32)
kernel_code_template = """
#include <math.h>
__global__ void euclidean(float *x, float *y, float *solution) {
int idx = threadIdx.x + blockDim.x * blockIdx.x;
int idy = threadIdx.y + blockDim.y * blockIdx.y;
float result = 0.0;
for(int iter = 0; iter < %(NDIM)s; iter++) {
float x_e = x[%(NDIM)s * idy + iter];
float y_e = y[%(NDIM)s * idx + iter];
result += pow((x_e - y_e), 2);
}
int pos = idx + %(NCOLS)s * idy;
solution[pos] = sqrt(result);
}
"""
kernel_code = kernel_code_template % {
'NCOLS': cols,
'NDIM': X.shape[1]
}
mod = SourceModule(kernel_code)
func = mod.get_function("euclidean")
func(drv.In(X), drv.In(Y), drv.Out(solution), block=(cols, rows, 1))
return numpy.divide(1.0, (1.0 + solution)) if inverse else solution
更多详情见:https://github.com/vinigracindo/pycudaDistances/blob/master/distances.py
【问题讨论】:
标签: python cuda gpu pycuda euclidean-distance