Schnelle Erzeugung + Schreiben + Ausgeben von Strings mittels omp bzw. openmp unter C ???



  • Hallo zusammen,

    ich möchte ein kleines Testprogramm in C unter Linux (Ubuntu 12.04) schreiben,
    dass 8 Byte lange Strings erzeugt und in eine Datei schreibt. Während dem Schreibvorgang
    soll der zu schreibende String auch gleichzeitig auf dem Bildschirm (Konsole) ausgegeben werden.
    Die Strings sollen nur aus Ziffern bestehen. Der erste String lautet: "00000000" und der letzte: "99999999".
    Die o.g. Strings sollen mittels einem zweidimensionalen arrays und einer verschachtelten for-Schleife erzeugt werden.

    Code-Beispiel:
    --------------

    #define  DIM1 10 /* Zeilen pro Durchlauf		 */
    #define  DIM2  8 /* Spalten je Zeile, also für 8 Zeichen */
    #define  ZERO 48 /* '0'					 */
    #define  ONE  49 /* '1'					 */
    #define  NINE 57 /* '9'					 */
    .
    .
    .
    function1( char *string )
    {
     ...
    }
    
    function2( char *string )
    {
     ...
    }
    
    int main( void )
    {
        char array[DIM1][DIM2]; /* Erzeugung der Strings von 00000000 bis 99999999 */
        char buf[DIM2];         /* Puffer - soll nach jedem Durchlauf der äußeren Schleife, den fertigen String beinhalten			 *
    			     * Anhand des Puffers sollen weitere Funktionen, wie zum Ausgeben der Strings auf dem Bildschirm und zum     *
    			     * Schreiben der Strings in eine Datei, aufgerufen werden. Also innerhalb der äußeren for-Schleife.		 */
        int  i, j;
    
        /* nur mal grob als Beispiel - "00000000" bis "00000009" */
    
        for( i = 0; i < DIM1; i++ )
        {
            for( j = 0; j < DIM2; j++ )
            {
                array[i][0] = ZERO;
                array[i][1] = ZERO;
                array[i][2] = ZERO;
                array[i][3] = ZERO;
                array[i][4] = ZERO;
                array[i][5] = ZERO;
                array[i][6] = ZERO;
                array[i][7] = i + ZERO; /* i + (ZERO == 49 == '0'), wenn i z.B. 3 --> 3 + 49 = 52 == '3' usw. */
                buf[j] = array[i][j];   /* am Ende der inneren Schleife hat buf den fertigen String. */
            }
    
            function1( buf );	    /* function1 gibt bspw. den String auf dem Bildschirm aus. */
            function2( buf );	    /* function2 schreibt den String in eine Datei.	       */
        }
    
        .
        .   ...hier noch mehr Code...if(...)...tue das...else...das...usw...
        .
    }
    

    Habe das alles soweit ausprobiert und es funktioniert auch einwandfrei.

    Nun zu meinem eigentlichen Anliegen, in der Hoffnung etwas Hilfe bzw. Tipps von euch zu bekommen:

    Ich würde die Erzeugung der Strings innerhalb der verschachtelten for-Schleife gerne beschleunigen.
    Dabei dachte ich an openmp. Doch dazu hätte ich gleich mehrere Fragen:

    1. Wäre es in dieser Form überhaupt möglich, openmp überhaupt anzuwenden?
    2. Wenn ja - würde es so denn überhaupt Sinn machen?
    Denn meine Befürchtung ist vor allem die Ausgabe des erzeugten Strings auf dem Bildschirm, könnte das ganze extrem ausbremsen, oder?
    Zumindest in der oben gezeigten Form.

    3. Wie könnte ich das umsetzen, dass sich die Prozessorkerne die Arbeit richtig aufteilen, das ganze richtig in die Datei geschrieben
    wird und mit voller Geschwindigkeit in Echtzeit auf dem Bildschirm ausgegeben wird?

    Ich hoffe ihr könnt mir ein paar Ratschläge geben und mich vielleicht bei der Umsetzung etwas unterstützen.

    Ich wäre euch sehr dankbar.

    Grüße Stephan



  • 1.) Ja.
    2.) Nein.
    3.) Garnicht.

    Leider kann ich dir keinen Ratschlage geben. Darueber hinaus ist SIMD wie SSE besser als OpenMP fuer die Erzeugung der Strings geeignet.



  • Wenn die Bildschirmausgabe so schnell wird wie du es dir wünschst, kannste das eh nicht mehr lesen (Daher wohl sinnlos). Es wird schon daher sinnlos, weil du eh nicht mehr Strings lesen kannst, wie dein Monitor Bilder in der Sekunde darstellen kann. Dein menschliches Auge wird auch kaum mehr als 24 Strings pro Sekunde bewusst unterscheiden können.

    Lösung: Gib doch einfach nur jeden 1000 oder 10000 oder ... String aus.
    Dann sollten deutlich mehr Strings pro Sekunde erzeugt werden, weil deine CPU wohl durch die Bildschirmausgabe gebremst wird.



  • knivil schrieb:

    1.) Ja.
    2.) Nein.
    3.) Garnicht.

    Leider kann ich dir keinen Ratschlage geben. Darueber hinaus ist SIMD wie SSE besser als OpenMP fuer die Erzeugung der Strings geeignet.

    SIMD oder SSE habe ich mich noch gar nicht damit befasst. Openmp habe ich mir schon etwas angeschaut bzw. versuche mich da etwas einzuarbeiten. Ist allerdings gar nicht so leicht. Trotzdem schon mal danke für dein posting. 😉

    Andreas XXL schrieb:

    Wenn die Bildschirmausgabe so schnell wird wie du es dir wünschst, kannste das eh nicht mehr lesen (Daher wohl sinnlos). Es wird schon daher sinnlos, weil du eh nicht mehr Strings lesen kannst, wie dein Monitor Bilder in der Sekunde darstellen kann. Dein menschliches Auge wird auch kaum mehr als 24 Strings pro Sekunde bewusst unterscheiden können.

    Lösung: Gib doch einfach nur jeden 1000 oder 10000 oder ... String aus.
    Dann sollten deutlich mehr Strings pro Sekunde erzeugt werden, weil deine CPU wohl durch die Bildschirmausgabe gebremst wird.

    Ja - so etwas hatte ich mir auch überlegt. Eben nur jeden 1000 oder von mir aus 10000 String am Bildschirm zu aktualisieren bzw. auszugeben.

    Mit dem Schreiben in die Datei, dass dürfte eigentlich nicht zu sehr ausbremsen, oder?

    Ich bräuchte wenn möglich etwas Hilfestellung bei der Anwendung von openmp für meine Schleife. Hättet ihr mir ein paar Vorschläge?


  • Mod

    1. Ja.
    2. Erzeugen: Prinzipiell ja., Ausgeben: Nein. Aber nicht weil dein bildschirm nicht mehr darstellen könnte, das ist Quatsch. Ausgabe an sich ist einfach langsam und nicht parallelisierbar (außer du hast einen Großrechner mit parallelem Dateisystem).
    3. Siehe 2.

    Da die erzeugende Funktion hier trivial ist, macht die Parallelisierung keinen Sinn. In der Zeit, wo du eine Zeile ausgeben kannst (selbst in eine Datei), kannst du schon zwei oder mehr neue Zeilen erzeugen. Die Erzeugung ist einfach nicht der Flaschenhals. Optimieren, ganz besonders durch Parallelisieren, lohnt sich nur, wenn es auch wirklich ordentlich was zu rechnen gibt.



  • SeppJ schrieb:

    1. Ja.
    2. Erzeugen: Prinzipiell ja., Ausgeben: Nein. Aber nicht weil dein bildschirm nicht mehr darstellen könnte, das ist Quatsch. Ausgabe an sich ist einfach langsam und nicht parallelisierbar (außer du hast einen Großrechner mit parallelem Dateisystem).
    3. Siehe 2.

    Da die erzeugende Funktion hier trivial ist, macht die Parallelisierung keinen Sinn. In der Zeit, wo du eine Zeile ausgeben kannst (selbst in eine Datei), kannst du schon zwei oder mehr neue Zeilen erzeugen. Die Erzeugung ist einfach nicht der Flaschenhals. Optimieren, ganz besonders durch Parallelisieren, lohnt sich nur, wenn es auch wirklich ordentlich was zu rechnen gibt.

    Hallo SeppJ,

    okay, mit dieser Antwort hast du mir schon sehr gut geholfen. Danke 🙂 Das dachte ich mir nämlich schon, dass Ausgabe nicht parallelisierbar ist (Bildschirm + Datei).

    Wenn ich aber die Funktionen zur Ausgabe auf dem Bildschirm und zum Schreiben in eine Datei so umändere, dass sie außerhalb der parallelisierten for-Schleife aufgerufen werden und ich die Bildschirmausgabe insofern anpasse, dass wirklich nur jeder 10000te String ausgegeben wird, müsste doch trotzdem ein Performance-Schub zu spüren sein, oder? Außerdem bin ich der Meinung, dass bei 100000000 Strings (00000000 bis 99999999), die ja letztendlich erzeugt, geschrieben und "ausgegeben" (also jeder 10000te als Beispiel) werden sollen, sich eine Parallelisierung durchaus lohnt. Klar würde ich so niemals die Kapazität erreichen, die rein rechnerisch machbar ist. Doch es muss doch zumindest möglich sein den Vorgang insgesamt, verglichen ohne Parallelisierung, zu beschleunigen. Auch mit Bildschirmausgabe + in Datei schreiben.


  • Mod

    Unwahrscheinlich. Die Rechnung ist zu trivial. Im Prinzip ist sie sogar unnötig, da man aus einem gegebenen Index fast instantan den String berechnen kann, ohne dass man vorher überhaupt alle Strings berechnen müsste.

    Die Rechnung ist einfach so sinnlos. Wenn dahinter ein realistisches Beispiel stecken soll, dann bring dieses für ein realistisches Urteil. Wenn dahinter das Lernen von OpenMP steht, dann sollte dir Performance egal sein, mach es einfach.



  • Eigentlich geht es mir um beides. Um das Lernen vom OpenMP und die Umsetzung meiner Idee. Allerdings verstehe ich nicht ganz, was du genau meinst. Ich bin noch nicht so erfahren in der Programmierung. Habe erst vor knapp einem Jahr damit angefangen. Wenn ich das richtig verstehe, meinst du das mein Beispiel mit der verschachtelten for-Schleife also total falsch ist, um auf die Art Strings zu erzeugen? Dann würde ich mich sehr darüber freuen, wenn du mir ein paar Tipps geben könntest, wie man das besser machen könnte. Ich bin ja noch voll in der Lernphase und habe bisher nicht soviel Erfahrung. Darum bin ich ja für Verbesserungsvorschläge und Tipps allgemein sehr offen. 🙂


  • Mod

    Dann kommt jetzt die Gretchenfrage: Was willst du erreichen?



  • Guten Morgen ;-),

    was ich erreichen möchte, habe ich ja oben bereits geschrieben. Du hast
    mir nun aber klar gemacht, dass mein Vorhaben so nicht wirklich sinnvoll ist.
    Das nehme ich auch gerne so an. Nun wollte ich dich fragen, wie ich das besser machen könnte? Mal angefangen mit der verschachtelten for-Schleife und dem zweidimensionalen Array. Du hast gestern geschrieben, dass es so wenig Sinn macht.



  • Wenn du aus dem Stand den 171345-ten String ausgeben wuerdes, wie sieht der aus?



  • Der String würde folgendermaßen aussehen: 00171344.


  • Mod

    Stephan87 schrieb:

    Der String würde folgendermaßen aussehen: 00171344.

    Und wie konntest du darauf kommen, ohne systematisch die vorherigen 171343 zu berechnen?

    Wie dem auch sei: Wenn das Endresultat wie oben beschrieben sein soll, alle diese Zeichenketten in eine Datei zu schreiben, dann hilft dir kein MPI, da du sicherlich kein paralleles Dateisystem hast. Die Gesamtgröße der Datei wird ungefähr 10 GB sein, das wäre schon längst fertig, wenn du einfach ein serielles Programm die Nacht lang hättest laufen lassen.

    Aber jetzt kommt bestimmt, dass es doch nicht das Ziel war, diese Zeichenketten alle in eine Datei zu schreiben und das alles nur ein Beispiel war. Wetten das?



  • Ja - ich schon. Ich kann ja rechnen. Aber damit das Programm es weiß, habe ich es eben in dieser Form anhand des arrays und der for-Schleife geschrieben. So fängt das Programm praktisch bei 0 (00000000) an und endet bei (99999999).
    Soweit ich das verstehe, geht es wohl einfach nicht. D.h. die Berechnung mittels array und versch. for-Schleife könnte man parallelisieren und dadurch auch deutlich beschleunigen, aber spätestens beim Schreiben der Datei wäre es sozusagen für die Katze, weil dass ganze dadurch wieder ausgebremst wird.
    Alles klar. Dann habe ich wohl wieder was dazu gelernt. Jedenfalls Dankeschön.

    Grüße
    Stephan



  • Oh, hatte ich fast vergessen.
    Doch das Ziel war es schon. Allerdings nicht alles in eine Datei zu schreiben, sondern gesplittet. Denn will man eine 10GB große Datei mit gedit öffnen, muss man im schlimmsten Fall mit einem Absturz des Computers rechnen.
    Sorry für den doppel-post, werde mich mal lieber bei euch registrieren.
    Grüße 🙂


  • Mod

    Wie du es splittest ist doch egal. Fakt ist: Das Programm soll 10 GB (nutzlose) Daten auf die Festplatte schreiben, die trivial zu berechnen sind (der Computer kann übrigens auch rechnen!). Dein Programm wird so lange dauern, wie dein Computer zum Schreiben von 10 GB Daten braucht, egal wie schnell du deine Strings berechnest.

    Noch mal: Was willst du überhaupt erreichen? Wozu sollen 10 GB Trivialdaten, die du jederzeit in wenigen Taktzyklen berechnen könntest, auf der Festplatte gut sein? Das riecht irgendwie nach völlig sinnverfehltem Lookuptable.



  • SeppJ schrieb:

    Wie du es splittest ist doch egal. Fakt ist: Das Programm soll 10 GB (nutzlose) Daten auf die Festplatte schreiben, die trivial zu berechnen sind (der Computer kann übrigens auch rechnen!). Dein Programm wird so lange dauern, wie dein Computer zum Schreiben von 10 GB Daten braucht, egal wie schnell du deine Strings berechnest.

    Noch mal: Was willst du überhaupt erreichen? Wozu sollen 10 GB Trivialdaten, die du jederzeit in wenigen Taktzyklen berechnen könntest, auf der Festplatte gut sein? Das riecht irgendwie nach völlig sinnverfehltem Lookuptable.

    Hallo zusammen,ich weiß das der Computer rechnen kann. Hatte mich nicht ganz richtig ausgedrückt. Ja, du hast Recht. Genau das wollte ich ausprobieren. Eine Art Lookuptable. Das es völlig sinnverfehlt ist, will ich auch gar nicht bestreiten. Deswegen bitte ich ja um Ratschläge. Das meine Theorie, die Erzeugung von Strings in Kombination mit Ausgeben und Schreiben mittels Parallelisierung beschleunigt werden könnte, völlig falsch und unrealistisch ist, habe ich mittlerweile auch begriffen. Deswegen frage ich, ob ihr mir ein paar Ratschläge geben könntet, wie man es anders oder besser machen könnte? Deswegen habe ich doch auch diesen Thread erstellt. 🙂


  • Mod

    Das beste wäre, gar nichts zu tun. Das heißt, nicht einmal den Lookuptable erstellen. Dieser wäre für die Aufgabe mit nahezu Sicherheit langsamer als eine direkte Berechnung und würde bei Start auch noch ewig zum Laden brauchen und Gigabytes von Speicher sinnlos verschwenden.



  • Okay. Alles klar. Vielen Dank.


Anmelden zum Antworten