Manera rápida de encontrar el máximo de una matriz flotante en OpenCL

Tengo problemas con la simple tarea de encontrar el máximo de una matriz en OpenCL.

__kernel void ndft(/* lots of stuff*/)
{
    size_t thread_id = get_global_id(0); // thread_id = [0 .. spectrum_size[

    /* MATH MAGIC */

    // Now I have    float spectrum_abs[spectrum_size]    and
    // I want the maximum as well as the index holding the maximum

    barrier();
    // this is the old, sequential code:
    if (*current_max_value < spectrum_abs[i])
    {
        *current_max_value = spectrum_abs[i];
        *current_max_freq = i;
    }
}

Ahora podría agregar if (thread_id == 0) y recorrer todo el proceso como lo haría en un sistema de un solo núcleo, pero dado que el rendimiento is un problema crítico (de lo contrario, no estaría haciendo cálculos de espectro en una GPU), ¿hay una forma más rápida de hacerlo?

Volver a la CPU al final del kernel anterior no es una opción, porque el kernel en realidad continúa después de eso.

preguntado el 03 de mayo de 12 a las 20:05

¿Cuál es el tamaño de sus datos? ¿Cuál es el tamaño de su grupo de trabajo? -

@ananthonline El tamaño de los datos es igual al tamaño del elemento de trabajo global y varía entre 25k y 40k -

1 Respuestas

Necesitarás escribir una reducción paralela. Divida su matriz "grande" en partes pequeñas (un tamaño que un solo grupo de trabajo puede procesar de manera efectiva) y calcule el mínimo-máximo en cada una.

Haga esto de forma iterativa (involucra tanto el código del host como el del dispositivo) hasta que solo le quede un conjunto de valores mínimos/máximos.

Tenga en cuenta que es posible que deba escribir un núcleo separado que haga esto a menos que la distribución de trabajo actual funcione para esta parte del kernel (ver mi pregunta a usted arriba).

Una alternativa si su distribución de trabajo actual es adecuada es encontrar el mínimo máximo dentro de cada grupo de trabajo y escribirlo en un búfer en la memoria global (índice = local_id). Después de una barrera (), simplemente haga que el kernel se ejecute en thread_id == 0 en bucle a través de los resultados reducidos y encuentre el máximo en él. Esta no será la solución óptima, pero podría ser una que encaje dentro de su núcleo actual.

contestado el 03 de mayo de 12 a las 22:05

puede pensar en esto como un "árbol" de reducciones y ver que toma tiempo O (log (n)), en lugar de O (n) para un solo hilo. además, debería haber soporte para esto en las bibliotecas (es una técnica muy común). por ejemplo, pyopencl - documen.tician.de/pyopencl/array.html#module-pyopencl.reducción - Andrew Cooke

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.