cuda - Retención del producto de puntos en GPGPU usando la rutina CUBLAS
dot-product (2)
Estoy escribiendo un código para calcular el producto escalar de dos vectores usando la rutina CUBLAS de producto de punto, pero devuelve el valor en la memoria del host. Quiero usar el producto de puntos para un mayor cálculo en GPGPU solamente. ¿Cómo puedo hacer que el valor resida solo en GPGPU y usarlo para realizar más cálculos sin hacer una copia explícita de la CPU a la GPGPU?
Puedes hacer esto en CUBLAS siempre que uses la API "V2". La API más nueva incluye una función cublasSetPointerMode
que puede usar para establecer que la API asuma que todas las rutinas que devuelven un valor escalar recibirán un puntero de dispositivo en lugar de un puntero de host. Esto se trata en la Sección 2.4 de la última documentación de CUBLAS. Por ejemplo:
#include <cuda_runtime.h>
#include <cublas_v2.h>
#include <stdio.h>
int main(void)
{
const int nvals = 10;
const size_t sz = sizeof(double) * (size_t)nvals;
double x[nvals], y[nvals];
double *x_, *y_, *result_;
double result=0., resulth=0.;
for(int i=0; i<nvals; i++) {
x[i] = y[i] = (double)(i)/(double)(nvals);
resulth += x[i] * y[i];
}
cublasHandle_t h;
cublasCreate(&h);
cublasSetPointerMode(h, CUBLAS_POINTER_MODE_DEVICE);
cudaMalloc( (void **)(&x_), sz);
cudaMalloc( (void **)(&y_), sz);
cudaMalloc( (void **)(&result_), sizeof(double) );
cudaMemcpy(x_, x, sz, cudaMemcpyHostToDevice);
cudaMemcpy(y_, y, sz, cudaMemcpyHostToDevice);
cublasDdot(h, nvals, x_, 1, y_, 1, result_);
cudaMemcpy(&result, result_, sizeof(double), cudaMemcpyDeviceToHost);
printf("%f %f/n", resulth, result);
return 0;
}
El uso de CUBLAS_POINTER_MODE_DEVICE
hace que cublasDdot
asuma que result_
es un puntero de dispositivo y no se intenta copiar el resultado al host. Tenga en cuenta que esto hace que las rutinas como dot
asíncronas, por lo que es posible que deba tener en cuenta la sincronización entre el dispositivo y el host.
No puedes, exactamente, usar CUBLAS. Según la respuesta de los talonmies, comenzando con CUBLAS V2 api (CUDA 4.0), el valor de retorno puede ser un puntero del dispositivo. Consulte su respuesta. Pero si está utilizando la API V1 es un valor único, por lo que es bastante trivial pasarlo como argumento a un kernel que lo usa; no necesita una cudaMemcpy
explícita (pero hay una implícita para devolver un host). valor).
Comenzando con la GPU Tesla K20 y CUDA 5, podrá llamar a las rutinas CUBLAS desde kernels de dispositivos usando el Paralelismo Dinámico CUDA. Esto significa que usted podría llamar a cublasSdot
(por ejemplo) desde dentro de una función de núcleo __global__
, y su resultado por lo tanto sería devuelto en la GPU.