2016-06-07 90 views
0

我目前正在將代碼從本地C++傳輸到CUDA,同時使用thrust::device_vector s。現在有一個函數來計算漸變,我還需要訪問不僅當前元素,而且還訪問周圍的元素。在原來的代碼中,我寫道:計算推力梯度:: device_vector

void calc_grad(Complex *grad, const Complex *data, const int size) 
{ 
    for (int i = 1; i < size - 1; i++) { 
     grad[i] = 0.5 * (data[i + 1] - data[i - 1]); 
    } 
    grad[0] = data[1] - data[0]; 
    grad[size - 1] = data[size - 1] - data[size - 2]; 
} 

是否有可能創造推力functor了這一點,這樣我可以把它稱爲thrust::transform()?直到現在,我只能訪問一個元素,而沒有得到周圍的元素。或者無論如何,由於取決於之前和之後的因素而改變了?

的碼公式來自於matlab功能gradient,如下所示:http://se.mathworks.com/help/matlab/ref/gradient.html?requestedDomain=www.mathworks.com

+1

你真的應該花一些時間閱讀推力文檔:https://thrust.github.io/doc/group__transformations.html#gaa41d309b53fa03bf13fe35a184148400 – talonmies

+0

這個功能是不是做我的職責做什麼。還有其他類似的功能嗎? –

+0

您可以使用'adjacent_differences'計算出的連續差異來計算您喜歡的任何訂單精確度方案,包括您在此顯示的二階中心差異。 – talonmies

回答

4

Thrust::transform()可以做你的工作大部分。所有你需要做的就是將數據稍微移動一下,這樣grad[i],data[i-1]data[i+1]是對齊的。

thrust::transform(data.begin()+2, 
        data.end(), 
        data.begin(), 
        grad.begin()+1, 
        (_1 - _2) * 0.5); 

然後你可以處理邊界情況。

編輯

而且你還可以包括一個邊界的情況下變換。通過以下形式的轉換,函子Grad應該能夠通過第一個函數參數知道他正在處理的數據的索引。基於該索引,他可以從第二個函子參數(這是一個元組)中的3個元素中選擇2個,以進行正確的計算。

這裏的一切都沒有經過測試。我不確定data.begin()-1是否有效。您也可以在Complex類型上小心。

thrust::transform(
    thrust::make_counting_iterator(int(0)), 
    thrust::make_counting_iterator(int(0)) + size, 
    thrust::make_zip_iterator(
     thrust::make_tuple(
      data.begin()-1, 
      data.begin(), 
      data.begin()+1)), 
    grad.begin(), 
    Grad(size) 
); 

仿函數就是這樣的。

struct Grad { 
    int size_; 
    Grad(int s) : 
     size_(s) { 
    } 
    template<typename T, typename Tuple> 
    __host__ __device__ 
    inline T operator()(const int& idx, const Tuple& d) { 
    if (idx == 0) { 
     return d.get<2>() - d.get<1>(); 
    } else if (idx == size_ - 1) { 
     return d.get<1>() - d.get<0>(); 
    } else { 
     return 0.5 * (d.get<2>() - d.get<0>()); 
    } 
    } 
}; 
+0

邊界情況:'grad [0] = data [1] -data [0]; grad [size-1] = grad [size-1] -grad [size-2];'還有更快的方法嗎? –

+0

@arc_lupus我編輯了答案。它應該有與第一個相同的性能。 – kangshiyin