一連のベクトルの大きさを取得するために、次のカーネルがあります。
__global__ void norm_v1(double *in, double *out, int n)
{
const uint i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < n)
{
double x = in[3*i], y = in[3*i+1], z = in[3*i+2];
out[i] = sqrt(x*x + y*y + z*z);
}
}
ただし、パッキングが原因in
で[x0,y0,z0,...,xn,yn,zn]
パフォーマンスが低下し、プロファイラーは 32% のグローバル負荷効率を示しています。としてデータを再パックする[x0, x1, ..., xn, y0, y1, ..., yn, z0, z1, ..., zn]
と、状況が大幅に改善されます ( x
、y
、およびz
それに応じてオフセットが変更されます)。実行時間が短縮され、効率は最大 100% になります。
ただし、このパッキングは私のアプリケーションには実用的ではありません。したがって、共有メモリの使用を調査したいと思います。私の考えは、ブロック内の各スレッドがblockDim.x
グローバル メモリから 3 つの値を (別々に) コピーすることであり、結合されたアクセスが得られます。blockDim.x = 256
私が思いついた最大値の仮定の下で:
#define BLOCKDIM 256
__global__ void norm_v2(double *in, double *out, int n)
{
__shared__ double invec[3*BLOCKDIM];
const uint i = blockIdx.x * blockDim.x + threadIdx.x;
invec[0*BLOCKDIM + threadIdx.x] = in[0*BLOCKDIM+i];
invec[1*BLOCKDIM + threadIdx.x] = in[1*BLOCKDIM+i];
invec[2*BLOCKDIM + threadIdx.x] = in[2*BLOCKDIM+i];
__syncthreads();
if (i < n)
{
double x = invec[3*threadIdx.x];
double y = invec[3*threadIdx.x+1];
double z = invec[3*threadIdx.x+2];
out[i] = sqrt(x*x + y*y + z*z);
}
}
n % blockDim.x != 0
ただし、これは が事前に最大値を知る必要があり、でテストした場合にblockDim
誤った結果を生成する場合、明らかに不十分です。これをどのように修正するのが最善ですか?out[i > 255]
n = 1024