2012-09-13 2 views
3

Я пишу код для вычисления точечного произведения двух векторов, используя процедуру CUBLAS для точечного продукта, но возвращает значение в памяти хоста. Я хочу использовать точечный продукт для дальнейших вычислений только на GPGPU. Как я могу сделать значение только на GPGPU и использовать его для дальнейших вычислений без явной копии от CPU к GPGPU?Сохранение точечного продукта на GPGPU с использованием процедуры CUBLAS

ответ

4

Вы не можете, используя CUBLAS. В соответствии с ответом talonmies, начиная с CUBLAS V2 api (CUDA 4.0), возвращаемое значение может быть указателем устройства. Обратитесь к его ответу. Но если вы используете API V1, это одно значение, поэтому довольно просто передать его в качестве аргумента ядру, использующему его. — вам не нужен явный cudaMemcpy (но есть один подразумеваемый, чтобы вернуть хост стоимость).

Начиная с графических процессоров Tesla K20 и CUDA 5, вы сможете вызывать процедуры CUBLAS из ядер устройств с использованием динамического параллелизма CUDA. Это означает, что вы могли бы вызвать cublasSdot (например) изнутри функции ядра , и поэтому ваш результат будет возвращен на графический процессор.

+0

Большое спасибо ... – user1439690

+2

Отметьте, это неправда. Начиная с около CUBLAS 4.0 (или всякий раз, когда был выпущен API V2), аргумент результата может быть указателем на хост или устройство, и вызов с удовольствием сохранит результат в памяти устройства. – talonmies

+0

Спасибо за исправление. Могли бы дать мне время, чтобы отредактировать мой ответ (огромная разница в часовом поясе). :) – harrism

12

Вы можете сделать это в CUBLAS, если используете API «V2». Новый API включает в себя функцию cublasSetPointerMode, которую вы можете использовать, чтобы установить API, чтобы предположить, что все подпрограммы, возвращающие скалярное значение, будут переданы указателем устройства, а не указателем узла. Это обсуждается в разделе 2.4 последней документации CUBLAS. Например:

#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; 
} 

Использование CUBLAS_POINTER_MODE_DEVICE делает cublasDdot предположить, что result_ является указателем устройства, и нет никаких попыток сделали, чтобы скопировать результат обратно к хозяину. Обратите внимание, что это делает процедуры вроде dot асинхронными, поэтому вам может потребоваться следить за синхронизацией между устройством и хостом.