2 Stimmen

Iterator für den Vektor der Strukturen in der Schubkraft

Ich versuche, auf folgende Weise Zugriff auf Vektorelemente zu erhalten

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 wurde ordnungsgemäß initialisiert. Ich erhalte folgende Fehler:

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

Was mache ich falsch?

6voto

jopasserat Punkte 5524

Ok, das war ein bisschen komplizierter als ich erwartet hatte :)
Hier sind die Ergebnisse meiner Untersuchungen:

Ihr Problem liegt in der Umsetzung von Thrust. Thrust verwendet einen Typ namens device_reference die, wie es in der Dokumentation heißt: http://wiki.thrust.googlecode.com/hg/html/classthrust_1_1device__reference.html

device_reference fungiert als referenzähnliches Objekt auf ein Objekt das im Gerätespeicher gespeichert ist. device_reference ist nicht dazu bestimmt direkt verwendet werden; vielmehr ist dieser Typ das Ergebnis der Zurückstellung einer device_ptr . Ähnlich verhält es sich, wenn man die Adresse einer device_reference ergibt sich ein device_ptr .

Es gibt jedoch einige Fälle, in denen wir es implizit mit device_reference . Wenn z.B. eine device_reference als Parameter an Funktionen übergeben wird, die auf POD warten (mehr oder weniger das, was Sie versuchen, mit operator<< ), stellt sich das folgende Problem:

Ein weiterer häufiger Fall, in dem ein device_reference nicht direkt sein anstelle des referenzierten Objekts verwendet werden tritt auf, wenn sie als Parameter übergeben werden an Funktionen wie printf die über varargs-Parameter haben. Da varargs Parameter Plain Old Data sein müssen, muss ein device_reference zu einem POD-Typ erfordert einen Cast wenn sie an printf übergeben wird:

Alles, was Sie tun müssen, ist, Ihre device_reference zu dem POD, den Sie bearbeiten. In Ihrem Fall würden Sie das tun:

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

Meiner Meinung nach ist dies nicht die eleganteste Lösung, ich würde lieber die std::copy Algorithmus zum Drucken des Inhalts Ihrer point Klasse. Deshalb habe ich eine kleine Beispieldatei geschrieben, die Ihre point Klasse und druckt sie auf drei verschiedene Arten aus:

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

Nun liegt es an Ihnen, sich für eine davon zu entscheiden!

3voto

Armen Tsirunyan Punkte 125469
std::cout << iter->x << " " << iter->y << " " << std::endl; 
                                      ^^^^

:))

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X