CUDA:获取数组中的最大值及其索引
我有几个块,每个块在整数数组的单独部分上执行。例如:块1从数组[0]到数组[9],块2从数组[10]到数组[20] 获取每个块的数组最大值索引的最佳方法是什么 示例块a[0]到a[10]具有以下值:CUDA:获取数组中的最大值及其索引,cuda,Cuda,我有几个块,每个块在整数数组的单独部分上执行。例如:块1从数组[0]到数组[9],块2从数组[10]到数组[20] 获取每个块的数组最大值索引的最佳方法是什么 示例块a[0]到a[10]具有以下值: 51023444563910 所以56是指数6的最大值 我无法使用共享内存,因为阵列的大小可能非常大。因此它不合适。有没有什么库可以让我这么快就完成 我知道约化算法,但我认为我的情况不同,因为我想得到最大元素的索引。如果我完全理解你想要的是:得到数组A的索引,其中的最大值 如果这是真的,那么我建议您
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除了使用推力的建议之外,您还可以使用CUBLAScublisamax
函数。与共享内存相比,数组的大小几乎是无关的,因为每个块中的线程数是限制因素,而不是数组的大小。一种解决方案是让每个线程块工作数组大小与线程块大小相同的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);在设备上?