0
將矩陣A和向量x相乘得到結果y之後,我想將函數h元素地應用於y。cuda函數在cuda中的元素應用
我想獲得z = h(A x),其中h是元素方向應用於矢量A x。
我知道如何在GPU上進行矩陣/向量乘法(與cublas)。現在我想要h(這是我自己的函數,用C++編碼)應用於GPU中的合成向量,我該怎麼做?
將矩陣A和向量x相乘得到結果y之後,我想將函數h元素地應用於y。cuda函數在cuda中的元素應用
我想獲得z = h(A x),其中h是元素方向應用於矢量A x。
我知道如何在GPU上進行矩陣/向量乘法(與cublas)。現在我想要h(這是我自己的函數,用C++編碼)應用於GPU中的合成向量,我該怎麼做?
兩種可能的方法是:
下面是兩種方法的工作例如:
$ 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呼叫。
非常感謝羅伯特。後面兩個問題:這兩種方法之間的效率是否有差別(就執行速度而言,其中一個更可取?)?並使用g ++進行編譯,或者它是否需要放在.cu文件中並由nvcc編譯。事實上,即使是用g ++編譯推力介紹的簡單例子(cuda 7.0.0) –
推測,在瞄準CUDA後端時,需要用nvcc編譯,你應該把這些推力代碼放在一個.cu文件。就我所表明的例子而言,兩種方法的效率差別不大。該算法將由內存訪問控制,這兩種方法都是相同的。 –
謝謝羅伯特。如果我再打擾你一次,說我的同樣的問題,我想計算y = h(A * x),並且我必須得到許多向量x,而不改變矩陣A和函數h。你能否證實一旦矩陣A被創建,它將在不同的x陣列的不同內核調用之間持續在GPU內存中? –