2015-10-05 71 views
0

將矩陣A和向量x相乘得到結果y之後,我想將函數h元素地應用於y。cuda函數在cuda中的元素應用

我想獲得z = h(A x),其中h是元素方向應用於矢量A x。

我知道如何在GPU上進行矩陣/向量乘法(與cublas)。現在我想要h(這是我自己的函數,用C++編碼)應用於GPU中的合成向量,我該怎麼做?

回答

4

兩種可能的方法是:

  1. 寫自己的CUDA內核來執行操作
  2. 使用thrust(例如thrust::for_each())。

下面是兩種方法的工作例如:

$ cat t934.cu 
#include <iostream> 
#include <thrust/host_vector.h> 
#include <thrust/device_vector.h> 
#include <thrust/copy.h> 
#include <thrust/for_each.h> 

#define DSIZE 4 

#define nTPB 256 

template <typename T> 
__host__ __device__ T myfunc(T &d){ 

    return d + 5; // define your own function here 
} 

struct mytfunc 
{ 
template <typename T> 
__host__ __device__ 
void operator()(T &d){ 

    d = myfunc(d); 
    } 
}; 

template <typename T> 
__global__ void mykernel(T *dvec, size_t dsize){ 

    int idx = threadIdx.x+blockDim.x*blockIdx.x; 
    if (idx < dsize) dvec[idx] = myfunc(dvec[idx]); 
} 

int main(){ 

    // first using kernel 
    float *h_data, *d_data; 
    h_data = new float[DSIZE]; 
    cudaMalloc(&d_data, DSIZE*sizeof(float)); 
    for (int i = 0; i < DSIZE; i++) h_data[i] = i; 
    cudaMemcpy(d_data, h_data, DSIZE*sizeof(float), cudaMemcpyHostToDevice); 
    mykernel<<<(DSIZE+nTPB-1)/nTPB,nTPB>>>(d_data, DSIZE); 
    cudaMemcpy(h_data, d_data, DSIZE*sizeof(float), cudaMemcpyDeviceToHost); 
    for (int i = 0; i < DSIZE; i++) std::cout << h_data[i] << ","; 
    std::cout << std::endl; 

    // then using thrust 
    thrust::host_vector<float> hvec(h_data, h_data+DSIZE); 
    thrust::device_vector<float> dvec = hvec; 
    thrust::for_each(dvec.begin(), dvec.end(), mytfunc()); 
    thrust::copy_n(dvec.begin(), DSIZE, std::ostream_iterator<float>(std::cout, ",")); 
    std::cout << std::endl; 
} 

$ nvcc -o t934 t934.cu 
$ ./t934 
5,6,7,8, 
10,11,12,13, 
$ 

注意的是,爲了提供一個完整的例子,我開始在主機內存中的向量定義。如果你已經在設備內存中使用矢量(也許是計算y = Ax的結果),那麼你可以直接使用該矢量,將該矢量傳遞給CUDA內核,或直接在推力函數中使用它,使用thrust::device_ptr包裝(此方法在先前鏈接的推力快速入門指南中已有介紹。)

我在這裏所做的假設是您想要使用一個變量的任意函數。這應該可以處理在myfunc中定義的幾乎任意的函數。但是,對於您可能感興趣的某些功能類別,您可能也可以實現一個或多個CUBLAS呼叫。

+0

非常感謝羅伯特。後面兩個問題:這兩種方法之間的效率是否有差別(就執行速度而言,其中一個更可取?)?並使用g ++進行編譯,或者它是否需要放在.cu文件中並由nvcc編譯。事實上,即使是用g ++編譯推力介紹的簡單例子(cuda 7.0.0) –

+0

推測,在瞄準CUDA後端時,需要用nvcc編譯,你應該把這些推力代碼放在一個.cu文件。就我所表明的例子而言,兩種方法的效率差別不大。該算法將由內存訪問控制,這兩種方法都是相同的。 –

+0

謝謝羅伯特。如果我再打擾你一次,說我的同樣的問題,我想計算y = h(A * x),並且我必須得到許多向量x,而不改變矩陣A和函數h。你能否證實一旦矩陣A被創建,它將在不同的x陣列的不同內核調用之間持續在GPU內存中? –