2011-04-19 301 views
4

我有几个块,每个块在整数数组的单独部分执行。举个例子:从数组[0]到数组[9]阻塞一个,从数组[10]到数组[20]阻塞两个。CUDA:获取数组中的最大值及其索引

什么是我可以在阵列的每个块的最大值的指数的最佳途径?

实施例块之一的[0]到[10]具有下列值:
5 10 2 3 4 34 56 3 9 10

所以56是在索引6.

我不能使用共享存储器,因为最大的值数组的大小可能非常大。因此它不适合。有没有任何图书馆可以让我这么快?

我知道的简化算法,但我认为我的情况是不同的,因为我想获得最大的元素的索引。

+1

只是为了理解。你在数组中有56个,你说34是最大的值。这是一个错字吗? – dubnde 2011-04-19 17:42:17

+0

你忘了提及你正在使用'CUDA'设置。 – 2011-04-19 18:39:09

回答

2

如果我的理解正是你想要的是:获取里面的最大值的数组A指数。

如果这是真的话,我会建议你使用推力库:

这里是你会怎么做:

#include <thrust/device_vector.h> 
#include <thrust/tuple.h> 
#include <thrust/reduce.h> 
#include <thrust/fill.h> 
#include <thrust/generate.h> 
#include <thrust/sort.h> 
#include <thrust/sequence.h> 
#include <thrust/copy.h> 
#include <cstdlib> 
#include <time.h> 

using namespace thrust; 

// return the biggest of two tuples 
template <class T> 
struct bigger_tuple { 
    __device__ __host__ 
    tuple<T,int> operator()(const tuple<T,int> &a, const tuple<T,int> &b) 
    { 
     if (a > b) return a; 
     else return b; 
    } 

}; 

template <class T> 
int max_index(device_vector<T>& vec) { 

    // create implicit index sequence [0, 1, 2, ...) 
    counting_iterator<int> begin(0); counting_iterator<int> end(vec.size()); 
    tuple<T,int> init(vec[0],0); 
    tuple<T,int> smallest; 

    smallest = reduce(make_zip_iterator(make_tuple(vec.begin(), begin)), make_zip_iterator(make_tuple(vec.end(), end)), 
         init, bigger_tuple<T>()); 
    return get<1>(smallest); 
} 

int main(){ 

    thrust::host_vector<int> h_vec(1024); 
    thrust::sequence(h_vec.begin(), h_vec.end()); // values = indices 

    // transfer data to the device 
    thrust::device_vector<int> d_vec = h_vec; 

    int index = max_index(d_vec); 

    std::cout << "Max index is:" << index <<std::endl; 
    std::cout << "Value is: " << h_vec[index] <<std::endl; 

    return 0; 
} 
+0

我想她问她是否可以打电话给max_index(d_vec);从内核里面?在设备上? – scatman 2011-04-20 05:40:09

0

除了建议使用推力,你也可以使用CUBLAS cublasIsamax函数。

0

相比于共享存储器的阵列的大小几乎是无关紧要的,因为线程的每个块中的数是限制因素,而不是在阵列的大小。一种解决方案是让每个线程块的大小与线程块的大小相同。也就是说,如果你有512个线程,那么块n将看着数组[n]到数组[n + 511]。每个块都会减少以找到该部分中最高的成员。然后,将每个部分的最大值返回给主机,并执行简单的线性搜索以找到整个阵列中的最高值。每次减少GPU不会将线性搜索减少512倍。根据阵列的大小,您可能希望在将数据恢复前进行更多减少。 (如果您的阵列尺寸为3 * 512^10,则可能需要对GPU执行10次减少操作,并让主机搜索其余3个数据点。)

0

有一点需要注意,最大值加索引减少是因为如果数组中存在多个相同值的最大元素,即在您的示例中,如果有2个或更多值等于56,那么返回的索引将不是唯一的并且可能不同在代码的每次运行中,因为GPU上的线程排序的时序不是确定性的。

为了解决这样的问题,你可以使用一个唯一的顺序设置指标,如线程ID + threadsperblock *块标识,否则元素的索引位置,如果这是唯一的。然后最大考验是沿着这些线路:

if(a>max_so_far || a==max_so_far && order_a>order_max_so_far) 
{ 
    max_so_far = a; 
    index_max_so_far = index_a; 
    order_max_so_far = order_a; 
} 

(索引和顺序可以是相同的变量,取决于应用程序。)

2

这将不利于原始的海报,但对于那些谁来到这个页面寻找答案我会建议使用推力已经有一个功能thrust :: max_element完全是 - 返回最大元素的索引。还提供了min_element和minmax_element函数。详情请参阅推力文档here

相关问题