matrix - una - CUBLAS-¿Es posible la exponenciación de elementos de matriz?
potencia de matriz de adyacencia (1)
Estoy usando CUBLAS (bibliotecas de Cuda Blas) para operaciones de matriz.
¿Es posible usar CUBLAS para lograr la exponenciación / raíz media cuadrada de una matriz de elementos?
Quiero decir, tener la matriz 2x2
1 4
9 16
Lo que quiero es una función para elevar a un valor dado, por ejemplo, 2
1 16
81 256
y calcular el cuadrado medio de la raíz, por ejemplo
1 2
3 4
¿Es esto posible con CUBLAS? No puedo encontrar una función adecuada para este objetivo, pero pediré aquí primero para comenzar a codificar mi propio kernel.
Así que esto puede ser algo que tienes que implementar tú mismo, porque la biblioteca no lo hará por ti. (Probablemente hay alguna forma de implementarlo en términos de rutinas de nivel 3 de BLAS, sin duda la cuadratura de los elementos de la matriz, pero implicaría multiplicaciones de vector de matriz costosas y de otro modo innecesarias. Y todavía no sé cómo d hacer la operación squareroot). La razón es que estas operaciones no son realmente procedimientos de álgebra lineal; tomar la raíz cuadrada de cada elemento de la matriz en realidad no corresponde a ninguna operación de álgebra lineal fundamental.
La buena noticia es que estas operaciones con elementos son muy simples de implementar en CUDA. Una vez más, hay muchas opciones de ajuste con las que uno podría jugar para obtener el mejor rendimiento, pero uno puede comenzar con bastante facilidad.
Al igual que con las operaciones de adición matricial, tratará las matrices NxM aquí como vectores (N * M) de longitud; la estructura de la matriz no es importante para estas operaciones con elementos. Por lo tanto, pasará un puntero al primer elemento de la matriz y lo tratará como una lista única de números N * M. (Voy a suponer que está usando float
aquí, ya que estaba hablando de SGEMM
y SAXPY
anteriormente).
El kernel, el bit real del código CUDA que implementa la operación, es bastante simple. Por ahora, cada hilo calculará el cuadrado (o raíz cuadrada) de un elemento de matriz. (Si esto es óptimo o no para el rendimiento es algo que podría probar). Entonces los granos se verían como los siguientes. Supongo que estás haciendo algo como B_ij = (A_ij) ^ 2; si quieres hacer la operación en el lugar, por ejemplo, A_ij = (A_ij) ^ 2, también puedes hacer eso:
__global__ void squareElements(float *a, float *b, int N) {
/* which element does this compute? */
int tid = blockDim.x * blockIdx.x + threadIdx.x;
/* if valid, squre the array element */
if (tid < N)
b[tid] = (a[tid]*a[tid]);
}
__global__ void sqrtElements(float *a, float *b, int N) {
/* which element does this compute? */
int tid = blockDim.x * blockIdx.x + threadIdx.x;
/* if valid, sqrt the array element */
if (tid < N)
b[tid] = sqrt(a[tid]); /* or sqrtf() */
}
Tenga en cuenta que si está bien con un error muy ligeramente mayor, la función ''sqrtf ()'' que tiene el error máximo de 3 ulp (unidades en el último lugar) es significativamente más rápido.
Cómo llamas a estos núcleos dependerá del orden en que estés haciendo las cosas. Si ya ha realizado algunas llamadas CUBLAS en estas matrículas, querrá usarlas en las matrices que ya están en la memoria de la GPU.