У меня есть структура данных с именем mol
, которую я пытаюсь выполнить с использованием ядра CUDA. Это выглядит так:
typedef struct {
float x, y, z;
} VecR;
typedef struct {
VecR r, rv, ra;
} Mol;
Я инициализирую указатель (Mol *mol
), выделяю пространство в объединенной памяти, инициализирую массив на хосте, чтобы в итоге получилось нечто подобное передается в ядро:
mol[foo] = {r = {x = -3.3927002, y = 1.72338998, z = 1.32186997}, rv = {x = 0.0281415954, y = 0.162121773, z = 0.606185317}, ra = {x = 0, y = 0, z = 0}}
Затем я передаю его этому ядру, которое должно выполнять вычисления для каждого из элементов и сохранять значения в соответствующих местах в массиве:
__global__ void computeForces(Mol *mol) {
int j1 = blockIdx.x * blockDim.x + threadIdx.x;
int j2 = 0;
VecR dr;
real fcVal, rr, rrCut, rri, rri3;
rrCut = Sqr(rCut);
mol[j1].ra.x = 0;
mol[j1].ra.y = 0;
mol[j1].ra.z = 0;
for (j2 = 0; j2 < nMol && j2!=j1; j2++) {
dr.x = mol[j1].r.x, mol[j2].r.x;
dr.y = mol[j1].r.y, mol[j2].r.y;
dr.z = mol[j1].r.z, mol[j2].r.z;
rr = VLenSq(dr); //This just the sum square of the values in dr
//Cutoff
if (rr < rrCut) {
rri = 1. / rr;
rri3 = Cube(rri);
fcVal = 48. * rri3 * (rri3 - 0.5) * rri;
Mol anchor = mol[j1];
float fcValdrx = fcVal*dr.x;
float fcValdry = fcVal*dr.y;
float fcValdrz = fcVal*dr.z;
atomicAdd(&(mol[j2].ra.x), -fcValdrx);
atomicAdd(&(mol[j2].ra.y), -fcValdry);
atomicAdd(&(mol[j2].ra.z), -fcValdrz);
}
}
}
В итоге я должен получить ra.x, ra.y, ra.z
порядка 1e0 или 1e-1 для каждого элемента массива. Однако, это не так. Для первых нескольких (возможно, 10) элементов в mol
значения ra.x, ra.y, ra.z
являются огромными, казалось бы, случайными числами (порядка 1e40). Для остальных элементов I я получаю 0 для этих значений.
Мне кажется, что я не обращаюсь к памяти правильно, но я недостаточно знаком с деталями функций управления памятью CUDA, чтобы точно понять, что происходит. Я изучил __threadfence()
и __syncthreads()
, но все еще не уверен, как именно их применять.