在推力结构向量的迭代器 [英] iterator for vector of structures in thrust
问题描述
我试图以这种方式访问向量元素
结构点
{
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实例化期间检测到
我做错了什么?
确定这个比我想象的要复杂一些)
这是我的调查结果: 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 <-c
)时,会出现以下问题:
另一个常见的情况是,
device_reference
b $ b用于替换其引用对象
,当将它们作为参数
传递给具有
varargs参数的printf
的函数时,会出现b $ b。因为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;
无符号整数;
};
__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);
//复制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 adevice_ptr
. Similarly, taking the address of adevice_reference
yields adevice_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 withoperator<<
), 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 likeprintf
which have varargs parameters. Because varargs parameters must be Plain Old Data, adevice_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 yourpoint
class. Thus, I've written a small example file, using yourpoint
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屋!