向量的N个最大元素及其索引

时间:2015-07-07 00:56:02

标签: c++ cuda thrust gpu-programming reduction

我有def copy_md5(source, target) chunk_size=1024 md5 = Digest::MD5.new open(target,'w') do |t| open(source) do |s| while chunk=s.read(chunk_size) md5.update chunk t.write chunk end end end md5 end 。假设thrust::device_vector <float> vecvec.size() = L。我想找到N < L中最大的N元素及其索引。我们如何使用原始CUDA或vec

有效地做到这一点

2 个答案:

答案 0 :(得分:2)

一个简单的解决方案是首先对值进行排序,然后选择最后的N元素。

以下示例从N=5值中选择L=18个最大元素及其原始索引。

使用

进行编译

nvcc -std=c++11 nlargest.cu -o nlargest

运行时输出./nlargest

d_values:   1   2   3   4   5   6   7   8   9   4   5   6   7   8   9   0   1   2   
d_indices:  0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  
d_values:   0   1   1   2   2   3   4   4   5   5   6   6   7   7   8   8   9   9   
d_indices:  15  0   16  1   17  2   3   9   4   10  5   11  6   12  7   13  8   14  
d_values_s: 7   8   8   9   9   
d_indices_s:12  7   13  8   14  

<强> nlargest.cu

#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/copy.h>
#include <thrust/sequence.h>
#include <iostream>

#define PRINTER(name) print(#name, (name))
template <template <typename...> class V, typename T, typename ...Args>
void print(const char* name, const V<T,Args...> & v)
{
    std::cout << name << ":\t";
    thrust::copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, "\t"));
    std::cout << std::endl;
}

template<typename... Iterators>
__host__ __device__
thrust::zip_iterator<thrust::tuple<Iterators...>> zip(Iterators... its)
{
    return thrust::make_zip_iterator(thrust::make_tuple(its...));
}


int main()
{

    const int size = 18;
    const int select_size = 5;

    float values[size] = {1,2,3,
                          4,5,6,
                          7,8,9,
                          4,5,6,
                          7,8,9,
                          0,1,2
    };

    thrust::host_vector<float> h_values (values, values+size);
    thrust::device_vector<float> d_values = h_values;
    thrust::device_vector<int> d_indices(size);
    thrust::sequence(d_indices.begin(), d_indices.end());

    PRINTER(d_values);
    PRINTER(d_indices);
    thrust::sort(zip(d_values.begin(), d_indices.begin()),zip(d_values.end(), d_indices.end()));
    PRINTER(d_values);
    PRINTER(d_indices);

    thrust::device_vector<float> d_values_s(select_size);
    thrust::device_vector<int> d_indices_s(select_size);

    thrust::copy(zip(d_values.end()-select_size, d_indices.end()-select_size),
                zip(d_values.end(), d_indices.end()),
                zip(d_values_s.begin(), d_indices_s.begin())
                );
    PRINTER(d_values_s);
    PRINTER(d_indices_s);

    return 0;
}

答案 1 :(得分:1)

您应该结帐this question.

我喜欢Ricky Bobby的回答(如果N远小于L)。

我也建议看下面的论文。 Fast K-selection Algorithm for Graphics Processing Units 作者:Alabi T等人

它为K选择提供了3种不同的并行算法。 他们描述的桶选择表现最佳。 该算法有两个步骤:

步骤1(预处理将原始数据拆分为大小小于2 ^ 21个元素的向量)

第2步:

1. Choose bucket containing Kth element
2. split the bucket again.
3. Repeat until the kth element is found (the min and max of the new bucket are equal).

现在你已经将其他k-1个最大的元素划分为桶。

此方法也称为分布式分区。