итератор для вектора структур в тяге

Я пытаюсь получить доступ к векторным элементам таким образом

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 был правильно инициализирован. Я получаю следующие ошибки:

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]"

Что я делаю не так?


person qutron    schedule 05.07.2011    source источник


Ответы (2)


Хорошо, это было немного сложнее, чем я ожидал :)
Вот результаты моих исследований:

Ваша проблема связана с реализацией тяги. Thrust использует тип device_reference, который, как указано в его документации: http://wiki. Thrust.googlecode.com/hg/html/classthrustdevice_reference1device__reference.html

device_reference действует как ссылка на объект, хранящийся в памяти устройства. device_reference не предназначен для прямого использования; скорее, этот тип является результатом присвоения device_ptr. Точно так же, взяв адрес device_reference, мы получим device_ptr.

Однако бывают случаи, когда мы неявно имеем дело с device_reference. Например, когда device_reference передается в качестве параметра функциям, ожидающим POD (более или менее то, что вы пытаетесь сделать с operator<<), возникает следующая проблема:

Другой распространенный случай, когда device_reference нельзя использовать напрямую вместо референтного объекта, возникает при передаче их в качестве параметров функциям, таким как printf, которые имеют параметры с переменным числом аргументов. Поскольку параметры varargs должны быть обычными старыми данными, device_reference в тип POD требует приведения при передаче в 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 для печати содержимого вашего класса point. Таким образом, я написал небольшой пример файла, используя ваш класс point и распечатав его тремя разными способами:

#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;
}

Теперь вам решать, какой из них вам больше по душе!

person jopasserat    schedule 06.07.2011
comment
К сожалению, это не помогает. - person qutron; 06.07.2011
comment
@qutron: я разобрался с твоей проблемой! Проверьте мой ответ еще раз. Это должно работать для вас сейчас. - person jopasserat; 07.07.2011

person    schedule
comment
@qutrun: Что еще мы не знаем? - person Armen Tsirunyan; 05.07.2011
comment
Ничего интересного. hPoints — это host_vector. Он был правильно инициализирован и отлично работает с этим подходом. Я обнаружил, что типы контейнеров в Thrust ограничены фундаментальными типами. Возможно, мои ошибки связаны с этим. - person qutron; 05.07.2011