ブロックとグリッドのサイズを知るために助けが必要です。ユークリッド距離、マンハッタン、ピアソン、コサインなど、scipyに基づいてメトリック計算を実行するPythonアプリを構築しています。
プロジェクトはPycudaDistancesです。
小さなアレイで非常にうまく機能するようです。もっと徹底的なテストを行ったところ、残念ながらうまくいきませんでした。movielens set(http://www.grouplens.org/node/73)をダウンロードしました。
100kを使用Movielens
して、形状(943、1682)の配列を宣言しました。つまり、ユーザーは943本と1682本の映画が評価されます。分類子ユーザーによるものではないフィルムは、値を0に構成しました。
はるかに大きな配列アルゴリズムでは、機能しなくなります。次のエラーが発生します。
pycuda._driver.LogicError:cuFuncSetBlockShapeが失敗しました:値が無効です。
このエラーを調べて、512スレッドをサポートするAndrewに、ブロックとグリッドを操作する必要がある、より大きなブロックを結合して操作するように指示する説明を見つけました。
アルゴリズムのユークリッド距離配列を小さな配列から巨大な配列まで機能するように適合させるための助けが必要でした。
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を参照してください。