vectores punteros matrices llenar funciones con como clase arreglos c cuda fortran intel-fortran

punteros - vectores en c++ pdf



Devolver un puntero a una matriz asignada del dispositivo de C a Fortran (1)

En primer lugar, soy algo nuevo con Fortran / C / CUDA. En segundo lugar, estoy trabajando en un programa Fortran / C que realiza la multiplicación vectorial matricial en la GPU usando cuBLAS. Necesito multiplicar varios vectores (hasta 1000) con una matriz antes de tener que actualizar los contenidos de la matriz. Sin embargo, la versión actual que tengo tiene que reasignar la matriz cada vez que se envía un nuevo vector a la GPU (que es increíblemente derrochador y lento ya que la matriz no ha cambiado).

Quiero ser capaz de multiplicar la matriz con el vector sin tener que reasignar la matriz para cada vector. Una idea que invoqué fue llamar a una función C separada que asignaría la matriz a la GPU, devuelve un puntero al programa principal Fortran y luego llama a otra función C que realiza la multiplicación vectorial matricial.

Usando ISO_C_BINDING, devolví un puntero a un número de punto flotante en la variable:

type(C_PTR) :: ptr

y cuando intento pasar esto a la función C del vector matricial:

en Fortran

call cudaFunction(ptr,vector, N)

extern "C" void cudaFunction_(float *mat, float *vector, int *N)

todo se compila y se ejecuta, pero la ejecución de cublasSgemv no se ejecuta. ¿Alguna idea sobre por qué esto estaría sucediendo? He visto algunas publicaciones relacionadas pero nunca intentan enviar el puntero devuelto a C y aquí es donde (creo) estoy teniendo el problema.

¡Gracias por adelantado!


Sugeriría que no reinventes la rueda, sino que uses las fijaciones de cublas fortran que se proporcionan para este propósito.

El contenedor "thunking" no es lo que quieres. Realiza operaciones de copia implícitas según sea necesario, cada vez que utiliza una llamada de cublas en fortran.

Desea el contenedor "non-thunking", por lo que tiene control explícito sobre la copia en curso. Puede usar equivalentes Get/SetMatrix de Get/SetMatrix y Get/SetVector para copiar datos de ida y vuelta.

Hay un código de ejemplo (ejemplo B.2) que muestra cómo usar el contenedor no thunk incluido en la documentación de cublas.

Incluso si desea reinventar la rueda, el contenedor le mostrará cómo hacer que funcione la sintaxis necesaria para moverse entre C y Fortran.

En una instalación estándar de Linux CUDA, los contenedores están en /usr/local/cuda/src El contenedor no thunk es /usr/local/cuda/src/fortran.c

Aquí hay un ejemplo completamente trabajado:

cublasf.f:

program cublas_fortran_example implicit none integer i, j c helper functions integer cublas_init integer cublas_shutdown integer cublas_alloc integer cublas_free integer cublas_set_vector integer cublas_get_vector c selected blas functions double precision cublas_ddot external cublas_daxpy external cublas_dscal external cublas_dcopy double precision cublas_dnrm2 c cublas variables integer cublas_status real*8 x(30), y(30) double precision alpha, beta double precision nrm integer*8 d_x, d_y, d_alpha, d_beta, d_nrm integer*8 dsize1, dlength1, dlength2 double precision dresult write(*,*) "testing cublas fortran example" c initialize cublas library c CUBLAS_STATUS_SUCCESS=0 cublas_status = cublas_init() if (cublas_status /= 0) then write(*,*) "CUBLAS Library initialization failed" write(*,*) "cublas_status=",cublas_status stop endif c initialize data do j=1,30 x(j) = 1.0 y(j) = 2.0 enddo dsize1 = 8 dlength1 = 30 dlength2 = 1 alpha = 2.0 beta = 3.0 c allocate device storage cublas_status = cublas_alloc(dlength1, dsize1, d_x) if (cublas_status /= 0) then write(*,*) "CUBLAS device malloc failed" stop endif cublas_status = cublas_alloc(dlength1, dsize1, d_y) if (cublas_status /= 0) then write(*,*) "CUBLAS device malloc failed" stop endif cublas_status = cublas_alloc(dlength2, dsize1, d_alpha) if (cublas_status /= 0) then write(*,*) "CUBLAS device malloc failed" stop endif cublas_status = cublas_alloc(dlength2, dsize1, d_beta) if (cublas_status /= 0) then write(*,*) "CUBLAS device malloc failed" stop endif cublas_status = cublas_alloc(dlength2, dsize1, d_nrm) if (cublas_status /= 0) then write(*,*) "CUBLAS device malloc failed" stop endif c copy data from host to device cublas_status = cublas_set_vector(dlength1, dsize1, x, dlength2, > d_x, dlength2) if (cublas_status /= 0) then write(*,*) "CUBLAS copy to device failed" write(*,*) "cublas_status=",cublas_status stop endif cublas_status = cublas_set_vector(dlength1, dsize1, y, dlength2, > d_y, dlength2) if (cublas_status /= 0) then write(*,*) "CUBLAS copy to device failed" write(*,*) "cublas_status=",cublas_status stop endif dresult = cublas_ddot(dlength1, d_x, dlength2, d_y, dlength2) write(*,*) "dot product result=",dresult dresult = cublas_dnrm2(dlength1, d_x, dlength2) write(*,*) "nrm2 of x result=",dresult dresult = cublas_dnrm2(dlength1, d_y, dlength2) write(*,*) "nrm2 of y result=",dresult call cublas_daxpy(dlength1, alpha, d_x, dlength2, d_y, dlength2) cublas_status = cublas_get_vector(dlength1, dsize1, d_y, dlength2, > y, dlength2) if (cublas_status /= 0) then write(*,*) "CUBLAS copy to host failed" write(*,*) "cublas_status=",cublas_status stop endif write(*,*) "daxpy y(1) =", y(1) write(*,*) "daxpy y(30) =", y(30) call cublas_dscal(dlength1, beta, d_x, dlength2) cublas_status = cublas_get_vector(dlength1, dsize1, d_x, dlength2, > x, dlength2) if (cublas_status /= 0) then write(*,*) "CUBLAS copy to host failed" write(*,*) "cublas_status=",cublas_status stop endif write(*,*) "dscal x(1) =", x(1) write(*,*) "dscal x(30) =", x(30) call cublas_dcopy(dlength1, d_x, dlength2, d_y, dlength2) cublas_status = cublas_get_vector(dlength1, dsize1, d_y, dlength2, > y, dlength2) if (cublas_status /= 0) then write(*,*) "CUBLAS copy to host failed" write(*,*) "cublas_status=",cublas_status stop endif write(*,*) "dcopy y(1) =", y(1) write(*,*) "dcopy y(30) =", y(30) c deallocate GPU memory and exit cublas_status = cublas_free(d_x) cublas_status = cublas_free(d_y) cublas_status = cublas_free(d_alpha) cublas_status = cublas_free(d_beta) cublas_status = cublas_free(d_nrm) cublas_status = cublas_shutdown() stop end

compilar / ejecutar:

$ gfortran -c -o cublasf.o cublasf.f $ gcc -c -DCUBLAS_GFORTRAN -I/usr/local/cuda/include -I/usr/local/cuda/src -o fortran.o /usr/local/cuda/src/fortran.c $ gfortran -L/usr/local/cuda/lib64 -lcublas -o cublasf cublasf.o fortran.o $ ./cublasf testing cublas fortran example dot product result= 60.0000000000000 nrm2 of x result= 5.47722557505166 nrm2 of y result= 10.9544511501033 daxpy y(1) = 4.00000000000000 daxpy y(30) = 4.00000000000000 dscal x(1) = 3.00000000000000 dscal x(30) = 3.00000000000000 dcopy y(1) = 3.00000000000000 dcopy y(30) = 3.00000000000000 $

CUDA 5.0, RHEL 5.5