2016-01-06 84 views
0

我想在CUDA中做一個非常基本的例子。我想對浮動列表做一個簡單的計算。Thrust :: transform自定義函數

VH [X] * K1 + K2

目前,我想這一點,它不工作:

代碼1

#include <vector> 
#include <iostream> 
#include <thrust/transform.h> 
#include <thrust/functional.h> 
#include <thrust/host_vector.h> 
#include <thrust/device_vector.h> 

using namespace std; 
using namespace thrust; 

float k1 = 42, k2 = 7; 

int main(void) 
{ 
    vector<float> vh = { 0, 1, 2, 3, 4, 5, 6, 7 }; 
    device_vector<float> v = vh; 
    device_vector<float> v_out(v.size()); 

    thrust::transform(v.begin(), v.end(), v_out.begin(), [=] __device__(float x) { 
     return x*k1 + k2; 
    }); 

    for (size_t i = 0; i < v_out.size(); i++) 
     std::cout << v_out[i] << std::endl; 
} 

我得到一個非常惱人的lambda函數與上面的代碼錯誤,所以我試圖使用自定義函數,如下面的代碼所示:

代碼2

#include <vector> 
#include <iostream> 
#include <thrust/transform.h> 
#include <thrust/functional.h> 
#include <thrust/host_vector.h> 
#include <thrust/device_vector.h> 

using namespace std; 
using namespace thrust; 

float k1 = 42, k2 = 7; 

float multiply(float x) 
{ 
    return x * k1 + k2; 
} 

int main(void) { 
    vector<float> vh = { 0, 1, 2, 3, 4, 5, 6, 7 }; 
    device_vector<float> v = vh; 
    device_vector<float> v_out(v.size()); 
    thrust::negate<float> op; 

    thrust::transform(v.begin(), v.end(), v_out.begin(), multiply __device__(float x)); 

    for (size_t i = 0; i < v_out.size(); i++) 
     std::cout << v_out[i] << std::endl; 

    std::getwchar(); 
} 

誰能告訴我爲什麼代碼1和/或代碼2不工作?

+0

您使用的是CUDA和推力版本? – talonmies

+0

CUDA 7.5,我猜是推力1.7.0。自從我安裝CUDA後,我還沒有更新它。 – Anonymous

回答

3

對於代碼2,您必須將您的函數包裝在一個對象中以創建函數。

對於代碼1,您必須使用--expt-extended-lambda nvcc選項來啓用完整的lambda支持。

您還必須聲明​​,k2const,或者沒有使他們通過靜態(例如)宣佈它的main內。

使用仿函數來生產代碼,除非你的lambda是很簡單。

查閱下面的代碼爲一個工作示例:

#include <vector> 
#include <iostream> 
#include <thrust/transform.h> 
#include <thrust/functional.h> 
#include <thrust/host_vector.h> 
#include <thrust/device_vector.h> 

using namespace std; 
using namespace thrust; 



template<class T> 
struct saxpi{ 
    T k1; 
    T k2; 
    saxpi(T _k1, T _k2){ 
     k1=_k1; 
     k2=_k2; 
    } 
    __host__ __device__ T operator()(T &x) const{ 
     return x*k1+k2; 
    } 
}; 


int main(void) 
{ 
    float kk1=1, kk2=5; 
    vector<float> vh = { 0, 1, 2, 3, 4, 5, 6, 7 }; 
    device_vector<float> v = vh; 
    device_vector<float> v_out(v.size()); 
    cout<<"Lambda:"<<endl; 
    auto ff = [=] __device__ (float x) {return kk1*x +kk2;}; 

    thrust::transform(v.begin(),v.end(),v_out.begin(),ff); 

    for (size_t i = 0; i < v_out.size(); i++) 
     std::cout << v_out[i] << std::endl; 

    cout<<"Functor:"<<endl; 
    saxpi<float> f(kk1,kk2); 
    v_out.clear(); 
    v_out.resize(v.size()); 
    thrust::transform(v.begin(),v.end(),v_out.begin(),f); 


    for (size_t i = 0; i < v_out.size(); i++) 
      std::cout << v_out[i] << std::endl; 

} 

使用下列選項編譯:--expt擴展 - 拉姆達-std = C++ 11

Lambda: 
5 
6 
7 
8 
9 
10 
11 
12 
Functor: 
5 
6 
7 
8 
9 
10 
11 
12 
+0

非常感謝!你能解釋__host__ __device__和__device__之間的區別嗎? – Anonymous

+0

** __ host__ __device __ **不過是一次寫入函數的簡寫,並告訴編譯器生成兩個版本的相同代碼:它爲CPU端生成x86彙編,爲GPU生成PTX。 –