Hallo, ich möchte angehängtes C-Programm, bestehend aus kurzem gcd.c und sehr langem, included vo.txt (5MB) mit GCC für nen Pentium target übersetzen. Das will mir nicht gelingen. Habe den GCC auf nem Windows-Rechner über mehrere Wege probiert: commandline von djgpp, Code::Blocks, commandline MingW. Das Ding terminiert ohne Warning (bei Code::Blocks offensichtlich mit exit-code 1), generiert aber nix. Warum? Wie kriegt man GCC bißchen gesprächiger? btw: Visual C generiert mit dem Ding 'internal Compiler Error' Gute Nacht Detlef
Unter Linux lässt es sich zumindest kompilieren (Verweis auf conio.h vorher entfernt): chef@localhost /tmp/xyz $ date && gcc -c gcd.c && date Fri Jun 29 01:26:09 CEST 2007 In Datei, eingefügt von gcd.c:15: vo.txt:78751:6: Warnung: Kein Newline am Dateiende Fri Jun 29 01:27:25 CEST 2007 Die Objekt-Datei ist etwas größer: chef@localhost /tmp/xyz $ ls -lah gcd.o -rw-r--r-- 1 chef chef 13M Jun 29 01:27 gcd.o Dafür spuckt der Linker ein paar Fehler aus: chef@localhost /tmp/xyz $ gcc -o gcd gcd.o 2>&1 gcd.o: In function `main': gcd.c:(.text+0x1776): undefined reference to `pow' gcd.c:(.text+0x1791): undefined reference to `pow' gcd.c:(.text+0x17b4): undefined reference to `pow' gcd.c:(.text+0x17da): undefined reference to `pow' gcd.c:(.text+0x17fd): undefined reference to `pow' Warnungen gibt es nur bzgl. unverwendeter Variablen: chef@localhost /tmp/xyz $ gcc -c -fpie -Wall gcd.c In Datei, eingefügt von gcd.c:15: vo.txt:78751:6: Warnung: Kein Newline am Dateiende gcd.c: In Funktion »main«: gcd.c:10: Warnung: Variable »b1za« wird nicht verwendet gcd.c:10: Warnung: Variable »b1ya« wird nicht verwendet gcd.c:10: Warnung: Variable »b1xa« wird nicht verwendet gcd.c:10: Warnung: Variable »v0a« wird nicht verwendet gcd.c:10: Warnung: Variable »b1z« wird nicht verwendet gcd.c:10: Warnung: Variable »b1y« wird nicht verwendet gcd.c:10: Warnung: Variable »b1x« wird nicht verwendet gcd.c:9: Warnung: Variable »k« wird nicht verwendet Das Problem ist vermutlich der Stack: Hier ein Auszug aus dem über 100 MB großen Listing: 28 main: 29 0000 8D4C2404 leal 4(%esp), %ecx 30 0004 83E4F0 andl $-16, %esp 31 0007 FF71FC pushl -4(%ecx) 32 000a 55 pushl %ebp 33 000b 89E5 movl %esp, %ebp 34 000d 53 pushl %ebx 35 000e 51 pushl %ecx 36 000f 81EC7090 subl $1806448, %esp Hier werden mal eben über 1 MB für den Stack freigeschaufelt.
Mit gcc -O9 -Wall -Wa,"ahl=list" gcd.c kommen jetzt noch mehr Warnungen: vo.txt:1: Warnung: »s1« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »tf2« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »tf3« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »w2x« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »w3x« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »tf1« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »w1x« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »w1z« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »w1y« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »w2y« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »w2z« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »w3y« wird in dieser Funktion uninitialisiert verwendet vo.txt:1: Warnung: »w3z« wird in dieser Funktion uninitialisiert verwendet Mich hat nämlich verwundert, dass überhaupt sqrt aufgerufen wird, obwohl in einem Großteil des Listings direkt die Coprozessor-Befehle auftauchten. Mal sehen, was der Optimizer macht ---- das kann aber wohl noch dauern.
Hat leider auch nichts gebracht. Ich würde vorschlagen, dass Du Deinen Term in mehrere Zuweisungen aufspaltest. Vielleicht ist ja dann etwas zu machen. Das scheint ja auch sehr verschachtelt zu sein. Die Frage ist auch, ob man mathematisch nicht etwas vereinfachen könnte, aber über den Sinn dieses Ausdrucks kann ich mir kein Urteil erlauben, da ich mir das nicht wirklich angeschaut habe. Es sieht aber nach irgendeiner Matrizen-Operation aus.
ein hübsches Monstrum. Ich würde das als Compiler auch nicht übersetzen wollen, zumal ich die freche Behauptung aufstelle, das sich in der vo.txt noch der eine oder andere Fehler verstecken könnte. Ich würde Vorschlagen den Compiler etwas zu entlasten und immer wiederkehrende Therme wie w1z*w2y*w3y erst einmal in Zwischenvariablen abzulegen, genau wie die ganzen pow - Therme Dann kann es nicht schaden, noch ein paar überschaubare Zwiscehnschritte einzufügen Zwischenwert = Zwischenwert + power(s1,2)*tf1*Power(tf2,2)*Power(tf3,2)*w1x*w2x*w2z; Zwischenwert = Zwischenwert - 2*Power(s1,2)*Power(tf1,2)*Power(tf2,2)*tf3*w1y*w2y*w2z; Zwischenwert = Zwischenwert + 2*Power(s1,2)*tf1*Power(tf2,2)*Power(tf3,2)*w1y*w2y*w2z; Zwischenwert = Zwischenwert + 2*Power(s1,2)*Power(tf1,2)*Power(tf2,2)*tf3*w1x*w1z*w3x; Bei der Gelegenheit sieht man auch gleich, ob sich noch etwas vereinfachen läßt. so kommt z.B. der Therm 2*Power(s1,2)*tf1*Power(tf2,2)*Power(tf3,2)*w1x*w2x*w2z + weit über 200 mal in Deiner Berechnung vor. Welchen Sinn soll es machen den uC das 200 mal ausrechnen zu lassen, und ich habe bei 20 dieser Therme aufgehört zu suchen. Also hier ist erst mal etwas Handarbeit in der Formel zu empfehlen.
Hallo, danke für die posts und die Übersetzungsversuche, Florian. >>gcd.c:(.text+0x1776): undefined reference to `pow' 'pow' is t doch plain C. math.h ist drin. Muß man nicht beim Linken explizit diese Mathelib einbinden? >>o.txt:1: Warnung: »w3z« wird in dieser Funktion uninitialisiert Ja, diese Variablen sind alle noch uniniatilisiert. Mact#ht aber nix, erstmal muß das Monster übersetztbar sein. Die Source ist automatisch erzeugt von Mathematica, wenn ich da händisch fummele baue ich erst Fehler ein, jetzt sollte das fehlerfrei sein. Vereinfachung ist also erstmal nicht (Simplify[] von Mathematice steigt bei dem Term auch aus) Ich brauche von dem Ding ne .exe fürn PC. Die kann ruhig groß sein und unoptimiert, Hauptsache ich kriege den Brocken kompiliert. Cheers Detlef
Also bei mir kompiliert das Dingens und generiert ein Programm, welches blblabbbb ausgibt. Kompiliert mit "gcc gcd.c -o gcd -lm -Wall", gcc version ist 4.1.2 irgendwas. gcd.c:7: warning: return type defaults to ‘int’ In file included from gcd.c:14: vo.txt:78751:6: warning: no newline at end of file gcd.c: In function ‘main’: gcd.c:9: warning: unused variable ‘b1za’ gcd.c:9: warning: unused variable ‘b1ya’ gcd.c:9: warning: unused variable ‘b1xa’ gcd.c:9: warning: unused variable ‘v0a’ gcd.c:9: warning: unused variable ‘b1z’ gcd.c:9: warning: unused variable ‘b1y’ gcd.c:9: warning: unused variable ‘b1x’ gcd.c:8: warning: unused variable ‘k’ gcd.c:17: warning: control reaches end of non-void function
Das Problem ist, dass mein Compiler pow und sqrt als inline ablegt und die tief verschachtelten Dinger dann wohl aufgrund irgendwelcher Constraints doch als Funktion aufrufen wollte. Diese Funktion gibt es aber nicht als externe Funktion; davon gehe ich zumindest aus. Vielleicht komme ich heute im Laufe des Tages dazu, die Funktion auseinaderzunehmen, d.h. zumindest die Klammertiefe zu verringern (natürlich nicht per Hand. Vielleicht hilft dem Compiler das schon. Ich darf jetzt erst einmal meine Post vom Schalter abholen, da der Postbote wohl zu faul war, meine Post zu schleppen.
> Also bei mir kompiliert das Dingens und generiert ein Programm
Oh, ich muss mir an den Kopf fassen. Es war das -lm. Richtig, da sind
sqrt und pow drin.
nun ja ,eine Formel die nur 4,493 MB im Arbeitsspeicher braucht, ohne Rechenoperationen, das wird ein lustige EXE werden ... ;-) Na mach mal, und sag uns was dabei rausgekommen ist ;-)
Schieb mal Werte rüber, um die Variablen zu initialisieren, mal schauen was rauskommt dabei...
> Also bei mir kompiliert das Dingens und generiert ein Programm
Super. Gelang das auf nem Linux System? Linux kann ich selbst nicht
probieren, habe hier GCC unter Windows laufen.
Cheers
Detlef
>>Schieb mal Werte rüber, um die Variablen zu initialisieren, mal schauen >>was rauskommt dabei... Initialisier sie doch bitte selber und schick die Initilisierung und das Ergebnis. Prüfen kann ich das dann anhand des Gleichungssystems. Cheers Detlef
Ja. Aber probier sonst mal ne neuere gcc version, vielleicht liegts ja nur daran.
Mmmkay...hab alle variablen mit 0 initialisiert, und raus kommt... nan Ok...da wird durch s1 dividiert, also sollte man vielleicht s1 nicht mit 0 initialisieren, aber andererseits müsste dann + oder - inf rauskommen und nicht nan...also...s1 mit 1 initialisiert, und raus kommt... nan Evtl. kannst du das gar nicht blindlings mit double durchrechnen, oder der generierte Code funkt nicht.
tex wrote: > nun ja ,eine Formel die nur 4,493 MB im Arbeitsspeicher braucht, ohne > Rechenoperationen, das wird ein lustige EXE werden ... ;-) > Na mach mal, und sag uns was dabei rausgekommen ist ;-) Ist das deine einzige Sorge bei heutzutagigen 2GB Arbeitsspeicher? ;)
Bei der Formel wird alles Mögliche rauskommen, nur kein einigermassen korrektes Ergebnis. Du erwartest zuviel von double. Ohne ein System, welches sowas exakt berechnen kann, hat das wenig bis gar keinen Sinn weil dich die Rundungsungenauigkeiten umbringen werden.
Ähm, ja, die Initialisierungen sind natürlich nicht beliebig, sonst muß man ne Wurzel aus ner negativen Zahl ziehen. Ich mache heute abend nen Datensatz zum Testen klar und poste den. Bartli, läuft das Programm unter Linux oder Windows? Cheers Detlef
Linux. Aber hör auf Karl Heinz: vermutlich hats eh keinen Sinn :D
> Ähm, ja, die Initialisierungen sind natürlich nicht beliebig, sonst muß > man ne Wurzel aus ner negativen Zahl ziehen. Das würde die nans erklären.
Hallo, habe es hingekriegt, es geht. Ermutigt durch den Ratschlag, das zu vereinfachen habe ich Mathematika heute nochmal ackern lassen und dabei ist tatsächlich eine Formel rausgekommen, die nur noch 2.2MB anstatt 5.5MB lang ist. Die schluckt mein GCC (4.1.2 mit Code::Blocks) und macht da ne wunderbare .exe raus. Und das Schönste: Es kommt was Richtiges raus: 3.4568..e2 (naja, almost, richtig richtig wäre 3.433742e+002). Die Genauigkeit muß ich noch ausloten, aber erstmal geht das. Karl heinz' Einwand zur Genauigkeit ist nicht von der Hand zu weisen. Aber es gibt natürlich Iterationen, bei denen öfter multipliziert/addiert wird als in dieser Formel und trotzdem was richtiges rauskommt. Oft hintereinander mul/add heißt ja nicht, daß das Ergebnis immer ungenauer wird. Fortpflanzung von Rechenfehlern ist ne harte Kiste, aber hier hats geklappt. Außerdem war der Einwand eher Motivation, es trotzdem zu probieren. Testfile mit Datensatz und kürzeres Include File habe ich angehängt. Würde mich sehr interessieren, ob die Ursprungsformel auch funzt. Danke an alle Mitwirkenden. Cheers Detlef
Kann ich frühestens Montags testen, falls ich dann noch dran denke.
gcd.c:2:19: Fehler: conio.h: Datei oder Verzeichnis nicht gefunden gcd.c:8: Warnung: Rückgabetyp ist auf »int« voreingestellt In Datei, eingefügt von gcd.c:33: cal1a.txt:28887:17: Warnung: Kein Newline am Dateiende gcd.c: In Funktion »main«: gcd.c:9: Warnung: Variable »k« wird nicht verwendet gcd.c:36: Warnung: Kontrollfluss erreicht Ende einer Nicht-void-Funktion Ein paar Änderungen, d.h. conio.h auskommentiert, int vor main eingefügt, einen Wert zurückgegeben und einen Zeilenumbruch in cal1a.txt eingefügt: chef@localhost /tmp $ date && gcc -o gcd -Wall -lm gcd.c && date Fri Jun 29 20:45:04 CEST 2007 gcd.c: In Funktion »main«: gcd.c:9: Warnung: Variable »k« wird nicht verwendet Fri Jun 29 20:45:21 CEST 2007 chef@localhost /tmp $ date && ./gcd && date Fri Jun 29 20:45:38 CEST 2007 3.456838e+02 Fri Jun 29 20:45:38 CEST 2007 chef@localhost /tmp $
Für genauere Ergebnisse könntest Du ggf. die GMP-Library benutzen und einen Floating-Point-Typ mit höherer Breite wählen. http://gmplib.org/ Das würde allerdings bedeuten, dass Du vorher Deinen Ausdruck umwandeln müsstest. Für den interessierten Hobby-Programmierer wäre dann z.B. YACC angesagt, aber hier würde es wohl auch noch mit einem Perl-Script getan sein, den Ausdruck umzubauen.
Zwecks der Genauigkeit fällt mir da spontan GMP ein (http://gmplib.org/) Ist eine Lib für beliebige Rechengenauigkeit und hoch optimiert. Wenn man irgendwie einfache Wrapper machen könnte, damit die benutzt wird, sollte es besser werden. Wiesi
Ich habe das Programm mal mit gcc 4.3 20070615 (experimental) getestet. GCC 4.3 ist in der Lage, Aufrufe von Math-Funktionen mit konstanten Argumenten zur Kompilierzeit zu berechnen. Dazu verwendet GCC die MPFR Library (http://www.mpfr.org). Das kommt dabei heraus:
1 | 08048390 <main>: |
2 | 8048390: 8d 4c 24 04 lea 0x4(%esp),%ecx |
3 | 8048394: 83 e4 f0 and $0xfffffff0,%esp |
4 | 8048397: ff 71 fc pushl 0xfffffffc(%ecx) |
5 | 804839a: 55 push %ebp |
6 | 804839b: 51 push %ecx |
7 | 804839c: 83 ec 14 sub $0x14,%esp |
8 | 804839f: c7 44 24 04 83 45 00 movl $0xe5004583,0x4(%esp) |
9 | 80483a6: e5 |
10 | 80483a7: c7 44 24 08 f0 9a 75 movl $0x40759af0,0x8(%esp) |
11 | 80483ae: 40 |
12 | 80483af: c7 04 24 d0 84 04 08 movl $0x80484d0,(%esp) |
13 | 80483b6: e8 d5 fe ff ff call 8048290 <printf@plt> |
14 | 80483bb: 83 c4 14 add $0x14,%esp |
15 | 80483be: 59 pop %ecx |
16 | 80483bf: 5d pop %ebp |
17 | 80483c0: 8d 61 fc lea 0xfffffffc(%ecx),%esp |
18 | 80483c3: c3 ret |
Ergebnis:
1 | ./gcd |
2 | 3.456838e+02 |
Das ausführbare Programm (Linux) ist übrigens insgesamt 7044 Bytes groß.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.