Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Cuda推力获取段中的上一个元素_C++_Algorithm_Parallel Processing_Cuda_Thrust - Fatal编程技术网

C++ Cuda推力获取段中的上一个元素

C++ Cuda推力获取段中的上一个元素,c++,algorithm,parallel-processing,cuda,thrust,C++,Algorithm,Parallel Processing,Cuda,Thrust,我有一个值向量和一个键向量(表示一个段) 对于每个元素,我想知道它的前一个元素(在同一段中)。 它可以是值,也可以是原始向量中的索引,这无关紧要 因此,结果应该是(在值的情况下) 对于算法的剩余部分,您可以使用任何元素,而不是nan 也许我可以用独占分段扫描和max操作来存档它,而不是sum。 所以有两个问题: 我的方法正确吗 还有更优雅或有效的解决方案吗 可以使用以下步骤实现所需的功能: 按k排序v,以获得彼此相邻的相等键值;这必须通过stable\u sort\u by_key来完成,因为您

我有一个值向量和一个键向量(表示一个段)

对于每个元素,我想知道它的前一个元素(在同一段中)。 它可以是值,也可以是原始向量中的索引,这无关紧要

因此,结果应该是(在值的情况下)

对于算法的剩余部分,您可以使用任何元素,而不是
nan

也许我可以用独占分段扫描和
max
操作来存档它,而不是
sum
。 所以有两个问题:

  • 我的方法正确吗
  • 还有更优雅或有效的解决方案吗
    可以使用以下步骤实现所需的功能:

  • k
    排序
    v
    ,以获得彼此相邻的相等键值;这必须通过
    stable\u sort\u by_key
    来完成,因为您希望检索“previous”元素,因此必须保留具有相等键的元素之间的顺序

  • 对已排序的数据应用以下转换:

  • if(上一个元素具有相同的键)
    然后返回上一个元素的值
    其他的
    返回-1


    以下代码实现这些步骤:

    #include <cstdint>
    #include <iostream>
    
    #include <thrust/host_vector.h>
    #include <thrust/device_vector.h>  
    #include <thrust/sort.h>
    #include <thrust/transform.h>
    #include <thrust/iterator/counting_iterator.h>
    #include <thrust/iterator/zip_iterator.h>
    
    #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...));
    }
    
    template <typename IteratorType, typename Integer>
    struct prev_value
    {
        prev_value(IteratorType first) : first(first){}
    
       template <typename Tuple>
       __host__ __device__
       Integer operator()(const Tuple& t)
       {
          const auto& index = thrust::get<0>(t);
          const auto& previousValue = thrust::get<1>(t);
    
          Integer result = -1;
          const auto& currentKey = *(first+index);
          const auto& previousKey = *(first+index-1);
          if(currentKey == previousKey)
          {
              result = previousValue;
          }
    
          return result;
       }
    
       IteratorType first;
    };
    
    template <typename Integer, typename IteratorType>
    prev_value<IteratorType, Integer> make_prev_value(IteratorType first)
    {
      return prev_value<IteratorType, Integer>(first);
    }
    
    
    int main(int argc, char** argv)
    {
        using Integer = std::int32_t;
        using HostVec = thrust::host_vector<Integer>;
        using DeviceVec = thrust::device_vector<Integer>;
    
        Integer v[] = {1, 1, 1, 2, 3, 5, 6};
        Integer k[] = {0, 0, 1, 1, 0, 2, 2};
    
        Integer size = sizeof(k)/sizeof(k[0]);
    
        HostVec h_k(k, k+size);
        HostVec h_v(v, v+size);
    
        // copy data to device
        DeviceVec d_k = h_k;
        DeviceVec d_v = h_v;
    
        std::cout << "---- input data ----" << std::endl;
        PRINTER(d_k);    
        PRINTER(d_v);
    
        thrust::stable_sort_by_key(d_k.begin(), d_k.end(), d_v.begin());
        std::cout << "---- after sorting ----" << std::endl;
        PRINTER(d_k);    
        PRINTER(d_v);
    
        DeviceVec d_r(size, -1);
        auto op = make_prev_value<Integer>(d_k.begin());
        thrust::transform(zip(thrust::make_counting_iterator(Integer(1)), d_v.begin()),
                          zip(thrust::make_counting_iterator(size), d_v.end()),
                          d_r.begin()+1,
                          op);
        std::cout << "---- result ----" << std::endl;
        PRINTER(d_r);
    
        return 0;
    }
    

    如何定义
    ?您的输入数据已经排序了吗?您的细分市场通常有多大?您的输入向量有多大?键是段的id。它从0开始,没有gapsso
    [1,1,3]
    都属于由
    k=1
    指示的同一段?是的,它是同一段,但
    k=0
    ,因为
    k=1
    它是
    [1,2]
    r = [nan, 1, nan, 1, 1, nan, 5]
    
    #include <cstdint>
    #include <iostream>
    
    #include <thrust/host_vector.h>
    #include <thrust/device_vector.h>  
    #include <thrust/sort.h>
    #include <thrust/transform.h>
    #include <thrust/iterator/counting_iterator.h>
    #include <thrust/iterator/zip_iterator.h>
    
    #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...));
    }
    
    template <typename IteratorType, typename Integer>
    struct prev_value
    {
        prev_value(IteratorType first) : first(first){}
    
       template <typename Tuple>
       __host__ __device__
       Integer operator()(const Tuple& t)
       {
          const auto& index = thrust::get<0>(t);
          const auto& previousValue = thrust::get<1>(t);
    
          Integer result = -1;
          const auto& currentKey = *(first+index);
          const auto& previousKey = *(first+index-1);
          if(currentKey == previousKey)
          {
              result = previousValue;
          }
    
          return result;
       }
    
       IteratorType first;
    };
    
    template <typename Integer, typename IteratorType>
    prev_value<IteratorType, Integer> make_prev_value(IteratorType first)
    {
      return prev_value<IteratorType, Integer>(first);
    }
    
    
    int main(int argc, char** argv)
    {
        using Integer = std::int32_t;
        using HostVec = thrust::host_vector<Integer>;
        using DeviceVec = thrust::device_vector<Integer>;
    
        Integer v[] = {1, 1, 1, 2, 3, 5, 6};
        Integer k[] = {0, 0, 1, 1, 0, 2, 2};
    
        Integer size = sizeof(k)/sizeof(k[0]);
    
        HostVec h_k(k, k+size);
        HostVec h_v(v, v+size);
    
        // copy data to device
        DeviceVec d_k = h_k;
        DeviceVec d_v = h_v;
    
        std::cout << "---- input data ----" << std::endl;
        PRINTER(d_k);    
        PRINTER(d_v);
    
        thrust::stable_sort_by_key(d_k.begin(), d_k.end(), d_v.begin());
        std::cout << "---- after sorting ----" << std::endl;
        PRINTER(d_k);    
        PRINTER(d_v);
    
        DeviceVec d_r(size, -1);
        auto op = make_prev_value<Integer>(d_k.begin());
        thrust::transform(zip(thrust::make_counting_iterator(Integer(1)), d_v.begin()),
                          zip(thrust::make_counting_iterator(size), d_v.end()),
                          d_r.begin()+1,
                          op);
        std::cout << "---- result ----" << std::endl;
        PRINTER(d_r);
    
        return 0;
    }
    
    ---- input data ----
    d_k:    0   0   1   1   0   2   2   
    d_v:    1   1   1   2   3   5   6   
    ---- after sorting ----
    d_k:    0   0   0   1   1   2   2   
    d_v:    1   1   3   1   2   5   6   
    ---- result ----
    d_r:    -1  1   1   -1  1   -1  5