¿La mejor manera de hacer una gran cantidad de cálculos vectoriales con gpgpu?

Tengo una matriz de 1 millón de columnas x 1 millón de filas.

Mi algoritmo necesita hacer:

Matrix m  = Matrix(rows,cols)
for (colB: cols){
  vector currColA = m.getcolumn(colA)

  for (colB: cols){
    vector currColB = m.getcolumn(colB)
    result = currColA.dotProduct(colB)
    return result;
}}

o también podrías decir:

Vectors [] v  = Vectors[]

for (i: v.length){
  vector v1 = v[i]

  for (i: v.length){
    vector v2 = v[i]
    result = v1.dotProduct(v2)
    return result;
}}

Mi pregunta: ¿cuál es la forma correcta de asignar memoria e inicializar la memoria para este problema?

- ¿Debo asignar la memoria para la matriz completa, inicializarla con la matriz completa y luego ejecutar el algoritmo?
- ¿O debería asignar la memoria para una lista de vectores y luego recorrer esta lista?
- ¿¿si no??

Mi preocupación es que me gustaría minimizar los tiempos de transferencia a la gpu. He intentado este tipo de cálculos modificando el JCublas hola mundo ejemplo para una operación sgemm en 2 vectores, pero al hacerlo en mi gran cantidad de vectores, terminé teniendo tiempos de transferencia que eliminaban los beneficios de la aceleración gpu.

¡Gracias! PD: la implementación podría estar en cualquier biblioteca de Java

preguntado el 12 de junio de 12 a las 16:06

¿Es esta una matriz dispersa o densa? Una matriz densa de 1 millón x 1 millón de valores enteros o de punto flotante de 32 bits requiere 4000 Gb de memoria. Eso no solo no cabrá en ninguna memoria de GPU, sino que no cabrá en la memoria de ningún sistema host para el que no necesite un centro de datos dedicado. ¿En qué tipo de máquina planea hacer esta operación? -

@talonmies, uso una matriz de 250,000 vectores dispersos de valores dobles. La longitud de cualquier vector es 1,100,000. (code.google.com/p/matrix-toolkits-java/source/browse/trunk/src/… los vectores son escaso (se llenan 10 valores en promedio). Por el momento puedo ejecutarlo con subprocesos múltiples en mi computadora portátil con i7-2860, 16Gb, pero toma un par de horas. -

1 Respuestas

Parece que está aplicando una restricción de 1 a la vez. Copia de CPU->GPU, espera, calcula, copia de GPU->CPU, espera. La mayoría de la gente no se da cuenta de las esperas implícitas que pueden causar las copias de memoria.

¿Puede canalizar sus operaciones? En otras palabras, ¿su bucle consiste en lo siguiente?

  • Copia CPU->GPU
  • Computación de GPU
  • Copia GPU->CPU

Para canalizar esto, usaría (por ejemplo) 4 colas de comando separadas (en orden), emitiría una transferencia sin bloqueo a la GPU en cada cola, emitiría la ejecución del kernel en cada cola y emitiría la copia GPU->CPU en cada cola. cola, en ese orden. Debe garantizar que ambos búfer sigan siendo válidos hasta la espera (descrita más adelante). Esto permitirá que la GPU comience a computar mientras se realizan las transferencias de memoria posteriores.

Además, nunca use bloqueo de transferencias de memoria, siempre use no bloqueo. Cada tantas (8?) transferencias, obtenga un objeto de evento para la copia GPU->CPU, pero espere primero al último objeto de evento si esta no es la primera iteración. Esto acelerará sus colas y le permitirá reutilizar los búferes, pero la superposición de las operaciones mantiene las transferencias y el cómputo superpuestos. Estamos esperando la transferencia hace 8 iteraciones, por lo que no estamos agotando la cola. Es importante administrar la profundidad de la cola, los elementos de trabajo excesivos provocan una interfaz gráfica de usuario lenta y la inanición de los elementos de trabajo.

Respondido el 14 de junio de 12 a las 14:06

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