Schlitzauge Geschrieben 27. September 2011 Teilen Geschrieben 27. September 2011 Hi COM, ich arbeite mich gerade in die CUDA-Programmierung ein, wollte aber gefundene Beispiele erstmal als Single-Prog-Lösung umsetzen und mich dann nach und nach an die Parallel- und GPGPU-Umsetzung heranwagen. Doch da steh ich gerade bei nem Beispiel, genauer gesagt der Vektoraddition, auf n Schlauch. Für mich sollte ein Beispiel wenigstens Ansatzweise einen Sinn ergeben. Es ist so: Als Vorlage dient der vecadd-Sourcecode aus den CUDA-SDK-Beispielen. Doch ich verstehe da nicht den Sinn dahinter, was dieses Prog dann tun soll. In der Vecadd-Funktion wird z.B. lediglich folgende Rechnung ausgeführt: void VecAdd(float *A,float *B,float *C) { C[i] = A[i] + B[i]; } Ähnliche Beispiele kenn ich auch aus dem OpenMP-Umfeld. Wofür da eine Extra-Funktion herhalten muss, wo es doch auch eine simple Schleife machen würde, ergibt für mich einfach keinen Sinn. Klar, bei CUDA benötigt der Feine Herr NVCC extra CU-Kernel (Funktionen), darum wohl auch die Auslagerung in extra Funktion, aber wie gesagt, kenn ich das VecAdd-Beispiel auch von der CPU-Programmierung her. Wo mein Problem jetzt darin liegt, ist der Anwendungszweck. Geht es hier wirklich nur um das Berechnen von EINDIMENSIONALEN Vektoren, also quasi stink normalen Zahlen, etwa wie im Beispiel oben, zu C? Oder tu ich da was verwechseln? Es ist so, dass ich, wenn ich an Vektoren denke, in erster Linie an zweidimensionale Vektoren (x,y) bzw. an dreidimensionale Vektoren (x,y,z) denke. Eindimensional (x) ist für mich normales Rechnen mit Werten bzw. Variablen. Von daher ergibt sich für mich nicht der Sinn dieses VecAdd-Beispiels. Geht es da wirklich nur um so etwas Essentielles wie das Addieren normaler Zahlen auf eindimensionaler Ebene oder hab ich da was übersehen und die VecAdd-Funktion ist auch für zweidimensionale bzw. n-dimensionale Vektoren bestimmt? Hier im Großen und Ganzen das Programm als Single-CPU-Version: void VecAdd(float *A,float *B,float *C, int N) { for(int i = 0; i<N; i++) { C = A[i] + B[i]; } } int main() { int N = 50000; h_A = (float *)malloc(N*sizeof(float)); h_B = (float *)malloc(N*sizeof(float)); h_C = (float *)malloc(sizeof(float)); VecAdd(h_A,h_B,h_C,N); free(h_A); free(h_; free(h_C); return 0; }[/code] Das Einzige was mir dazu einfallen würde, wäre ne Teilrechnung auf jeweils nur eine Art Objekt eines mehrdimensionalen Vektors, sprich: Addieren aller X-Werte von n Vektoren zu nur dem X-Wert eines Ergebnis-Vektor´s C z.B.. Dann würde die Funktion auch wieder einen logischeren Nutzen ergeben, da man diese Funktion z.B. bei dreidimensionalen Vektoren (x,y,z) einfach nur drei mal aufrufen müsste, jeweils für x, für y und für z. Persönlich würde ich das Ganze dann natürlich einfacher händeln, nämlich mit eigener Vektor-Klasse und mit Operatorüberladung. Aber wie gesagt, stehe ich derzeit aufn Schlauch den Sinn des Beispiels zu verstehen. Denke ich denn zu anspruchsvoll, als es das Beispiel hergibt? Besten Dank, Grüße Schlitzauge :):) Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
flashpixx Geschrieben 27. September 2011 Teilen Geschrieben 27. September 2011 (bearbeitet) Ich helf Dir mal mit nem kleinen Tip auf die Sprünge: Du hast zwei 3-dimensionale Vektoren, dann sieht die Vektoraddition mit Schleife so aus: for(i=0; i < 3; ++i) target[i] = source1[i] + source2[i] Cuda oder auch OpenMP sind Strukturen um parallel zu arbeiten und jetzt überleg' Dir einmal, ob das 0te Element bei der Addition eine Abhängigkeit zu dem 1. oder 2. hat. Also kannst Du das 0te Element unabhängig von der 1. oder 2. berechnen? Zu der Frage nach der "Funktion", schau Dir dafür die Piplinetechnologie der Graphikkarte an und überlege Dir, wie dann Dein real geschriebener Code auf der Karte ausgeführt wird. Zu weiteren Frage der Berechnung von Skalaren, so heißen Deine eindimensionalen Vektoren. Wieso muss man einen Vektor als n-dimensionale topologische Struktur auffassen, evtl kann man doch einfach einen Vektor als "Menge von Zahlen" auffassen, die man zu einer anderen Menge addieren will !? Bearbeitet 27. September 2011 von flashpixx Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Schlitzauge Geschrieben 28. September 2011 Autor Teilen Geschrieben 28. September 2011 Eindimensionaler Vektor = Skalar = Zahl, das ist mir schon klar und bekannt. Um mal Missverständnisse zu vermeiden: Du hast zwei 3-dimensionale Vektoren, dann sieht die Vektoraddition mit Schleife so aus: for(i=0; i < 3; ++i) target[i] = source1[i] + source2[i] Deine dreidimensionalen Vektoren sind also zwei normale Arrays von je 3 Elementen (x,y,z)? Will man also eine Vektoraddition von zwei dreidimensionalen Vektoren durchführen (X1+X2,Y1+Y2,Z1+Z2), muss man die Funktion also drei mal anwenden, einmal für die X-Addition, einmal für die Y-Addition und einmal für die Z-Addition. Bzw. das Ganze zu einer Schleife von drei Iterationen vereinfachen (beim Beispiel von 3D-Vektoren, ansonsten n Iterationen bei nD-Vektoren). Dann lag ich doch nicht so verkehrt, dass mit der Funktion lediglich Skalare summiert werden. Als Schleife wird dann halt durch die n-Dimensionen des übergebenen Vektors (Array mit (n * Anzahl Dimensionen) Elemente) iteriert. Gut, dann ergibt das Ganze schon einen Sinn. Das der Ablauf bei OpenMP und CUDA aufgrund der Parallelität etwas anders ist, ist mir schon bewusst. Mir gings aber erstmal darum eine Single-Prozess/Thread-Lösung zu implementieren. Zu weiteren Frage der Berechnung von Skalaren, so heißen Deine eindimensionalen Vektoren. Wieso muss man einen Vektor als n-dimensionale topologische Struktur auffassen, evtl kann man doch einfach einen Vektor als "Menge von Zahlen" auffassen, die man zu einer anderen Menge addieren will !? Weil wir hier im Umkreis das so halt gelernt haben. Vorher war stets nur die Rede von "Zahlen" (1D). Bis zur "Vektorrechnung" als Fachspezifisches Teilgebiet der Mathematik, wurden 2D-Vektoren lediglich als "Koordinaten" (X,Y) bezeichnet (Stichwort: KUDI). Den Begriff "Vektoren" als solches, haben wir lediglich im Zusammenhang mit Räumlichkeiten kennengelernt, also 3D (X,Y,Z). Ebenso haben wir auch nur ausschließlich mit 3D-Vektoren gerechnet (+,-,*,etc.). Deshalb würde ich persönlich die VecAdd-Funktion so implementieren, dass als Referenz zwei Vektor-Objekte (eigene Klasse, welche X,Y und Z auffasst) übergeben und zu einem Ergebnis-Vektor summiert werden. Besser noch, würde ich das gleich als Operatorüberladung der Vektor-Klasse implementieren. Da würde der Code etwas anders ausschauen. Gleiches gilt dann natürlich auch für nD-Vektoren. Tja, so kommen Missverständnisse auf. Jetzt wird mir aber einiges klarer. THX nochmal. :D:D:D Eine nebenläufige Frage hättsch ma noch. Wie kann man statt Arrays (Vektoren) das Ganze mit std::vector implementieren? Oder was würdet Ihr überhaupt empfehlen, Arrays (statisch oder dynamisch) oder std:vector? Wie würde der Zugriff (lesend/schreibend) auf einem std::vector aussehen? Hab mich zwar schon belesen, aber finde so gut wie nur Beispiele und Tut´s für normale std:vector´s, nicht für mehrdimensionale oder ineinander verschachtelte. Ich würde gerne folgendes machen: Ein std::vector "BASE" mit 3 Elementen (z.B. weil das Objekt dann ein 3D-Vektor mit X,Y und Z, darstellen soll). Diesen BASE-std:vector würde ich jetzt noch gerne n-mal für n-viele Vektoren anlegen, ebenfalls wieder als std:vector, nennen wir ihn einfach mal ARRAYofBASEVEKTOREN. Der VecADD-Funktion soll dann wahlweise nur zwei std::Vektoren oder gleich ein ganzes std::vector-Array übergeben werden können. Ist es denn sinnvoller von einem std::vector-Objekt selbst nochmal ein std::vector-Objekt (std::vector-Array) anzulegen (insofern das möglich ist) oder dafür statt ein normales C-Array mit std::vector´en (insofern auch das möglich sein sollte)? Betrachtet soll jetzt primär erstmal das Ganze als Single-Prozess-Variante. Mich würde es aber auch mal interessieren, inwieweit man std::vector´en bei OpenMP und CUDA (ab v3.0) einsetzen sollte, Zwecks Thread-Sicherheit. STL-Objekte- und STL-Funktionen sollen ja nicht threadsicher sein (z.B. ostream mit cout) und der std:vector gehört da ja wohl eindeutig auch dazu oder spielt das da keine Rolle? Besten Dank und Grüße Schlitzauge :):) Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
flashpixx Geschrieben 28. September 2011 Teilen Geschrieben 28. September 2011 Weil wir hier im Umkreis das so halt gelernt haben. Vorher war stets nur die Rede von "Zahlen" (1D). Bis zur "Vektorrechnung" als Fachspezifisches Teilgebiet der Mathematik, wurden 2D-Vektoren lediglich als "Koordinaten" (X,Y) bezeichnet (Stichwort: KUDI). Den Begriff "Vektoren" als solches, haben wir lediglich im Zusammenhang mit Räumlichkeiten kennengelernt, also 3D (X,Y,Z). Ebenso haben wir auch nur ausschließlich mit 3D-Vektoren gerechnet (+,-,*,etc.). Du gehst hier anscheinend immer von dem klassischen Kartesisches Koordinatensystem aus. Ich verweise einmal auf Geodätische Distanz so dass man eben einen Vektor als "Struktur von Zahlen" auffassen kann. D.h. wenn Du z.B. Punkte auf einer Sphäre beschreibst, dann wäre das ein Vektor mit zwei Dimensionen nämlich die Winkel (ggf. drei Dimensionen, wenn Du noch einen Radius hast). Da einfach mit Addition, Multiplikation zu arbeiten würde fatal enden :-P Deshalb würde ich persönlich die VecAdd-Funktion so implementieren, dass als Referenz zwei Vektor-Objekte (eigene Klasse, welche X,Y und Z auffasst) übergeben und zu einem Ergebnis-Vektor summiert werden. Besser noch, würde ich das gleich als Operatorüberladung der Vektor-Klasse implementieren. Da würde der Code etwas anders ausschauen. Gleiches gilt dann natürlich auch für nD-Vektoren. Das ist ja eigentlich auch der gängige Fall es so zu machen. Wie kann man statt Arrays (Vektoren) das Ganze mit std::vector implementieren? Oder was würdet Ihr überhaupt empfehlen, Arrays (statisch oder dynamisch) oder std:vector? Wie würde der Zugriff (lesend/schreibend) auf einem std::vector aussehen? Die Frage wäre, ob man einen std::vector braucht. Da die Dimension meist konstant ist, kann man das Allokieren des Speichers auch selbst machen und würde sich die ganze std::vector Struktur spare. Ich nutze generell Boost Basic Linear Algebra - Boost 1.47.0 denn gerade wenn man sparse / dünnbesetzte Strukturen braucht bietet die Boost schon alles fertig. Ebenso lassen sich die Automatically Tuned Linear Algebra Software und LAPACK direkt an die Boost Datenstrukturen anbinden. Zugriff auf die Vektoren / Matrizen geschieht einfach per []-Operator bzw ()-Operator. Ich würde gerne folgendes machen: Ein std::vector "BASE" mit 3 Elementen (z.B. weil das Objekt dann ein 3D-Vektor mit X,Y und Z, darstellen soll). Diesen BASE-std:vector würde ich jetzt noch gerne n-mal für n-viele Vektoren anlegen, ebenfalls wieder als std:vector, nennen wir ihn einfach mal ARRAYofBASEVEKTOREN. Der VecADD-Funktion soll dann wahlweise nur zwei std::Vektoren oder gleich ein ganzes std::vector-Array übergeben werden können. Ich würde von einer eigenen Implementierung abraten, denn die Boost Strukturen sind sowohl sehr umfangreich, wie auch sehr performant. Außerdem würde man Vektoren generell als n-dimensional auffassen und nicht fest von der Dimension vorgeben. Auch würde ich hier keine Verschachtelungen machen, also eine Matrix würde ich nicht als "Vektor von Vektoren" auffassen. Wenn man diese Operatoren braucht, dann kann man durch entsprechende Methoden überladen. Mich würde es aber auch mal interessieren, inwieweit man std::vector´en bei OpenMP und CUDA (ab v3.0) einsetzen sollte, Zwecks Thread-Sicherheit. STL-Objekte- und STL-Funktionen sollen ja nicht threadsicher sein (z.B. ostream mit cout) und der std:vector gehört da ja wohl eindeutig auch dazu oder spielt das da keine Rolle? Ich benutze Chapter*24.*Thread - Boost 1.47.0 für Mutex. OpenMP unterstützt auch kritische Bereiche, so dass man das auch ohne weiteres implementieren kann (CUDA habe ich leider keine Erfahrung). Bei std::vector muss man unterscheiden, ob man eine resize Operation (push_back) macht oder nur auf Elemente lesend zugreift. Aber ein Vektor wird nicht einmal "spontan" seine Dimension ändern. Im Normalfall ist die Dimensionalität während der Berechnung konstant, so dass man recht einfach parallelisieren kann. OT: Evtl kannst Du hier einmal rein schauen Machine Learning Framework | flashpixx.de dort arbeite ich mit den genannten Strukturen. Ggf auch PM an mich wenn Fragen sind Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.