一種可能的方法是使用thrust。
一個可能的序列將是這樣的:
- 使用 thrust::reduce_by_key 以產生用於每個範圍的最大值。
- 使用thrust :: adjacent_difference描繪每個範圍的起始點
- 對步驟2的結果使用包含式掃描來生成聚集索引,即將用於選擇縮小值的索引(來自步驟1)將會出現在輸出向量的每個位置。
- 使用thrust::gather_if使用步驟3中生成的聚集索引,選擇性地將縮小的值放置到輸出向量中的適當位置(B向量中存在1)。
這裏的一個充分的工作代碼演示此,使用像您的示例A和B載體:
關於示例
#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/adjacent_difference.h>
#include <thrust/reduce.h>
#include <thrust/copy.h>
#include <thrust/transform_scan.h>
#include <thrust/iterator/discard_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/functional.h>
#define DSIZE 8
template <typename T>
struct abs_val : public thrust::unary_function<T, T>
{
__host__ __device__
T operator()(const T& x) const
{
if (x<0) return -x;
else return x;
}
};
template <typename T>
struct subtr : public thrust::unary_function<T, T>
{
const T val;
subtr(T _val): val(_val) {}
__host__ __device__
T operator()(const T& x) const
{
return x-val;
}
};
int main(){
int A[DSIZE] = {45,21,764,234,7,0,12,55};
int B[DSIZE] = {1,1,1,0,1,1,0,0};
thrust::device_vector<int> dA(A, A+DSIZE);
thrust::device_vector<int> dB(B, B+DSIZE);
thrust::device_vector<int> dRed(DSIZE);
thrust::device_vector<int> diffB(DSIZE);
thrust::device_vector<int> dRes(DSIZE);
thrust::reduce_by_key(dB.begin(), dB.end(), dA.begin(), thrust::make_discard_iterator(), dRed.begin(), thrust::equal_to<int>(), thrust::maximum<int>());
thrust::adjacent_difference(dB.begin(), dB.end(), diffB.begin());
thrust::transform_inclusive_scan(diffB.begin(), diffB.end(), diffB.begin(), abs_val<int>(), thrust::plus<int>());
thrust::gather_if(thrust::make_transform_iterator(diffB.begin(), subtr<int>(B[0])), thrust::make_transform_iterator(diffB.end(), subtr<int>(B[0])), dB.begin(), dRed.begin(), dRes.begin());
thrust::copy(dRes.begin(), dRes.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
注:
- reduce_by_key正在產生降低的值(最大值),用於每個 連續的0序列或 B中的1個序列。您只需真正需要 這1個序列的最大值。我們將通過gather_if函數丟棄最大值爲0的序列 。
- 我允許該B載體可以與任一 1個序列或0的序列開始,通過使用transform_iterator 處理步驟2的矢量結果,減去從每個B載體的第一 值的可能性收集索引。
- adjacent_difference操作將產生1或-1到 劃定新序列的開始。爲了掃描目的(即生成聚集索引),我使用帶有abs_val函子的變換包含變換函數variant_inclusive_scan來平等對待它們。
上面的代碼應該產生的結果符合期望C
輸出向量,就像這樣:
$ nvcc -arch=sm_20 -o t53 t53.cu
$ ./t53
764 764 764 0 7 7 0 0
$
我們可以使用thrust::placeholders進一步簡化上面的代碼,省去了多餘的仿函數定義的需要:
#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/adjacent_difference.h>
#include <thrust/reduce.h>
#include <thrust/copy.h>
#include <thrust/transform_scan.h>
#include <thrust/iterator/discard_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/functional.h>
#define DSIZE 2000000
using namespace thrust::placeholders;
typedef int mytype;
int main(){
mytype *A = (mytype *)malloc(DSIZE*sizeof(mytype));
int *B = (int *)malloc(DSIZE*sizeof(int));
for (int i = 0; i < DSIZE; i++){
A[i] = (rand()/(float)RAND_MAX)*10.0f;
B[i] = rand()%2;}
thrust::device_vector<mytype> dA(A, A+DSIZE);
thrust::device_vector<int> dB(B, B+DSIZE);
thrust::device_vector<mytype> dRed(DSIZE);
thrust::device_vector<int> diffB(DSIZE);
thrust::device_vector<mytype> dRes(DSIZE);
cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start);
thrust::reduce_by_key(dB.begin(), dB.end(), dA.begin(), thrust::make_discard_iterator(), dRed.begin(), thrust::equal_to<mytype>(), thrust::maximum<mytype>());
thrust::adjacent_difference(dB.begin(), dB.end(), diffB.begin());
thrust::transform_inclusive_scan(diffB.begin(), diffB.end(), diffB.begin(), _1*_1, thrust::plus<int>());
thrust::gather_if(thrust::make_transform_iterator(diffB.begin(), _1 - B[0]), thrust::make_transform_iterator(diffB.end(), _1 - B[0]), dB.begin(), dRed.begin(), dRes.begin());
cudaEventRecord(stop);
cudaEventSynchronize(stop);
float et;
cudaEventElapsedTime(&et, start, stop);
std::cout<< "elapsed time: " << et << "ms " << std::endl;
thrust::copy(dRes.begin(), dRes.begin()+10, std::ostream_iterator<mytype>(std::cout, " "));
std::cout << std::endl;
return 0;
}
(I已經修改了上述佔位符代碼還包括生成一個較大尺寸的數據集的,以及一些基本定時APPA鼠標)
您可以使用[thrust](https://github.com/thrust/thrust/wiki/Quick-Start-Guide)函數[reduce_by_key](http://thrust.github.io/doc /group__reductions.html#ga1fd25c0e5e4cc0a6ab0dcb1f7f13a2ad)來幫助解決這個問題。 – 2014-09-01 12:07:25
這將有助於找到區域的最大值,但是我是不是仍然會丟失我的位置,或者不得不基本遍歷整個陣列來填充區域不平行的區域 – user2719805 2014-09-01 13:27:24
是的,我沒有暗示這是一個完整的解決方案。我已經添加了一個答案,說明如何在完整的解決方案中使用它。 – 2014-09-01 15:02:07