Je calcule la distance euclidienne entre des points n-dimensionnels en utilisant OpenCL. Je reçois deux listes de points n-dimensionnels et je devrais retourner un tableau qui contient seulement les distances de chaque point de la première table à chaque point de la deuxième table.Récapitulatif des tableaux cumulés en utilisant OpenCL
Mon approche est de faire la boucle doble régulière (pour chaque point au tableau 1 {pour chaque point Tableau2 {...}} puis faire le calcul pour chaque paire de points dans paralell.
euclidienne la distance est ensuite divisée en 3 parties: 1. prendre la différence entre chaque dimension dans les points 2. mettre cette différence par carré (toujours pour chaque dimension) 3. additionner toutes les valeurs obtenues en 2. 4. Prendre la racine carrée de la valeur obtenue en 3. (cette étape a été omise dans cet exemple.)
Tout fonctionne comme un charme jusqu'à ce que je essayer d'accumuler la somme de toutes les différences (à savoir, exécuter l'étape 3 de la procédure décrite ci-dessus, ligne 49 du code ci-dessous). Comme données de test, j'utilise DescriptorLists avec 2 points chacune: DescriptorList1: 001,002,003, ..., 127,128; (p1) 129, 130, 131, ..., 255, 256; (p2)
DescriptorList2: 000,001,002, ..., 126,127; (p1) 128,129,130, ..., 254,255; (p2)
Donc le vecteur résultant devrait avoir les valeurs: 128, 2064512, 2130048, 128 En ce moment je reçois des nombres aléatoires qui varient avec chaque exécution.
J'apprécie toute aide ou conduit sur ce que je fais mal. Espérons que tout est clair sur le scénario que je travaille dans
#define BLOCK_SIZE 128
typedef struct
{
//How large each point is
int length;
//How many points in every list
int num_elements;
//Pointer to the elements of the descriptor (stored as a raw array)
__global float *elements;
} DescriptorList;
__kernel void CompareDescriptors_deb(__global float *C, DescriptorList A, DescriptorList B, int elements, __local float As[BLOCK_SIZE])
{
int gpidA = get_global_id(0);
int featA = get_local_id(0);
//temporary array to store the difference between each dimension of 2 points
float dif_acum[BLOCK_SIZE];
//counter to track the iterations of the inner loop
int loop = 0;
//loop over all descriptors in A
for (int i = 0; i < A.num_elements/BLOCK_SIZE; i++){
//take the i-th descriptor. Returns a DescriptorList with just the i-th
//descriptor in DescriptorList A
DescriptorList tmpA = GetDescriptor(A, i);
//copy the current descriptor to local memory.
//returns one element of the only descriptor in DescriptorList tmpA
//and index featA
As[featA] = GetElement(tmpA, 0, featA);
//wait for all the threads to finish copying before continuing
barrier(CLK_LOCAL_MEM_FENCE);
//loop over all the descriptors in B
for (int k = 0; k < B.num_elements/BLOCK_SIZE; k++){
//take the difference of both current points
dif_acum[featA] = As[featA]-B.elements[k*BLOCK_SIZE + featA];
//wait again
barrier(CLK_LOCAL_MEM_FENCE);
//square value of the difference in dif_acum and store in C
//which is where the results should be stored at the end.
C[loop] = 0;
C[loop] += dif_acum[featA]*dif_acum[featA];
loop += 1;
barrier(CLK_LOCAL_MEM_FENCE);
}
}
}
Je dois dire tout d'abord, que je suis très reconnaissant de la réponse de Grizzly. Je suis plutôt nouveau à OpenCL et, bien que je devais modifier le code d'exemple qu'il a donné un peu, cela m'a mené droit dans la bonne direction.Les choses importantes que j'ai remarquées (par essais et erreurs): les threads qui ne traitent pas les positions du tableau doivent être jetés; la boucle SCAN avait besoin d'un peu de peaufinage, à savoir utiliser un tampon auxiliaire pour accumuler des résultats partiels et vérifier les conditions aux limites pour trouver les termes à ajouter. Encore merci beaucoup! Je poste le code qui a fonctionné pour moi. – SebastianP