[C/C++] OpenCL

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von Rushh0ur, 21. Dezember 2009 .

  1. 21. Dezember 2009
    OpenCL

    Guten Tag ЯRler,

    ich versuche mich grad in OpenCL einzuarbeiten, jedoch komm ich irgentwie nicht weiter....

    Ich will OpenCL dazu verwenden um mit Hilfe der Grafik-GPUs (NVidea: CUDA; ATI: ATI Stream) (erstmal) eine paralle Suche nach Primzahlen (im Berreich von 1..~10^8 ) durchzuführen, die Frage ist jetzt nun wie greife ich richtig auf diese Schnittstelle zu.

    So wie ichs vertsanden habe muss man zuerst einen Context (die Zielhardware) auswählen und initialisieren, anschliessen Speicher auf diesem Reservieren und den dazugehörigen Kernelcode in echtzeit kompilieren und ausführen lassen, aber wie?

    Das ist nun was ich bis jetzt habe:

    Spoiler
    PHP:
    #include "StdAfx.h"

    // Function deklerations
    void Printf_Info    ();
    bool IsPrime        ( unsigned int value );
    void SetAppPriority ( DWORD dwPiority );

    // Entrypoint of program
    int wmain ( int argc _TCHAR argv [])
    {
        
    Printf_Info ();

        
    // Print avaible devices and their infos *****************************************************************************
        
    {
            
    cl_uint            i ;
            
    cl_uint            device_count ;
            
    cl_device_id     * device_list ;

            
    clGetDeviceIDs ( 0 CL_DEVICE_TYPE_ALL 0 NULL , & device_count );
            
    device_list  = new  cl_device_id [ device_count ];
            
    clGetDeviceIDs ( 0 CL_DEVICE_TYPE_ALL device_count device_list NULL );

            
    printf ( "Found %d devices:\n" device_count );
            for (
    i = 0 i < device_count i ++)
            {
                    
    char device_string [ 1024 ];

                    
    // CL_DEVICE_NAME
                    
    clGetDeviceInfo ( device_list [ i ],  CL_DEVICE_NAME sizeof ( device_string ), & device_string NULL );
                    
    printf ( "\t%s\n" device_string );

                    
    // CL_DEVICE_VENDOR
                    
    clGetDeviceInfo ( device_list [ i ],  CL_DEVICE_VENDOR sizeof ( device_string ), & device_string NULL );
                    
    printf ( "\t Vendor:%s\n" device_string );

                    
    // CL_DEVICE_INFO
                    
    cl_device_type type ;
                    
    clGetDeviceInfo ( device_list [ i ],  CL_DEVICE_TYPE sizeof ( type ), & type NULL );
                    
    printf ( "\t Type:\t" );
                    if( 
    type  CL_DEVICE_TYPE_CPU  )
                        
    printf ( "%s " "CPU" );
                    if( 
    type  CL_DEVICE_TYPE_GPU  )
                        
    printf ( "%s " "GPU" );
                    if( 
    type  CL_DEVICE_TYPE_ACCELERATOR  )
                        
    printf ( "%s " "ACCELERATOR" );
                    if( 
    type  CL_DEVICE_TYPE_DEFAULT  )
                        
    printf ( "%s " "DEFAULT" );
                    
    printf ( "\n" );


                    
    printf ( "\n" );
            }
            
    delete []  device_list ;
        }
        
    // End print avaible devices *****************************************************************************************

        
    {
            
    cl_int        status ;
            
    cl_context    context ;

            
    context  clCreateContextFromType ( 0 CL_DEVICE_TYPE_GPU NULL NULL , & status );
            
            if (
    status  !=  0 )
            {
                
    printf ( "No GPU device found, fallback to CPU\n" );
                
    context  clCreateContextFromType ( 0 CL_DEVICE_TYPE_CPU NULL NULL , & status );
            }

            if (
    status  ==  0 )
            {
                
    // Wie gehts hier weiter?
                // Hat jemand nen Plan wie der weiter Aufruf 
                // durchgeführt werden muss?

                
    clReleaseContext ( context );
            }
            else
                
    printf ( "Error: No device available\n Code: 0x%08x" status );
        }

        
    system ( "PAUSE" );
        return 
    0 ;
    }


    // ****************************************************
    // Function pirint the programmname an the build version
    // ****************************************************
    void Printf_Info ()
    {
        
    printf ( "OpenCL Test v1.0_" );
        
    #if defined(_WIN64)
            
    printf ( "x64\n" );    
        
    #else
            
    printf ( "x32\n" );
        
    #endif
        
    printf ( "\n" );
    }

    // ****************************************************
    // Function check if the value is a prime
    // ****************************************************
    bool IsPrime ( unsigned int value )
    {
        if ((
    value == 2 ) || ( value == 3 )) return  true ;
        else
        {
            for(
    int i = 2 sqrtl ( value );  i ++)
            { 
                if ( 
    value  ==  0            ) break;
                if ( 
    i      1   sqrtl ( value )) return  true ;
            }
        } 
        
        return 
    false ;
    }

    // ****************************************************
    //  Fuction changes priority of current process:
    //
    //  following arguments can be used:
    //       IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS,
    //       HIGH_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS
    // ****************************************************
    void SetAppPriority ( DWORD dwPiority )
    {
       if(!
    SetPriorityClass ( GetCurrentProcess (), dwPiority ))
         
    printf ( "Cannot change the process priority!\n" );
    }
    StdAfx.h:
    PHP:
    #pragma once

    //Pre compiled headers

    #define _CRT_SECURE_NO_WARNINGS

    #include <CL/cl.h>

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <ctime>
    #include <algorithm>
    #include <vector>

    #include <tchar.h>
    #include <math.h>
    #include <windows.h>

    Mal schauen ob mir da jemand Helfen kann ....
    Und Links zu guten und einfach verständlichen Besipielcode wäre auch super, hab aber davon irgentwie nicht wirklich was gefunden, jedenfalls keinen der leicht zu verstehen ist.

    Mfg Rushh0ur
     
  2. 21. Dezember 2009
    AW: OpenCL

    Schau dir mal die Beispiele aus dem Stream SDK von ATI an. Ist zwar alles recht spärlich kommentiert, aber es sollte dir weiterhelfen.

    //EDiT:
    Auf gut verständliche Tutorials muss man wohl noch warten. Es ist einfach zu neu, aber vllt. magst du ja eins schreiben, sobald du es geschafft hast?
    Ist das selbe mit DirectX 11 (bzw. Direct3D 11). Das Aug. '09 SDK wirkt wie eine Beta, Dokumentation Fehlanzeige und bei D3DX11 fehlt auch noch die hälfte (einiges ist sogar nur typedef'ed D3DX10 Zeugs ). Für D3D 9 gibt's einen Haufen guter Tutorials, für D3D 10 sieht es um einiges schlechter aus, aber bei D3D 11 wird es endgültig duster. Ich bin schon froh darüber, dass ich ein mit Rot "geleertes" Fenster bekomme x)
     
  3. 23. Dezember 2009
    AW: OpenCL

    Dank dir, muss ich wohl die Stream SDK von ATI nochmal genauer unter die Lupe nehmen.
    Wie du schon gesagt hast ist alles zur Zeit noch neuland, mal schauen wie weit ich komme evtl. schreib ich ja noch ein Tut.

    Ansonsten wenn jemand was brauchbares findet, immer her damit.

    Mfg Rushh0ur
     
  4. 25. Dezember 2009
    AW: OpenCL

    Hat jetzt nichts mit deinem Problem zu tun, aber den Primzahlentest könnte man effizienter gestalten (ich hab mich die letzten Tage auch damit beschäftigt):

    Auf jeden Fall (bei dir Value) mit der 3 Starten, die 2 kannste vorgen. Die Schrittweite kannst du dann auf 2 stellen. Das Gleiche mit dem Teiler, wenn du nur ungerade Zahlen hast, können die auch nur ungerade Teiler haben.
    Das Quadrat des Teilers zu berechnen geht schneller als die Wurzel der Zahl zu ziehen. Bei mir sind das dann so aus: (Achja, ich hab bei mir die Erfahrunge gemacht, dass break das ganze stark verlangsamt, deswegen der Schalter "c")

    Code:
    #include <stdio.h>
    #include <math.h>
    
    char primeln(unsigned long long int);
    
    int main(void)
    {
     unsigned long long int i=2, anzahl=1;
    
     printf("%lld. \t %lld \n",anzahl,i); //Vorgegebene Primzahl 2 Ausgeben
     for (i=3; i<=15000000; i+=2) // i muss unbedingt ungerade sein!
     {
     if (primeln(i))
     printf("%lld. \t %lld \n",++anzahl,i);
     }
     return 0;
    }
    
    char primeln(unsigned long long int i)
    {
     int c=0, teiler=3;
     while ( teiler*teiler <= i && !c) // hier war Teiler*Teiler schneller als pow(teiler,2) und sqrt(i)
     {
     if(!(i%teiler)) //Wenn die Zahl n Teiler hat, Schalter umlegen, und rausspringen
     c=1;
     teiler+=2;
     }
     if (!c)
     return 1;
     else
     return 0;
    }
    Dieser Code gribt die Zahlen nur aus, aber den Rest kann man ja anpassen. Ich habe es mir nochmal so umgeschrieben, dass es mir alle Primzahlen bis 10.000.000 (also ein Zehntel von dem was du willst) in eine Datei schreibt. Das hat auf dem eeePC 1000H (Atom 1,6Ghz) eine Stunde Gedauert, muss mal schauen wie lange das auf einem E6300 mit 2,1GHz läuft.

    Die erhöhung der Schrittweite auf 2 hat bei mir auf jeden Fall sehr geholfen.
     
  5. 26. Dezember 2009
    AW: OpenCL

    Hi don_bilbo13,

    @Offtopic
    ja gut das Leuchtet auch ein dass man in zweier Schritten gehen kann da alle geraden Zahlen sowieso durch 2 teilbar sind dabei fällt die Hälfte aller Zahlen schon mal weg wodurch die Performance wohl um 100% gesteigert werden kann.

    Danke für den Vebsserungsvorschlag mit dem Quadrieren, muss ich mir aber noch mal durch den Kopf gehen lassen, war aber wie du ja gesagt hast auch nicht die Frage. Wenn mans wirklich optimieren will, muss man das sowieso mittels assembler optimieren.

    Du sagst das hat bei dir eine Stunde gedauert bis 10.000.000? Ja gut das liegt wahrscheinlich mit der Dateiausgabe zussamen, dass es solange gedauert hatt, aber trotzdem etwas lange ....
    Hab auch ein paar versuche gemacht mit einem Core 2 Duo P8700 @2.53Ghz, da hatt ich (auch bis 10000000) ohne Dateiausgabe und ohne Multicore-Optimierung eine Zeit von ~8200ms, mit Multicore-Optimierung eine von ~4200ms und ne Dateiausgabe dürft das auch nicht wirklich stark verlängern. (richtig millisekunden!)
    Etwas zu krasser unterschied zwischen den zwei CPUs, kann sein dass du irgentwas falsch gemacht hast bei deiener Programmierung.

    Aber wir wollen ja hier jetzt nicht über Optimierung diskutieren, ist zwar auch ein schönes Thema (könnte man vielleicht sogar eins Aufmachen), aber welches zur Zeit jeden Programmierer ein Dreck interessiert. Und dann sich wundern wenn was laggt....

    @Topic
    Dank den Feiertagen komme ich net dazu da was zu machen sobald sich das gelegt hat melde ich mich nochmal wenn ich was habe....

    Und bleibt beim Thema leute.

    Mfg Rushh0ur
     
  6. 26. Dezember 2009
    AW: OpenCL

    ok, habs jetzt nochmal ohne Dateiausgabe gemacht und mit dem Schalter -O3 optimiert, jetzt habe ich 56666ms gebraucht, also knapp eine Minute, ich werde mich später nochmal an den Desktop setzen und es da nochmal starten und testen.
    Kannst mir ja per PM oder sowas deine ICQ-NR schicken, falls du Lust hast, drüber zu reden.

    Das mit GPGPU interessiert mich auch sehr, ich werde hier mal am Ball bleiben.

    Edit: mit Dualcore optimierung hats auf dem eee 37,7sek gebraucht (37656ms)
    Edit2: auf dem Desktop (E6300 @2,1GHz) hats 11004ms/6079ms gedauert. JEtzt bin ich auch ruhig
     
  7. 7. Oktober 2011
    AW: OpenCL

    Man den Thread hab ich schon ganz vergessen, sry ...

    Zum Primzahlen Problem, mein Mathematik-Professor hat mir einen besseren weg gezeigt Primzahlen zu ermitteln; zumindest einen relativ schnelleren weg und zwar ganz einfach durch ausstreichen von Teilbaren Zahlen in einem Kontinuierliche Zahlenarray. (Was jedoch unter Umständen auf den Speicherverbrauch begrenzt wird)

    Nach knap einem Jahr, ja ne sogar 2, bin ich nun Endlich wieder dazu gekommen OpenCL mir anztuen und das mit Erfolg.

    Eine klein Zusammenfassung der Arbeitsweise von OpenCL:
    • Die Plattform Funktionen werde genutzt um den aktuellen Treiber zu ermitteln (-> clGetPlatformIDs)
    • Nach Auswahl eine Plattform können die verfügbaren Recheneinheiten gelistet
      und zum verwenden selektiert werden (-> clGetDeviceIDs, -> clCreateContext)
    • Sobald Geräte ausgewählt wurden wird für diese zur Laufzeit
      das Programm compiliert ("Offline Kompilierung" auch möglich) welches auf den
      Geräten ausgeführt werden soll (-> clCreateProgramWithSource, -> clBuildProgram)
    • Nach erfolgreichem Compilieren müssen die Funktionsschnittstellen zwischen
      der CPU und den Geräten generiert werden, welche im folgendem Aufgerufen werden sollen(-> clCreateKernel, clEnqueueNDRangeKernel)
    • Nach all diesen Initialisierungen können Kommandoliste erstellt
      und abgearbeitet werden (-> clCreateCommandQueue)
    • Arbeitsspeicherreservierungen und -Operationen können mit den Befehlen
      clCreateBuffer, clEnqueueRead/WriteBuffer u.ä durchgeführt werden
    • Des weiteren stellt (fast) jede Kommandolistenfunktion Parameter bereit
      um auf vorherige Ereignisse zu warten (-> clWaitForEvents)

    //Edit:
    Ach ja ne Quick Reference Card zu OpenCL findet man hier:
    http://www.khronos.org/files/opencl-1-1-quick-reference-card.pdf

    Mehr gibt es von mir erst mal nicht, eventuell findet jedoch noch jemand Interesse an dem Thema um weiter zu Diskutieren.

    Mfg Rushh0ur
     
  8. 9. Oktober 2011
    AW: OpenCL

    Das nennt sich Sieb des Eratosthenes
     
  9. 10. Oktober 2011
    AW: OpenCL

    darf ich mal fragen, warum du OpenCL verwendest? Hast du ne ATI-Grafikkarte?
    Ich weiß nur von einem Freund, der mit OpenCL und CUDA gearbeitet hat und er hat zu mir gesagt: "Vergiss OpenCL... nutzt CUDA", denn er hat nur über OpenCL geschimpft.
     
  10. 11. Oktober 2011
    AW: OpenCL

    OpenCL ist teil von OpenGL und somit Hard- und Software unabhängig.
    Wenn ich mich richtig erinnere braucht man bei OpenGL OpenCL wenn man mit ATI Stream oder CUDA arbeiten will.
     
  11. 11. Oktober 2011
    AW: OpenCL

    @Thrake7

    zugführer hat eigentlich schon erklärt was OpenCL ist; damit man auf CUDA und/oder ATI Stream arbeiten kann, ja nicht nur auf Grafikkarten sondern auch weiteren Geräten mit OpenCL unterstützung.
    Irgendwo hab ich gelesen das Intel sogar über die Schnittstelle von OpenCL Treiber anbietet um das ganze sogar noch auf CPU, mit den selben Befehlen, auszulagern.

    Ich habe auf meinem Rechner ne ATI Grafikkarte und nach Installation der Treiber hab ich festgestellt, dass ich die CPU auch nutzen kann (was oberes bestätigen würde): das kam mir gerade recht sodass ich OpenCL gewählt habe.

    Ich kann aber dein Freund verstehen, zur Zeit ist die OpenCL-Schnittstelle noch nicht auf dem Stand wie vl. die CUDA oder ATI-Stream Implementierung, da noch einige Befehle, wie ich feststellen musste, noch nicht korrekt auf allen Geräten funktionieren, dennoch kann man, wenn man diese meidet wunderbar damit für mehre Geräte gleichzeitig Programmieren.

    Mfg Rushh0ur
     
  12. 11. Oktober 2011
    AW: OpenCL

    hmm... okay.
    Ich weiß nur, dass OpenCL schon lange existiert und die Entwicklung meiner Ansicht nach zu langsam verläuft. Der einzige Punkt, der eben gut dafür spricht, ist die unabhängigkeit der Grafikkarten.
    Es fragt sich eben nur, wo der größere Vorteil liegt. Ich kenne CUDA, allerdings bin ich weniger mit ATI Stream vertraut und kann wenig über die Performance sagen.

    Ich denke mal, du wirst wissen, was du tust Mich hat es nur interessiert, warum man OpenCL Cuda bzw. Ati Stream vorziehen würde.
     
  13. 11. Oktober 2011
    AW: OpenCL

    Quark, OpenCL und OpenGL sind zwei paar Schuhe, deren einziger Zusammenhang die Verwaltung durch die Khronos Group ist. Man kann OpenCL nutzen, ohne auch nur ein Quäntchen mit OpenGL in Berührung zu kommen, im Gegensatz zu z.B. DirectCompute, welches mit D3D verzahnt ist. Natürlich wurde aber auch die Möglichkeit geschaffen, OpenCL und OpenGL gemeinsam effizient nutzen zu können.

    OpenCL ist in erster Linie eine API nebst zugehöriger Programmiersprache, ohne Bindung an jedwede Hardware. Daher kann man es auch nicht mit CUDA vergleichen. Die Hardware kommt erst mit der Implementierung ins Spiel und dabei ist es der API völlig egal, worauf der Code später läuft. Hauptsache es wird sich an die Spezifikation gehalten. Wenn du Lust hast, kannst du auch eine Implementierung für eine 8-bit MCU schreiben. Ob das sinnvoll ist sei mal dahingestellt, denn dieses Beispiel soll einfach nur verdeutlichen, dass OpenCL nicht auf Grafikkarten beschränkt ist.

    Bisher existieren Implementierungen für AMD GPUs, nVidia GPUs, x86/x64 (AMD, Intel, Apple), IBM Power, Cell, PowerVR und bald auch Adreno (beides Smartphone GPUs!) und noch einige andere Geräte.

    Das Hauptaugenmerk von OpenCL ist die Portabilität, nicht die Effizienz. Letztere erreicht man, wenn man sich an die Gegebenheiten der jeweiligen Implementation anpasst. Eine GPU arbeitet nun mal anders als eine CPU... daran kann man nichts ändern.
    Der Vorteil daran ist, dass man nur eine einzige Sprache lernen muss.

    @Thrake7:
    Die Performance AMD vs. nVidia hängt von der gegebenen Problemstellung ab. Bei vektorisierbaren Problemen zieht eine HD5870 momentan jede andere single GPU - auch eine GTX580 - locker ab. Dafür gerät sie bei Problemen mit vorwiegend skalaren Berechnungen ins Hintertreffen. Jede Architektur hat ihre Vor- und Nachteile...
     
  14. 11. Oktober 2011
    AW: OpenCL

    Sry ich kannte OpenCL nur als Teil von OpenGL nicht als eigenständige Sprache. Aber ich war der Meinung OpenCL ist sehr wohl mit CUDA/Stream verknüpt. OpenCL muss ja auf die GPU zugreifen können und dies geschieht in der jeweiligen Sprache in der die Implementierung geschrieben wurde. Bei Nvidia ist das CUDA bei AMD Stream.
     
  15. 11. Oktober 2011
    AW: OpenCL

    Wie das geschieht ist völlig belanglos. Ob da jetzt APP (neuer Name von Stream) oder CUDA drunter steckt oder Heinzelmännchen rumwürfeln und auf ein richtiges Ergebnis hoffen ist aus Sicht eines Programmes völlig egal. Das sieht nur die API und darüber die installierten ICDs.

    Programm -> OpenCL API -> OpenCL ICD. Mit dem ICD beginnt die jeweilige Implementation. Man muss nicht mal die SDKs der jeweiligen Hersteller laden. Man braucht nur die Header (gibt's bei Khronos) und die OpenCL-lib für's eigene Betriebssystem, denn die ICDs liefern AMD und nVidia mittlerweile mit ihren GPU-Treibern aus.

    AMD geht folgenden Weg: OpenCL -> LLVM -> Optimierung -> CAL-Backend -> CAL -> GPU
    nVidia geht AFAIK: OpenCL -> LLVM -> ... -> PTX-Backend -> PTX -> GPU, ohne Umweg über CUDA.
     
  16. 11. Oktober 2011
    AW: OpenCL

    Gibt es somit auch eine ARM-Lösung für OpenCL, wenn du PowerVR erwähnst? Kann ich dann überhaupt gut Performance aus PowerVR rausholen?
    Das klingt für mich nämlich interessant.
     
  17. 27. Oktober 2011
    AW: OpenCL

    Von dem Zahlenarray hab ich auch schon gehört, ist nur leider in C nicht so schön bzw garnicht zu coden, wenn man keine Pointer verwendet.
    Das müsste mit Python eigentlich gut gehen, aber performant ist das nicht :\

    Vielleicht kann man hier noch ne elegante OpenCL Lösung entwickeln.
    Ich habe eben noch einen "alten" Algorithmus gefunden, der ist allerdings deutlich effizienter als der obige. Was ich da fürn scheiß gecodet hab

    Code:
    char primeln(unsigned long long int n)
    {
     unsigned int wurz, i;
     if (n%2==0)
     return 0;
     if (n%3==0)
     return 0;
     wurz= sqrt(n);
     for (i=6; i <= wurz; i+=6)
     {
     if(n%(i-1)==0)
     return 0;
     if (n%(i+1)==0)
     return 0;
     }
     return 1;
    }
    Das ganze ist jetzt auf die Gegebenheiten der C-Typen abgestimmt, die Wurzel aus einer 64Bit Zahl kann nie mehr als 32Bit haben - da kann man dann Performance rausholen udn Zeit sparen.
    Achja, die 2 und 3 fallen hier auch raus, aber die beiden Zahlen interessieren meist am wenigsten und eine Abfrage lässt sich ja leicht einfügen.
     
  18. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.