カーネルコード全体を投稿していただけますか? params とプライベート変数について仮定する必要があります。
グループには nt 個の作業項目があり、ti は現在の作業項目を表します。ループが実行されると、グループ内の各アイテムは単一の要素のみをコピーします。通常、このコピーはグローバル データ ソースからのものです。最初のバリアは、他のアイテムがコピーを作成するまでワークアイテムを強制的に待機させます。これが必要なのは、グループ内のすべての作業項目が他のすべての作業項目からコピーされたデータを読み取る必要があるためです。ti は作業項目ごとに異なる必要があるため、値は同じであってはなりません。(ただし、jb*nt は最初のループではゼロに等しくなります)
カーネルコード全体は次のとおりです。
__kernel
void
nbody_sim(
__global float4* pos ,
__global float4* vel,
int numBodies,
float deltaTime,
float epsSqr,
__local float4* localPos,
__global float4* newPosition,
__global float4* newVelocity)
{
unsigned int tid = get_local_id(0);
unsigned int gid = get_global_id(0);
unsigned int localSize = get_local_size(0);
// Number of tiles we need to iterate
unsigned int numTiles = numBodies / localSize;
// position of this work-item
float4 myPos = pos[gid];
float4 acc = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
for(int i = 0; i < numTiles; ++i)
{
// load one tile into local memory
int idx = i * localSize + tid;
localPos[tid] = pos[idx];
// Synchronize to make sure data is available for processing
barrier(CLK_LOCAL_MEM_FENCE);
// calculate acceleration effect due to each body
// a[i->j] = m[j] * r[i->j] / (r^2 + epsSqr)^(3/2)
for(int j = 0; j < localSize; ++j)
{
// Calculate acceleartion caused by particle j on particle i
float4 r = localPos[j] - myPos;
float distSqr = r.x * r.x + r.y * r.y + r.z * r.z;
float invDist = 1.0f / sqrt(distSqr + epsSqr);
float invDistCube = invDist * invDist * invDist;
float s = localPos[j].w * invDistCube;
// accumulate effect of all particles
acc += s * r;
}
// Synchronize so that next tile can be loaded
barrier(CLK_LOCAL_MEM_FENCE);
}
float4 oldVel = vel[gid];
// updated position and velocity
float4 newPos = myPos + oldVel * deltaTime + acc * 0.5f * deltaTime * deltaTime;
newPos.w = myPos.w;
float4 newVel = oldVel + acc * deltaTime;
// write to global memory
newPosition[gid] = newPos;
newVelocity[gid] = newVel;
}
各ワークグループに「localSize」ワークアイテムを持つ「numTiles」ワークグループがあります。
「gid」はグローバル インデックスで、「tid」はローカル インデックスです。
ループ「for(int i = 0; i < numTiles; ++i)」と「i=0」の最初の反復から始めましょう。
たとえば、次のようになります。
numTiles = 4、localSize = 25、および numBodies = 100 = ワークアイテムの数。
次に、実行時に、gid = 80 の場合、tid = 5、idx = 5 となり、最初の代入は localPos[5] = pos[5] になります。
ここで、gid = 5、次に tid = 5 および idx = 5 を使用します。localPos[5] = pos[5] と同じ代入があります。
したがって、私が理解していることから、最初の反復と最初の「バリア」の後、各ワークアイテムには同じローカル配列「localPos」、つまり最初のグローバルブロックのサブ配列「pos[0: 24]」。
これは何が起こるかの良い説明ですか?