CUDA:获取数组中的最大值及其索引

CUDA:获取数组中的最大值及其索引,cuda,Cuda,我有几个块,每个块在整数数组的单独部分上执行。例如:块1从数组[0]到数组[9],块2从数组[10]到数组[20] 获取每个块的数组最大值索引的最佳方法是什么 示例块a[0]到a[10]具有以下值: 51023444563910 所以56是指数6的最大值 我无法使用共享内存,因为阵列的大小可能非常大。因此它不合适。有没有什么库可以让我这么快就完成 我知道约化算法,但我认为我的情况不同,因为我想得到最大元素的索引。如果我完全理解你想要的是:得到数组A的索引,其中的最大值 如果这是真的,那么我建议您

我有几个块,每个块在整数数组的单独部分上执行。例如:块1从数组[0]到数组[9],块2从数组[10]到数组[20]

获取每个块的数组最大值索引的最佳方法是什么

示例块a[0]到a[10]具有以下值:
51023444563910

所以56是指数6的最大值

我无法使用共享内存,因为阵列的大小可能非常大。因此它不合适。有没有什么库可以让我这么快就完成


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

如果我完全理解你想要的是:得到数组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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间推力;
//返回两个元组中最大的元组
模板
结构大元组{
__设备主机__
元组运算符()(常量元组&a、常量元组&b)
{
如果(a>b)返回a;
否则返回b;
} 
};
模板
int最大索引(设备向量和向量){
//创建隐式索引序列[0,1,2,…)
计数迭代器开始(0);计数迭代器结束(vec.size());
元组初始化(vec[0],0);
元组最小;
最小值=reduce(make_-zip_迭代器(make_-tuple(vec.begin(),begin)),make_-zip_迭代器(make_-tuple(vec.end(),end)),
init,biger_tuple());
返回get(最小值);
}
int main(){
推力:主机向量h向量(1024);
推力::序列(h_vec.begin(),h_vec.end());//值=索引
//将数据传输到设备
推力:设备向量d向量=h向量;
int index=最大索引(d_vec);

std::cout除了使用推力的建议之外,您还可以使用CUBLAS
cublisamax
函数。

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

进行最大值加索引缩减时需要注意的一件事是,如果数组中有多个相同的最大值元素,即在您的示例中,如果有2个或多个值等于56,则返回的索引将不是唯一的,并且在每次代码运行时可能会不同,因为f GPU上的线程顺序是不确定的

要解决此类问题,您可以使用唯一的排序索引,如threadid+threadsperblock*blockid,或者如果元素索引位置是唯一的,则使用元素索引位置

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;
}

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

这对原始海报没有好处,但对于那些来到本页寻找答案的人,我支持使用已经有函数推力的推力的建议。推力::max\u元素正是这样做的-返回最大元素的索引。还提供了min\u元素和min max\u元素函数。参见推力文档详细信息请点击此处。

我只是想了解一下。您的数组中有一个56,您说34是最大值。这是一个输入错误吗?您忘了提到您正在使用
CUDA
设置。我想她是在问她是否可以从内核内部调用max_index(d_vec);在设备上?