在推力结构向量的迭代器 [英] iterator for vector of structures in thrust

查看:279
本文介绍了在推力结构向量的迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图以这种方式访问​​向量元素

 结构点
{
unsigned int x;
unsigned int y;
};

...
thrust :: device_vector< point> devPoints(hPoints.begin(),hPoints.end());

for(thrust :: device_vector< point> :: iterator iter = devPoints.begin(); iter!= devPoints.end(); iter ++)
{
std: :cout< iter> x<< < iter> y<< < std :: endl; (1)
}

device_vector已正确初始化。我得到以下错误:

 错误:表达式必须有指针类型(在1)
错误:定义从const thrust :: detail :: normal_iterator< thrust :: device_ptr< point>>>到thrust :: device_ptr< point>存在
在实例化Pointer thrust :: experimental :: iterator_facade 时检测到:: :: operator->()const [with Derived = thrust :: detail :: normal_iterator< thrust :: device_ptr< point>>,Pointer = thrust :: device_ptr< point> ;, Value = point,Space = thrust :: detail :: cuda_device_space_tag,Traversal = thrust :: random_access_traversal_tag,Reference = thrust :: device_reference< point>,Difference = ptrdiff_t]

我做错了什么?

解决方案

Ok这个比我想象的要复杂一些)

这是我的调查结果: p>

您的问题来自推力的实现。 Thrust使用一种名为 device_reference 的类型,它的文档说: http://wiki.thrust.googlecode.com/hg/html/classthrust_1_1device__reference.html


device_reference 充当存储在设备内存中的对象

引用对象。
device_reference 不是要直接使用
;相反,这种类型是
是引用
device_ptr 的结果。同样,使用 device_reference
地址产生
device_ptr

但是,在某些情况下,我们隐式地处理 device_reference 。例如,当device_reference作为参数传递给等待POD的函数(或多或少你正在尝试使用 operator <)时,会出现以下问题:


另一个常见的情况是,
device_reference b $ b用于替换其引用对象
,当它们作为参数
传递给具有
varargs参数的 printf 的函数时,因为varargs
参数必须是普通旧数据,所以对POD类型的
device_reference 需要转换
当传递给printf时:


说完之后,你所要做的就是把 device_reference 到你正在处理的POD。在你的情况下,你可以这样做:

  for(thrust :: device_vector< point> :: iterator iter = devPoints.begin (); iter!= devPoints.end(); iter ++){
std :: cout< (static_cast< point>(* iter))。x< < (static_cast< point>(* iter))。y< std :: endl;
}

在我看来,这不是最优雅的解决方案,使用 std :: copy 算法打印您的类的内容。因此,我写了一个小的示例文件,使用您的类并使用三种不同的方式打印:

  #include< thrust / host_vector.h> 
#include< thrust / device_vector.h>
#include< cstdlib>
#include< algorithm>
#include< iostream>

struct point
{
unsigned int x;
unsigned int y;
};

__host__
point getRandomPoint(){
point p;

p.x = rand();
p.y = rand();

return p;
}

__host__
std :: ostream&运算符<< (std :: ostream& os,const point& p){
os< [< p.x<< ;< p<< ];
return os;
}

int main(){
//使用随机点填充host_vector
thrust :: host_vector< point> hPoints(512);
thrust :: generate(hPoints.begin(),hPoints.end(),getRandomPoint);

// copy h将内容指向设备内存
thrust :: device_vector< point> devPoints(hPoints.begin(),hPoints.end());

// first way
for(thrust :: device_vector< point> :: iterator iter = devPoints.begin(); iter!= devPoints.end(); iter ++){
std :: cout<< (static_cast< point>(* iter))。x< < (static_cast< point>(* iter))。y< std :: endl;
}

//第二种方式
for(thrust :: device_vector< point> :: iterator iter = devPoints.begin(); iter!= devPoints.end(); iter ++)
{
std :: cout< * iter<< std :: endl;
}

//第三方法
std :: copy(devPoints.begin(),devPoints.end(),std :: ostream_iterator< point> cout,$));

return 0;
}

现在,由您自己决定。


I'm trying to get access to vector elements in this manner

struct point
{
    unsigned int x;
    unsigned int y;
};

...
thrust::device_vector<point> devPoints(hPoints.begin(), hPoints.end());

for(thrust::device_vector<point>::iterator iter = devPoints.begin(); iter != devPoints.end(); iter++) 
{
    std::cout << iter->x << " " << iter->y << " " << std::endl; (1)
}

device_vector was initialized properly. I get following errors:

error: expression must have pointer type (at 1)
error: no suitable user-defined conversion from "const thrust::detail::normal_iterator<thrust::device_ptr<point>>" to "thrust::device_ptr<point>" exists
          detected during instantiation of "Pointer thrust::experimental::iterator_facade<Derived, Pointer, Value, Space, Traversal, Reference, Difference>::operator->() const [with Derived=thrust::detail::normal_iterator<thrust::device_ptr<point>>, Pointer=thrust::device_ptr<point>, Value=point, Space=thrust::detail::cuda_device_space_tag, Traversal=thrust::random_access_traversal_tag, Reference=thrust::device_reference<point>, Difference=ptrdiff_t]"

What am I doing wrong?

解决方案

Ok this one was a bit more complicated than I expected :)
Here are the results of my investigations:

Your problem comes from thrust's implementation. Thrust uses a type called device_reference which, as its documentation says: http://wiki.thrust.googlecode.com/hg/html/classthrust_1_1device__reference.html

device_reference acts as a reference-like object to an object stored in device memory. device_reference is not intended to be used directly; rather, this type is the result of deferencing a device_ptr. Similarly, taking the address of a device_reference yields a device_ptr.

However, there are some cases when we are dealing implicitly with device_reference. For example, when a device_reference is passed as a parameter to functions waiting for POD (more or less what you are trying to do with operator<<), the following problem appears:

Another common case where a device_reference cannot directly be used in place of its referent object occurs when passing them as parameters to functions like printf which have varargs parameters. Because varargs parameters must be Plain Old Data, a device_reference to a POD type requires a cast when passed to printf:

Having said that, all you have to do is to cast your device_reference to the POD you're handling. In your case, you'd do:

for(thrust::device_vector<point>::iterator iter = devPoints.begin(); iter != devPoints.end(); iter++)  {
   std::cout << (static_cast<point>(*iter)).x << " " << (static_cast<point>(*iter)).y << std::endl;
}

In my opinion, this is not the most elegant solution, I'd rather use the std::copy algorithm to print the content of your point class. Thus, I've written a small example file, using your point class and printing it using three different ways:

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <cstdlib>
#include <algorithm>
#include <iostream>

struct point
{
        unsigned int x;
        unsigned int y;
};

__host__
point getRandomPoint() {
        point p;

        p.x = rand();
        p.y = rand();

        return p;
}

__host__
std::ostream& operator<< (std::ostream& os, const point& p) {
        os << "[ " << p.x << " ; " << p.y << " ]";
        return os;
}

int main() {
        // fill the host_vector with random points
        thrust::host_vector<point> hPoints(512);
        thrust::generate(hPoints.begin(), hPoints.end(), getRandomPoint);

        // copy hPoints content to device memory
        thrust::device_vector<point> devPoints(hPoints.begin(), hPoints.end());

        // first way 
        for(thrust::device_vector<point>::iterator iter = devPoints.begin(); iter != devPoints.end(); iter++)  {
                std::cout << (static_cast<point>(*iter)).x << " " << (static_cast<point>(*iter)).y << std::endl;
        }

        // second way
        for(thrust::device_vector<point>::iterator iter = devPoints.begin(); iter != devPoints.end(); iter++)
        {
                std::cout << *iter << std::endl;
        }

        // third way
        std::copy(devPoints.begin(), devPoints.end(), std::ostream_iterator< point >(std::cout, "  $  ") );

        return 0;
}

Now, it's up to you to choose the one you prefer!

这篇关于在推力结构向量的迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆