Estoy calculando la distancia euclidiana entre puntos n-dimensionales usando OpenCL. Obtengo dos listas de puntos n-dimensionales y debería devolver una matriz que contiene solo las distancias desde cada punto en la primera tabla hasta cada punto en la segunda tabla.Suma acumulativa acumulativa usando OpenCL
Mi enfoque es hacer el bucle doble regular (por cada punto en la Tabla 1 {por cada punto en la Tabla2 {...}} y luego hacer el cálculo para cada par de puntos en paralelo.
El euclidiana la distancia se divide en 3 partes: 1. tome la diferencia entre cada dimensión en los puntos 2. cuadre esa diferencia (aún para cada dimensión) 3. sume todos los valores obtenidos en 2. 4. Tome la raíz cuadrada del valor obtenido en 3. (este paso se ha omitido en este ejemplo)
Todo funciona como un amuleto hasta que intente acumular la suma de todas las diferencias (es decir, ejecutar el paso 3. del procedimiento descrito anteriormente, línea 49 del código a continuación).
Como datos de prueba estoy usando DescriptorLists con 2 puntos cada uno: 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)
Así que el vector resultante debería tener los valores: 128, 2064512, 2130048, 128 Ahora mismo estoy obteniendo números aleatorios que varían con cada ejecución.
Agradezco cualquier ayuda o pistas sobre lo que estoy haciendo mal. Con suerte todo está claro el escenario estoy trabajando en
#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);
}
}
}
Tengo que decir, en primer lugar, que estoy muy agradecido con la respuesta de Grizzly. Soy bastante nuevo en OpenCL y, aunque necesitaba modificar el código de ejemplo que me dio un poco, me condujo directamente a la dirección correcta.Cosas importantes que noté (por prueba y error): hilos que no abordan las posiciones de la matriz necesitaban ser descartados; el bucle SCAN necesitaba un pequeño ajuste, a saber, el uso de un búfer auxiliar para acumular resultados parciales y verificar las condiciones de contorno para encontrar los términos que se agregarían. ¡De nuevo, muchas gracias! Estoy publicando el código que funcionó para mí. – SebastianP