Cuda 加权推力直方图

Cuda 加权推力直方图,cuda,gpu,histogram,thrust,Cuda,Gpu,Histogram,Thrust,我想计算网格上粒子的密度。因此,我有一个包含每个粒子的细胞ID的向量,以及一个具有给定质量的向量,它不必是均匀的 我已经从asch中选取了非稀疏示例来计算粒子的直方图。 然而,为了计算密度,我需要包括每个粒子的重量,而不是简单地求每个细胞的粒子数之和,也就是说,对于满足cellID[j]=I的所有j(可能没有必要解释,因为大家都知道) 用推力实现这一点对我来说并不奏效。我还尝试使用CUDA内核和struct\u raw\u pointer\u cast,但也没有成功 编辑: 下面是一个简单的工作

我想计算网格上粒子的密度。因此,我有一个包含每个粒子的
细胞ID
的向量,以及一个具有给定
质量的向量,它不必是均匀的

我已经从
asch
中选取了非稀疏示例来计算粒子的直方图。 然而,为了计算密度,我需要包括每个粒子的重量,而不是简单地求每个细胞的粒子数之和,也就是说,对于满足
cellID[j]=I
的所有
j
(可能没有必要解释,因为大家都知道)

推力实现这一点对我来说并不奏效。我还尝试使用CUDA内核和
struct\u raw\u pointer\u cast
,但也没有成功

编辑:

下面是一个简单的工作示例,它应该通过CUDA 6.5下的
nvcc file.cu
编译,并安装了推力

#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/copy.h>
#include <thrust/binary_search.h>
#include <thrust/adjacent_difference.h>


// Predicate
struct is_out_of_bounds {
    __host__ __device__ bool operator()(int i) {

        return (i < 0); // out of bounds elements have negative id;
    }
};



// cf.: https://code.google.com/p/thrust/source/browse/examples/histogram.cu, but modified
template<typename T1, typename T2>
void computeHistogram(const T1& input, T2& histogram) {
    typedef typename T1::value_type ValueType; // input value type
    typedef typename T2::value_type IndexType; // histogram index type

    // copy input data (could be skipped if input is allowed to be modified)
    thrust::device_vector<ValueType> data(input);

    // sort data to bring equal elements together
    thrust::sort(data.begin(), data.end());


    // there are elements that we don't want to count, those have ID -1;
    data.erase(thrust::remove_if(data.begin(), data.end(), is_out_of_bounds()),data.end());



    // number of histogram bins is equal to the maximum value plus one
    IndexType num_bins = histogram.size();

    // find the end of each bin of values
    thrust::counting_iterator<IndexType> search_begin(0);
    thrust::upper_bound(data.begin(), data.end(), search_begin,
            search_begin + num_bins, histogram.begin());

    // compute the histogram by taking differences of the cumulative histogram
    thrust::adjacent_difference(histogram.begin(), histogram.end(),
            histogram.begin());

}




int main(void) {



    thrust::device_vector<int> cellID(5);
    cellID[0] = -1; cellID[1] = 1; cellID[2] = 0; cellID[3] = 2; cellID[4]=1;
    thrust::device_vector<float> mass(5);
    mass[0] = .5; mass[1] = 1.0; mass[2] = 2.0; mass[3] = 3.0; mass[4] = 4.0;

    thrust::device_vector<int> histogram(3);
    thrust::device_vector<float> density(3);


    computeHistogram(cellID,histogram);

    std::cout<<"\nHistogram:\n";

    thrust::copy(histogram.begin(), histogram.end(),
                    std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
    // this will print: " Histogram 1 2 1 " 
    // meaning one element with ID 0, two elements with ID 1 
    // and one element with ID 2

    /* here is what I am unable to implement:
     *
     *
     * computeDensity(cellID,mass,density);
     *
     * print(density):        2.0 5.0 3.0
     *
     *
     */
}
#包括
#包括
#包括
#包括
#包括
//谓词
结构是超出界限的{
__主机设备布尔运算符()(int i){
return(i<0);//越界元素具有负id;
}
};
//参见:https://code.google.com/p/thrust/source/browse/examples/histogram.cu,但已修改
样板
无效计算直方图(常数T1和输入,T2和直方图){
typedef typename T1::value_type ValueType;//输入值类型
typedef typename T2::value_type IndexType;//直方图索引类型
//复制输入数据(如果允许修改输入,则可以跳过)
推力:设备矢量数据(输入);
//对数据进行排序以将相等的元素组合在一起
推力::排序(data.begin(),data.end());
//有些元素我们不想计数,它们的ID为-1;
data.erase(推力::如果(data.begin()、data.end()、超出边界()、data.end())则删除);
//直方图箱数等于最大值加一
IndexType num_bins=直方图.size();
//查找每个值箱的末尾
推力::计数\u迭代器搜索\u开始(0);
推力::上限(data.begin(),data.end(),search\u begin,
搜索\u begin+num\u bins,histogram.begin());
//通过计算累积直方图的差值来计算直方图
推力::相邻_差(histogram.begin()、histogram.end(),
直方图(begin());
}
内部主(空){
推力::设备_向量单元(5);
cellID[0]=-1;cellID[1]=1;cellID[2]=0;cellID[3]=2;cellID[4]=1;
推力:装置_矢量质量(5);
质量[0]=0.5;质量[1]=1.0;质量[2]=2.0;质量[3]=3.0;质量[4]=4.0;
推力:设备_矢量直方图(3);
推力:装置的矢量密度(3);
计算直方图(cellID,直方图);

std::cout您在示例中描述的内容看起来不像直方图,而是分段缩减

以下示例代码用于汇总同一单元格内的粒子质量:

密度.cu

#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/reduce.h>
#include <thrust/copy.h>
#include <thrust/scatter.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\t";
    thrust::copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, "\t"));
    std::cout << std::endl << std::endl;
}

int main()
{

    const int particle_count = 5;
    const int cell_count  = 10;

    thrust::device_vector<int> cellID(particle_count);
    cellID[0] = -1; cellID[1] = 1; cellID[2] = 0; cellID[3] = 2; cellID[4]=1;
    thrust::device_vector<float> mass(particle_count);
    mass[0] = .5; mass[1] = 1.0; mass[2] = 2.0; mass[3] = 3.0; mass[4] = 4.0;

    std::cout << "input data" << std::endl;
    PRINTER(cellID);
    PRINTER(mass);

    thrust::sort_by_key(cellID. begin(), cellID.end(), mass.begin());

    std::cout << "after sort_by_key" << std::endl;
    PRINTER(cellID);
    PRINTER(mass);

    thrust::device_vector<int> reduced_cellID(particle_count);
    thrust::device_vector<float> density(particle_count);

    int new_size = thrust::reduce_by_key(cellID. begin(), cellID.end(),
                                         mass.begin(),
                                         reduced_cellID.begin(),
                                         density.begin()
                                        ).second - density.begin();                                        
    if (reduced_cellID[0] == -1)
    {
        density.erase(density.begin());
        reduced_cellID.erase(reduced_cellID.begin());
        new_size--;
    }
    density.resize(new_size);
    reduced_cellID.resize(new_size);

    std::cout << "after reduce_by_key" << std::endl;

    PRINTER(density);
    PRINTER(reduced_cellID);

    thrust::device_vector<float> final_density(cell_count);
    thrust::scatter(density.begin(), density.end(), reduced_cellID.begin(), final_density.begin());
    PRINTER(final_density);
}
输出

input data
cellID:     -1   1  0   2   1   

mass:       0.5  1  2   3   4   

after sort_by_key
cellID:     -1   0  1   1   2   

mass:       0.5  2  1   4   3   

after reduce_by_key
density:        2   5   3   

reduced_cellID: 0   1   2   

final_density:  2   5   3   0   0   0   0   0   0   0   

您在示例中描述的内容看起来不像直方图,而是分段缩减

以下示例代码用于汇总同一单元格内的粒子质量:

密度.cu

#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/reduce.h>
#include <thrust/copy.h>
#include <thrust/scatter.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\t";
    thrust::copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, "\t"));
    std::cout << std::endl << std::endl;
}

int main()
{

    const int particle_count = 5;
    const int cell_count  = 10;

    thrust::device_vector<int> cellID(particle_count);
    cellID[0] = -1; cellID[1] = 1; cellID[2] = 0; cellID[3] = 2; cellID[4]=1;
    thrust::device_vector<float> mass(particle_count);
    mass[0] = .5; mass[1] = 1.0; mass[2] = 2.0; mass[3] = 3.0; mass[4] = 4.0;

    std::cout << "input data" << std::endl;
    PRINTER(cellID);
    PRINTER(mass);

    thrust::sort_by_key(cellID. begin(), cellID.end(), mass.begin());

    std::cout << "after sort_by_key" << std::endl;
    PRINTER(cellID);
    PRINTER(mass);

    thrust::device_vector<int> reduced_cellID(particle_count);
    thrust::device_vector<float> density(particle_count);

    int new_size = thrust::reduce_by_key(cellID. begin(), cellID.end(),
                                         mass.begin(),
                                         reduced_cellID.begin(),
                                         density.begin()
                                        ).second - density.begin();                                        
    if (reduced_cellID[0] == -1)
    {
        density.erase(density.begin());
        reduced_cellID.erase(reduced_cellID.begin());
        new_size--;
    }
    density.resize(new_size);
    reduced_cellID.resize(new_size);

    std::cout << "after reduce_by_key" << std::endl;

    PRINTER(density);
    PRINTER(reduced_cellID);

    thrust::device_vector<float> final_density(cell_count);
    thrust::scatter(density.begin(), density.end(), reduced_cellID.begin(), final_density.begin());
    PRINTER(final_density);
}
输出

input data
cellID:     -1   1  0   2   1   

mass:       0.5  1  2   3   4   

after sort_by_key
cellID:     -1   0  1   1   2   

mass:       0.5  2  1   4   3   

after reduce_by_key
density:        2   5   3   

reduced_cellID: 0   1   2   

final_density:  2   5   3   0   0   0   0   0   0   0   

a) 请发布代码的a;b)同时发布示例输入数据和所需输出。我将编辑我的问题。谢谢你的建议。我正在努力理解你想要计算的内容与直方图的关系。你对问题的*非常*简短的描述听起来更像是前缀和,而不是直方图)请发布你的code;b)同时发布示例输入数据和您想要的输出。我将编辑我的问题。谢谢您的建议。我正在努力理解您想要计算的内容与直方图的关系。您对您的问题的*非常*简短的描述听起来更像是一个前缀和,而不是一个Historogram感谢您的回答!我认为这接近于我想,但是有一个问题。我想变量
密度
可能包含零值,即该单元格中没有粒子。我感觉,您的代码删除了零个条目。另外,就我的理解而言,我谈论的是直方图,我不确定我是否错了,或者您的理解有什么不同g是。谢谢!@sonystarmap:柱状图在箱子内进行计数。但是你想要的似乎是箱子内的求和。它们不一样,A不理解你关于零值的观点。如果你在求和,零值就是零irrelevant@sonystarmap如果粒子不包含在
cellID
中,则它不能包含在
reduced\u cellID 。如果您确实希望有明确的零值,您可以为不在
cellID
中的每个单元格添加它们。但是,根据您希望对该结果向量执行的操作,可能需要添加这些零值项,也可能不需要添加这些零值项。我已更新了我的问题,希望这能澄清我的问题。谢谢,这正是我一直在查找的内容我同意你的观点,所有的信息都存储在密度和简化的cellID中,但是对于进一步的计算和IO例程,我更容易假设密度总是一个固定大小的矩阵。再次感谢你的帮助!感谢你的回答!我想这接近我想要的,但是有一个p问题。我希望变量<代码>密度可能包含零值,即该单元格中没有粒子。我感觉,您的代码删除了零个条目。另外,就我的理解而言,我说的是直方图,我不确定我是否错了,或者您的理解有什么不同。谢谢!@sonystarmap:a histogram在存储箱中执行计数。但是您想要的似乎是存储箱中的求和。它们不一样,A不理解您关于零值的观点。如果要求和,则零值为ir