[CUDA] Problem 3: Sinus und Cosinus werden in C nicht ausgeführt, warum?
-
Ich übe gerade das generieren von Bitmaps über CUDA. Einfarbige Bitmaps kriege ich problemlos hin, nun wollte ich Farbverläufe generieren.
Das ist mein aktueller Code:
#include "../common/cpu_bitmap.h" #include "../common/book.h" const int DIM = 1000; __global__ void kernel( unsigned char *ptr){ int x = blockIdx.x; int y = blockIdx.y; int offset = x + y * gridDim.x; ptr[offset*4 + 0] = 255; ptr[offset*4 + 1] = 0; ptr[offset*4 + 2] = 0; ptr[offset*4 + 3] = 255; } int main ( void ) { [b] short test; test = 255; printf("%d", &test);[/b] CPUBitmap bitmap( DIM, DIM ); unsigned char *dev_bitmap; cudaMalloc ( (void**)&dev_bitmap, bitmap.image_size() ); dim3 grid(DIM, DIM); kernel<<<grid,1>>>(dev_bitmap ); cudaMemcpy( bitmap.get_ptr(), dev_bitmap, bitmap.image_size(), cudaMemcpyDeviceToHost); bitmap.display_and_exit(); cudaFree( dev_bitmap); }
Den problematischen Teil habe ich mal Fett markiert.
Im Grunde sollte es ganz einfach sein. Beim laufzeitstart definiert er ein Float. Dann gibt er die Zahl 255 in den Float und dann soll er die ausgeben.
Aber anstatt 255 gibt er Zahlen wie 3340368 aus.
Ich habe aktuell keinen Plan wo das herkommen kann. Jemand ne Idee? Zumal die Zahlen aj auch varrieren...
-
Du gibst die Adresse der Variablen test aus, nicht deren Wert.
-
Ah ok, das war jetzt echt dumm von mir.
Ok weiter gehts im Thema, nun will ich eine Formel aufbauen welche die 255 mögliche Farben in die 1000 einzelne Pixel aufteilt.
Gedacht ist das so:
test = (255 / 1000) * 1000;Sollte am Ende eigentlich in 1000 Schritten von 0 bis 255 gehen. Und bei 1000 logischerweise dann 255 am Ende der Grafik.
Dabei wird aber permanent die 0 ausgespuckt... Selbst ein umwandeln in float ouder double funktioniert nicht.
-
Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89 und C99) in das Forum Rund um die Programmierung verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Ok habs lösen können indem ich die Werte erstmal als double vorgegeben und berechnet und anschließend umgewandelt habe.
nun bin ich ein paar Schritte weiter und möchte eine komplexe Formel zur Berechnung benutzen.
Der Quellcoe schaut so aus:
#include "../common/cpu_bitmap.h" #include "../common/book.h" #include "math.h" #include "stdio.h" const int DIM = 1000; __global__ void kernel( unsigned char *ptr){ int x = blockIdx.x; int y = blockIdx.y; int offset = x + y * gridDim.x; int z = 300; double formel = ((150 - z/10)/150*((sin(x/160)*cos(y/350)) + 1)*(255/2)); int blau = 30; ptr[offset*4 + 0] = 0; ptr[offset*4 + 1] = 0; ptr[offset*4 + 2] = blau; ptr[offset*4 + 3] = 255; } int main ( void ) { CPUBitmap bitmap( DIM, DIM ); unsigned char *dev_bitmap; cudaMalloc ( (void**)&dev_bitmap, bitmap.image_size() ); dim3 grid(DIM, DIM); kernel<<<grid,1>>>(dev_bitmap ); cudaMemcpy( bitmap.get_ptr(), dev_bitmap, bitmap.image_size(), cudaMemcpyDeviceToHost); bitmap.display_and_exit(); cudaFree( dev_bitmap); }
Beim Ausführen bekomme ich folgende Fehlermeldung:
error: more than one instance of overloaded function "sin" matches the argument list:und
error: more than one instance of overloaded function "cos" matches the argument list:
Irgentas scheint ihn am Sinus cosinus nicht zu schmecken obwohl math.h definiert ist. :nixblick:
Ich dachte erst das es vielleicht an CUDA liegt, aber auch eine einfache Sin Anweisung im Main also auf dem prozessor mag er nicht.
-
Ich kenne CUDA zwar nicht, aber wie es aussieht, weiß der Compiler nicht, welche seiner Sinusfunktionen er nehmen soll.
Du ruftst die mit einem integer Parameter auf.
Da hast du das selbe Problem wie bei deinem letzten Post.Bei einer reinen Integerdivision, ist das Ergebnis auch ein Integer.
5/10 ist 0 (0.5 kannst du nicht mit int darstellen)
999/1000 ist auch 0Ist dir klar, das die Winkelfunktionen mit Bogenmaß arbeiten?
Mach mal aus deinen Konstanten in der Eormel Fließkommazahlen.
Dazu reicht es, einfach ein . anzuhängen.
5./10. ist 0.5
-
Larkis schrieb:
Ich dachte erst das es vielleicht an CUDA liegt, aber auch eine einfache Sin Anweisung im Main also auf dem prozessor mag er nicht.
waere es nicht sinnvoller die grundlagen zu lernen, bevor du dich an CUDA wagst? CUDA ist zum beschleunigen von programmen, das bedeutet, dass man erstmal programme erstellen koennen sollte. ob deine funktion nun auf der gpu oder cpu laeuft, ist doch nicht wichtig fuers erste, oder?
zwei dinge auf einmal lernen und nichtmal wissen wo der fehler liegt bei einfachsten dingen, schaut nicht vorteilhaft aus.
-
Ah wie dumm von mir.
In der tat da lag der Fehler. Ich habe jetzt noch 2 Variablen angelegt in denen die Index-Zahlen als Float abgelegt werden und das Programm gibt keine Fehlermeldung mehr aus... Dafür verreckt mir aber nun der Grafiktreiber wenn er versucht das darzustellen.
#include "../common/cpu_bitmap.h" #include "../common/book.h" #include "math.h" #include "stdio.h" const int DIM = 1000; __global__ void kernel( unsigned char *ptr){ int x = blockIdx.x; int y = blockIdx.y; float x1 = blockIdx.x; float y2 = blockIdx.y; int offset = x + y * gridDim.x; int z = 300; double formel = ((150 - z/10)/150*((sin(x1/160)*cos(y2/350)) + 1)*(255/2)); int blau = formel; ptr[offset*4 + 0] = 0; ptr[offset*4 + 1] = 0; ptr[offset*4 + 2] = blau; ptr[offset*4 + 3] = 255; } int main ( void ) { CPUBitmap bitmap( DIM, DIM ); unsigned char *dev_bitmap; cudaMalloc ( (void**)&dev_bitmap, bitmap.image_size() ); dim3 grid(DIM, DIM); kernel<<<grid,1>>>(dev_bitmap ); cudaMemcpy( bitmap.get_ptr(), dev_bitmap, bitmap.image_size(), cudaMemcpyDeviceToHost); bitmap.display_and_exit(); cudaFree( dev_bitmap); }
-
Also ich hab das problem nochmal extrahiert und in der Main getestet:
float x1 = 300; float y1 = 500; double formel = ((150 - 300 / 10) / 150 * ((sin(x1 / 160) * cos(y1 / 350)) + 1) * (255 / 2)); int blau = 255 - formel; printf("%f", blau);
Ergebnis im printf ist immer 0.000.
Andererseits funktioniert die Funktion in meinem WinAPI-Code ohne Probleme :nixblick:
@rapso
Ich hatte während meines Studiums mehrere Semester Java und davor während meiner Ausbildung Abi alles über HTML,CSS, JS PHP, MySQl ect.C Bedarf einer kleinen Umstellung aber damit werde ich denk ich schon fertig. Learning by Doing.
Problem ist nur das ich Ende nächster Woche was in CUDA präsentieren soll.
-
sin(300/160) = sin(0) = 0
Das ist aber in allen üblichen Programmiersprachen so. Außerhalb der Schule rechnet kaum jemand mit Grad.
edit: Ebenfalls:
(150 - 300 / 10) / 150 = (150 - 30) / 150 = 120 / 150 = 0
Auch dies sollte dir eigentlich von Sprachen mit C-Syntax (Java) her nichts neues sein...
-
So hab es jetzt soweit hinbekommen.
Ich habe die große Formel in mehrere Terme zerlegt die das programm nacheinander abarbeiten kann und nun läuft der Laden.
Und ja ich geb zu mir fehlt aktuell etwas die Praxis gerade mit den Variablen und deren umrechnung. Nervige kleine Dinge.
-
SeppJ schrieb:
sin(300/160) = sin(0) = 0
Das ist aber in allen üblichen Programmiersprachen so. Außerhalb der Schule rechnet kaum jemand mit Grad.
Fast
300/160 = 1
Es bleibt aber eine Integerdivision.Und nochmal für den TO. Die Winkelfunktionen rechnen mit Bogenmaß
Larkis schrieb:
int blau = 255 - formel; printf("%f", blau);
%f steht bei printf für float (und double). Du übergibst aber ein int.
Das haut hinten und vorne nicht hin.
Und wegen deiner Zerlegung in mehrere Terme: Schreib da Fließkommazahlen hin und keine Ganzzahlen.
-
Larkis schrieb:
So hab es jetzt soweit hinbekommen.
Ich habe die große Formel in mehrere Terme zerlegt die das programm nacheinander abarbeiten kann und nun läuft der Laden.Zwischen läuft und funktioniert richtig gibt es auch Unterschiede.
Larkis schrieb:
Und ja ich geb zu mir fehlt aktuell etwas die Praxis gerade mit den Variablen und deren umrechnung. Nervige kleine Dinge.
Das sind enorm wichtige Grundlagen.
Vor allem, weil da in sehr vielen Programmiersprachen so ist.
-
DirkB schrieb:
Larkis schrieb:
So hab es jetzt soweit hinbekommen.
Ich habe die große Formel in mehrere Terme zerlegt die das programm nacheinander abarbeiten kann und nun läuft der Laden.Zwischen läuft und funktioniert richtig gibt es auch Unterschiede.
Larkis schrieb:
Und ja ich geb zu mir fehlt aktuell etwas die Praxis gerade mit den Variablen und deren umrechnung. Nervige kleine Dinge.
Das sind enorm wichtige Grundlagen.
Vor allem, weil da in sehr vielen Programmiersprachen so ist.Was soll ich machen... Seid Ewigkeiten nicht mehr Programmiert, dann nur mit Java und nun will der Cheff das ich ihm was in CUDA hinzaubere.
Ich habe jetzt 2 Wochen C durchgeackert, dann ne Woche WINAPI um das Programm zu Vorführungszwecken schonmal damit zu realisieren und nun soll ich die Testversion, da ich ja so schön im Zeitplan liege nochmal auf Cuda umsetzen. Und seid einer Woche sitze ich hier mit nem CUDA Handbuch.
Hab mir das auch net unbedingt so ausgesucht, aber wie heißt es so schön, learning by doing und jeden Fehler macht man nur einmal. :p
Ok aktueller Stand ist das mein Programm läuft. Es zeichnet den gewünschten Bereich der Funktion in einem Feld von 500x500 Pixel. Dabei spuckt er aber folgendes im Ereignisfenster aus:
Eine Ausnahme (erste Chance) bei 0x7695b9bc in Cuda1.exe: Microsoft C++-Ausnahme: cudaError_enum an Speicherposition 0x002af730..Nun möchte ich die Darstellung auf 1000x1000 Pixel erhöhen. Ist ja einfach nur den DIm Wert verändern, danach bricht aber der Grafiktreiber zusammen und die Funktion wird nur zur Hälfte dargestellt.
Neues Rätsel neues Glück. Und schonmal vielen Dank für die Hilfe.
#include "../common/cpu_bitmap.h" #include "../common/book.h" #include "math.h" #include "stdio.h" const int DIM = 500; __device__ float cosinus( float y1) { return cos(y1 / 350); } __device__ float sinus( float x1) { return sin(x1 / 160); } __device__ float rechnung1( float z1) { return (150 - z1 / 10) / 150; } __device__ float rechnung2() { return 255 / 2; } __device__ float formel1(float zahl1, float sin1, float cos1, float zahl2 ) { return 255 - (zahl1 * (sin1 * cos1) * zahl2); } __global__ void kernel( unsigned char *ptr){ int x = blockIdx.x; int y = blockIdx.y; float x1 = blockIdx.x; float y1 = blockIdx.y; float z1 = 300; int offset = x + y * gridDim.x; float sin1 = sinus(x1); float cos1 = cosinus(y1); float zahl1 = rechnung1(z1); float zahl2 = rechnung2(); float formel = formel1(zahl1, sin1, cos1, zahl2); ptr[offset*4 + 0] = 0; ptr[offset*4 + 1] = 0; ptr[offset*4 + 2] = formel; ptr[offset*4 + 3] = 255; } int main ( void ) { CPUBitmap bitmap( DIM, DIM ); unsigned char *dev_bitmap; cudaMalloc ( (void**)&dev_bitmap, bitmap.image_size() ); dim3 grid(DIM, DIM); kernel<<<grid,1>>>(dev_bitmap ); cudaMemcpy( bitmap.get_ptr(), dev_bitmap, bitmap.image_size(), cudaMemcpyDeviceToHost); bitmap.display_and_exit(); cudaFree( dev_bitmap); }