Hallo Leute, ich möchte gerne C++11 Code auf einer Default Red Hat Enterprise Linux 5 Installation ausführen. D.h. ich darf z.B. nicht das Red Hat Developer Toolset installieren. In der Default installation hat RHEL5 leider keinen C++11 fähigen Compiler... Ist es möglich, auf einer anderen Maschine (meinetwegen in einer VM) zu Kompilieren und dann einfach auf RHEL5 auszuführen? Wo sind dabei die Probleme? Danke schonmal im Voraus! (p.s. ich kenne mich mit Linux noch sehr wenig aus)
Porter schrieb: > Wo sind dabei die > Probleme? wenn du alles statisch links muss nur die gleiche Plattform vorhanden sein ( x68, 64bit, ARM ... ). Wenn du dynamisch links, müssen die die passenden Libs (z.b. glibc) auf dem System vorhanden sein (auch mit möglichst der gleichen Version). Das ganze ist aber kein Linux Problem. Das gleiche Problem hat man auch unter Windows.
Du kannst dir auch eine aktuelle Version von GCC oder Clang selbst compilieren. Habe ich hier auch gemacht (allerdings auf RHEL6). Edit: Oder was vermutlich auch geht ist einen PC/VM mit RHEL5 und dem Developer Toolset einzurichten und darauf compilieren. Nach meinem Wissen ist das Developer Toolset so konfiguriert das die compilierten Programme auch auf PCs ohne dieses Toolset laufen (indem die Standardlibrary statisch gelinkt wird etc.)
:
Bearbeitet durch User
Peter II schrieb: > Wenn du dynamisch links, müssen die die passenden Libs (z.b. glibc) auf > dem System vorhanden sein (auch mit möglichst der gleichen Version). Ich möchte gerne dynamisch linken, da ich sehr viele Threads erzeuge und Performance sehr wichtig ist. Sebastian V. schrieb: > Du kannst dir auch eine aktuelle Version von GCC oder Clang selbst > compilieren. Du meinst also, dass ich das aktuelle GCC mitliefere und dann zuerst GCC kompiliere und anschließend mit dem neuen GCC mein Programm? Sebastian V. schrieb: > Edit: Oder was vermutlich auch geht ist einen PC/VM mit RHEL5 und dem > Developer Toolset einzurichten und darauf compilieren. Nach meinem > Wissen ist das Developer Toolset so konfiguriert das die compilierten > Programme auch auf PCs ohne dieses Toolset laufen (indem die > Standardlibrary statisch gelinkt wird etc.) Das werde ich prüfen, hört sich interessant an!
Porter schrieb: > Sebastian V. schrieb: >> Du kannst dir auch eine aktuelle Version von GCC oder Clang selbst >> compilieren. > > Du meinst also, dass ich das aktuelle GCC mitliefere und dann zuerst GCC > kompiliere und anschließend mit dem neuen GCC mein Programm? Ne nicht mitliefern. Ich glaube ich hatte dein Problem anfangs falsch verstanden. Wenn du keine root Rechte hast und dir der Admin auch kein Developer Toolkit installieren will kann man sich den GCC selbst compilieren und ins Benutzerverzeichnis installieren, um an einen aktuellen Compiler zu kommen. Du willst aber scheinbar das fertig compilierte Programm auf mehreren PCs verteilen wenn ich dich richtig verstanden habe. Porter schrieb: > Peter II schrieb: >> Wenn du dynamisch links, müssen die die passenden Libs (z.b. glibc) auf >> dem System vorhanden sein (auch mit möglichst der gleichen Version). > > Ich möchte gerne dynamisch linken, da ich sehr viele Threads erzeuge und > Performance sehr wichtig ist. Was hat dynamisch/statisch linken mit Performance zu tun?
:
Bearbeitet durch User
Sebastian V. schrieb: > Was hat dynamisch/statisch linken mit Performance zu tun? Das kann man hier nachlesen: http://stackoverflow.com/questions/1993390/static-linking-vs-dynamic-linking Sebastian V. schrieb: > Ne nicht mitliefern. Ich glaube ich hatte dein Problem anfangs falsch > verstanden. Wenn du keine root Rechte hast und dir der Admin auch kein > Developer Toolkit installieren will kann man sich den GCC selbst > compilieren und ins Benutzerverzeichnis installieren, um an einen > aktuellen Compiler zu kommen. Du willst aber scheinbar das fertig > compilierte Programm auf mehreren PCs verteilen wenn ich dich richtig > verstanden habe. Es ist mir eigentlich egal, ob ich das fertig kompilierte Programm verteile, oder auf dem PC auf dem es laufen soll kompiliere. Ich entwickele halt auf einem PC, muss das fertige Programm aber auf einem anderen ausführen, wo die Admins mir fast nichts erlauben (auch nicht das Developer Toolkit). Dort habe ich auch keinen Internetzugriff. Wenn ich dich richtig verstanden habe, muss ich GCC selbst kompilieren (muss das auf dem auszuführenden Rechner passieren, einer VM mit demselben System oder egal wo?) und dann meinen Code mit deisem GCC auf dem auszuführenden Rechner kompilieren. Ist das richtig so?
Machs wie alle Welt?! Ich mein, wer entwickelt groß Programme auf dem PC auf dem sie auch ausgeführt werden. Liefere einfach das Binary mit allen dazu nötigen Libs. Wenn du nicht mehrere Prozesse ausführst, die dieselbe lib teilen, dann sollte es so gut wie gar keinen Unterschied machen, ob das ganze statisch oder dynamisch ist. Und selbst wenn das der (unwahrscheinliche) Fall ist, dann ist es immer noch sehr ungewöhnlich, wenn das aufrufen der Funktionen aus der Lib die meiste Zeit in Anspruch nehmen sollte.
Das Problem ist, dass ich sehr viele Prozesse ausführe, die sehr rechenaufwendig und zeitkritisch sind und alle hauptsächlich ein und dieselbe Funktion ausführen. Deswegen ist es hier sinnvoll, dynamisch zu linken, da so der Cache geschohnt wird.
Was jetzt? Viele Prozesse oder Threads? Bei Threads dürfte es egal sein und ich vermute auch bei Prozessen ist Linux nicht so blöd das es das gleiche Programm Tausend mal in den RAM läd. Von wie vielen Prozessen reden wir überhaupt? Und bevor wir hier noch ewig über Performance reden, hast du schonmal nachgemessen wie schnell es läuft?
Porter schrieb: > Das Problem ist, dass ich sehr viele Prozesse ausführe, die sehr > rechenaufwendig und zeitkritisch sind und alle hauptsächlich ein und > dieselbe Funktion ausführen. Deswegen ist es hier sinnvoll, dynamisch zu > linken, da so der Cache geschohnt wird. die paar Bytes die die libs brauchen, spielt doch keine Rolle bei großen Aufgaben. Oder musst du die Programm in der sekunde tausendfach starten?
Porter schrieb: > und > Performance sehr wichtig ist. und > RHEL5 passt nicht wirklich gut zusammen. Das wurde 2007 freigegeben, der Kernel 2.6.18 der da verwendet wird ist von 2006. In den 10 Jahren hat sich bei Linux einiges getan was die Performance angeht.
Sebastian V. schrieb: > Was jetzt? Viele Prozesse oder Threads? Bei Threads dürfte es egal sein > und ich vermute auch bei Prozessen ist Linux nicht so blöd das es das > gleiche Programm Tausend mal in den RAM läd. Obs Prozesse oder Threads sind, werde ich prüfen (ich schreibe nur einen seriellen Teil des Programms, nicht die Parallelisierung). Sebastian V. schrieb: > Von wie vielen Prozessen > reden wir überhaupt? Das ist noch nicht sicher. So viele, dass die Performance ein Maximum erreicht. Ich gehe aber von einigen Dutzend aus. Sebastian V. schrieb: > Und bevor wir hier noch ewig über Performance > reden, hast du schonmal nachgemessen wie schnell es läuft? Du meinst den Unterschied zwischen dynamisch und statisch? Nein, noch nicht. Kann ich vorerst auch nicht machen, weil ich momentan keinen Zugriff auf den Rechner habe. Aber ansonsten messe ich die Laufzeiten natürlich... Peter II schrieb: > die paar Bytes die die libs brauchen, spielt doch keine Rolle bei großen > Aufgaben. Oder musst du die Programm in der sekunde tausendfach starten? Es geht vor allem um den Cache. Je weniger Neuladen in den (Istruction) Caches ergibt mehr Performance. Gerd E. schrieb: >> und >> Performance sehr wichtig ist. > > und > >> RHEL5 > > passt nicht wirklich gut zusammen. Ich bin auch nicht glücklich darüber, aber es ist wies ist... Leider ist es oft so, dass wenn etwas ein mal läuft, es nie wieder angefasst wird. Auch nicht, wenn es wirklich Zeit wird...
Porter schrieb: > Es geht vor allem um den Cache. Je weniger Neuladen in den (Istruction) > Caches ergibt mehr Performance. ja und? Warum sollte Linux sind die beiden Binary die statisch gelinkt sind in den selber Speicher laden?
Peter II schrieb: > Porter schrieb: >> Es geht vor allem um den Cache. Je weniger Neuladen in den (Istruction) >> Caches ergibt mehr Performance. > > ja und? Warum sollte Linux sind die beiden Binary die statisch gelinkt > sind in den selber Speicher laden? Er lädt sie eben nicht in denselben Speicher... Deswegen wird derselbe Code mehrmals geladen, was den Cache füllt.
Also... es wird über MPI in mehreren Prozessen ausgeführt. Ist es möglich, ein portables GCC zu verwenden? Mit dynamischem Linken?
Porter schrieb: > Ist es möglich, ein portables GCC zu verwenden? Mit dynamischem Linken? Du kannst einen ganz normalen gcc verwenden. Wenn Du dynamisch linken willst, musst Du aber alle gelinkten libs in den passenden Versionen mit auf das Zielsystem kopieren. Also auf dem Entwicklungssystem mit ldd rausfinden was alles für libs in Dein Programm gelinkt wurden. Die dann alle mit auf das Zielsystem kopieren. Am besten trägt der Admin den Pfad dieser Libs dann in die /etc/ld.so.conf ein und ruft einmal ldconfig auf. Wenn er sich weigert, musst Du vor jedem Start Deines Progs den Pfad der libs in der environment-variable LD_LIBRARY_PATH hinterlegen damit der Linker die findet.
Porter schrieb: > Er lädt sie eben nicht in denselben Speicher... Deswegen wird derselbe > Code mehrmals geladen, was den Cache füllt. woran sieht du das?
Porter schrieb: > Ich entwickele halt auf einem PC, muss das fertige Programm aber auf > einem anderen ausführen, wo die Admins mir fast nichts erlauben (auch > nicht das Developer Toolkit). Warum sollte das Developer Toolkit auf dem Zielrechner nötig sein? Du entwickelst auf Deinem Entwicklungsrechner, wo Du die Tools installieren kannst die Du brauchst. Auf dem Zielrechner hast Du dann eben die fertig übersetzten Binaries und ggf. Bibliotheken.
:
Bearbeitet durch User
Porter schrieb: > muss das fertige Programm aber auf > einem anderen ausführen, wo die Admins mir fast nichts erlauben Ich frag mal ganz direkt, musst du den Job machen? Manchmal ist die beste Lösung einen Idiotenjob nicht zu machen und das Weite zu suchen. Wenn einem die Hände auf dem Rücken festgebunden werden muss man nicht unbedingt versuchen durch den Ärmelkanal zu schwimmen. Porter schrieb: > ich möchte gerne C++11 Code Auch hier die direkte Frage, gibt es für C++11 einen echten technischen Grund oder ist das nur so eine Art Liebesbeziehung und du willst nicht über deinen Schatten springen? Man könnte ja auch den alten Compiler (keine Ahnung was der Standard bei RHEL5 war) auf neuere Sprachkonstrukte verzichten und notfalls vorhandenen neueren Code zurück portieren.
Jay schrieb: > Porter schrieb: >> ich möchte gerne C++11 Code > > Auch hier die direkte Frage, gibt es für C++11 einen echten technischen > Grund oder ist das nur so eine Art Liebesbeziehung und du willst nicht > über deinen Schatten springen? Dann können wir ja auch wieder zurückgehen und programmieren alles in C oder Assembler. Technische Gründe in einer Hochsprache zu programmieren gibt es nicht.
:
Bearbeitet durch User
Sebastian V. schrieb: > Dann können wir ja auch wieder zurückgehen und programmieren alles in C > oder Assembler. Technische Gründe in einer Hochsprache zu programmieren > gibt es nicht. Nö. Es gibt massenhaft Code und Projekte die heute noch nicht beim C99 Standard angekommen sind. Es ist ja nicht so dass die Entwickler nicht gerne etwas Moderneres nehmen würden. Nur am Ende entscheidet halt der, der einem das Gehalt auszahlt. Und das ist nicht immer jemand, der softwaretechnisch die besten Entscheidungen trifft. Außerdem, warum nicht gleich C++14 nehmen? C++11 ist doch sowas von veraltet... ;-)
:
Bearbeitet durch User
Sebastian V. schrieb: > Dann können wir ja auch wieder zurückgehen und programmieren alles in C > oder Assembler. Technische Gründe in einer Hochsprache zu programmieren > gibt es nicht. Ja, ja, alles was alt ist ist scheiße, bla, bla, bla, hat nie funktioniert, bla bla bla ... und ohne Hipster-Bärtchen und Narrenkappe (https://de.wikipedia.org/wiki/Baseballcap oder https://de.wikipedia.org/wiki/M%C3%BCtze#/media/File:DreiPudelm%C3%BCtzen.jpg) kann man sowieso gar nicht programmieren.
Ich sag ja nicht, dass alles was noch nicht C++14 nutzt scheiße ist oder es keinen Grund gibt etwas in C zu programmieren. Ich sage nur, dass ich keine Lust hätte bereits vorhandenen C++11/C++14 Code zurück auf C++98 zu portieren, nur damit es unter RHEL5 compiliert.
:
Bearbeitet durch User
Porter schrieb: > Er lädt sie eben nicht in denselben Speicher... Deswegen wird derselbe > Code mehrmals geladen, was den Cache füllt. Wie kommst du darauf? Eigentlich läuft das so ab (ich gehe jetzt davon aus, dass dasselbe Programm mehrmals gestartet wird). Linux liest das Binary von der HDD um es in das RAM zu laden. Dabei steht das Gelesene erstmal im Filesystem Cache. Linux spart sich jetzt, das Binary in den "Arbeitsspeicher" zu laden um es dort auszuführen, weil es liegt ja schon im RAM (der FS-Cache). Deswegen wird dieser Teil des Cache zum Arbeitsspeicher erklärt und das Programm wird im ehemaligen Cache ausgeführt. Damit wird ein Kopiervorgang gespart. Wird das Programm nochmal gestartet, merkt der Kernel, dass es schon im Speicher steht und startet es dort. Da wird nix kopiert. Erst wenn Daten im Programm beschrieben werden, werden diese einen eigenen RAM-Bereich bekommen (copy on write). Dynamisch linken spart den RAM-Platz für die Bibliotheken, falls diese schon geladen wurden. Aber eben auch nur einmal, nicht 1000x bei 1000 Instanzen vom Programm.
:
Bearbeitet durch User
Gerd E. schrieb: > Porter schrieb: >> Ist es möglich, ein portables GCC zu verwenden? Mit dynamischem Linken? > > Du kannst einen ganz normalen gcc verwenden. Wenn Du dynamisch linken > willst, musst Du aber alle gelinkten libs in den passenden Versionen mit > auf das Zielsystem kopieren. > > Also auf dem Entwicklungssystem mit ldd rausfinden was alles für libs in > Dein Programm gelinkt wurden. > > Die dann alle mit auf das Zielsystem kopieren. Am besten trägt der Admin > den Pfad dieser Libs dann in die /etc/ld.so.conf ein und ruft einmal > ldconfig auf. > > Wenn er sich weigert, musst Du vor jedem Start Deines Progs den Pfad der > libs in der environment-variable LD_LIBRARY_PATH hinterlegen damit der > Linker die findet. Ich denke das ist die beste Lösung, danke schön! Peter II schrieb: > Porter schrieb: >> Er lädt sie eben nicht in denselben Speicher... Deswegen wird derselbe >> Code mehrmals geladen, was den Cache füllt. > > woran sieht du das? Ich kann die Links gerade nicht finden, aber ich habe es in vielen Quellen so gelesen. Mark B. schrieb: > Warum sollte das Developer Toolkit auf dem Zielrechner nötig sein? > > Du entwickelst auf Deinem Entwicklungsrechner, wo Du die Tools > installieren kannst die Du brauchst. Auf dem Zielrechner hast Du dann > eben die fertig übersetzten Binaries und ggf. Bibliotheken. Damit man zu den libraries ohne Umwege dynamisch linken kann. Jay schrieb: > Auch hier die direkte Frage, gibt es für C++11 einen echten technischen > Grund oder ist das nur so eine Art Liebesbeziehung und du willst nicht > über deinen Schatten springen? Speziell bei mir habe ich viele Datentypen und möchte den Ausgabewert einer Funktion von den Typen der Eingabeparameter abhängig machen. (z.B. 8uin8 + uint16 = uint16 usw.). Das geht in C++11 in einer Funktion, bei C++03 müste ich sehr viele überlagerte Funktionen schreiben. Jay schrieb: > Ich frag mal ganz direkt, musst du den Job machen? Manchmal ist die > beste Lösung einen Idiotenjob nicht zu machen und das Weite zu suchen. > Wenn einem die Hände auf dem Rücken festgebunden werden muss man nicht > unbedingt versuchen durch den Ärmelkanal zu schwimmen. Das Problem ist, dass nicht immer alles so einfach ist... Die Admins haben einen guten Grund, missrauisch zu sein. Die Maschine kostet 50k die Stunde, da kann man sich keinen Ausfall erlauben...
Porter schrieb: > Die Maschine kostet 50k > die Stunde, da kann man sich keinen Ausfall erlauben... 50k pro Stunde?! Mietet ihr den Tianhe-2 oder was?
Porter schrieb: > Die Maschine kostet 50k die Stunde, da kann man sich keinen Ausfall > erlauben... Was ist denn das für ein wundersames Ding? Ein Steuergerät in einer Anlage, die Medikamente produziert oder sowas in der Art? Du meinst vielleicht eher "wenn die Maschine ausfiele, dann würde das 50k pro Stunde Ausfallzeit kosten"?
:
Bearbeitet durch User
Porter schrieb: >>> Er lädt sie eben nicht in denselben Speicher... Deswegen wird derselbe >>> Code mehrmals geladen, was den Cache füllt. >> >> woran sieht du das? > > Ich kann die Links gerade nicht finden, aber ich habe es in vielen > Quellen so gelesen. Die solltest Du vielleicht nochmal genauer lesen, vermutlich hast Du sie nicht richtig verstanden. Oder diese Quellen sind falsch oder unpräzise. Diese Beschreibung hier von Fritz: Beitrag "Re: C++ auf default Red Hat Enterprise Linux 5" ist richtig. Das dynamische Linken spart Dir nur dann Speicher, wenn Du verschiedene Programme, die mit der selben Library gelinkt sind, gleichzeitig ausführst. Wenn Du das selbe Programm mehrfach ausführst ist es für den Speicherverbrauch egal welches Linking Du verwendest. Das dynamische Linken ist aber schon seit längerem die üblichere Variante. Daher werden statische Libraries (.a-Dateien) oft nicht mehr fertig mitgeliefert und das statische Linken ist bei vielen Programmen in den mitgelieferten Makefiles etc. nicht mehr vorgesehen. Daher macht es erfahrungsgemäß mehr Aufwand etwas statisch zu linken.
Sebastian V. schrieb: > 50k pro Stunde?! Mietet ihr den Tianhe-2 oder was? Nein, einen FEL. Gerd E. schrieb: > Die solltest Du vielleicht nochmal genauer lesen, vermutlich hast Du sie > nicht richtig verstanden. Oder diese Quellen sind falsch oder unpräzise. Ein Beispiel ist hier: https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&ved=0ahUKEwjq0uaH96zKAhWLlCwKHQotB8cQFghBMAQ&url=http%3A%2F%2Fwww3.nd.edu%2F~dthain%2Fcourses%2Fclassconf%2Fworts2006%2FWangLiu.ppt&usg=AFQjCNHJpaWhMgpt7OusGNeU53tbiuRwUg&cad=rja auf Folie 4. Ich hatte auch eine andere Quelle, die genau dieses Problem anging... Die sagte, dass die aktuellen Betriebssysteme das nicht unterstützen. Ich kann sie leider nicht mehr finden. Hier: http://stackoverflow.com/questions/1993390/static-linking-vs-dynamic-linking wird das auch angeschnitten (Unless modern OS's are smart enough to notice identical segments in statically linked binaries. Seems hard, anyone know?), aber nicht wirklich geklärt. Theoretisch ist das natürlich möglich, aber praktisch ist das nicht ganz so einfach. Ein neuer Prozess hat seinen eigenen virtuellen Speicher, der auf physikalischen Speicher (RAM) gemapped wird. Theoretisch könnte man diesn Speicher also auf denselben physikalischen Speicher (RAM) mappen. Dafür müsste man aber wissen, dass genau das schon im RAM liegt und wo es liegt. Aktuell schein es noch nicht implementiert zu sein (wie gesagt, für verschiedene Prozesse, natürlich geht das für threads). Wenn ein Programm auf Speicher zugreift, dann gibt es ja eine virtuelle Adresse an, die in seinem Virtuellen RAM liegt. Dass diese virtuelle Adresse auf eine Library zeigt, die gerade im Speicher eines anderen Prozesses liegt ist ja nicht trivial.
Anstatt hier ewig rumzuspekulieren, teste doch einfach ob es einen Unterschied macht. Ist doch jetzt nicht so der riesen Act und mich würde das Ergebnis auch mal interessieren.
Peter II schrieb: > Porter schrieb: >> Es geht vor allem um den Cache. Je weniger Neuladen in den (Istruction) >> Caches ergibt mehr Performance. > > ja und? Warum sollte Linux sind die beiden Binary die statisch gelinkt > sind in den selber Speicher laden? Copy-On-Write.
Porter schrieb: > Theoretisch ist das natürlich möglich, aber praktisch ist das nicht ganz > so einfach. Ein neuer Prozess hat seinen eigenen virtuellen Speicher, > der auf physikalischen Speicher (RAM) gemapped wird. Theoretisch könnte > man diesn Speicher also auf denselben physikalischen Speicher (RAM) > mappen. Dafür müsste man aber wissen, dass genau das schon im RAM liegt > und wo es liegt. Aktuell schein es noch nicht implementiert zu sein (wie > gesagt, für verschiedene Prozesse, natürlich geht das für threads). Wenn > ein Programm auf Speicher zugreift, dann gibt es ja eine virtuelle > Adresse an, die in seinem Virtuellen RAM liegt. Dass diese virtuelle > Adresse auf eine Library zeigt, die gerade im Speicher eines anderen > Prozesses liegt ist ja nicht trivial. Mit einer Ausnahme gibt es unter UNIX-Systemen nur eine Möglichkeit, einen neuen Prozeß zu starten: nämlich den Systembefehl fork(). Dieser erzeugt immer eine exakte Kopie des Prozesses, der ihn aufgerufen hat. Um ein anderes Programm zu starten, braucht es daher eine Systemfunktion aus der exec()-Familie, die das Abbild des aufrufenden Prozesses durch ein neues Prozeßabbild ersetzt. (Auf clone() gehen wir jetzt mal nicht näher ein.) Mit diesem Vorwissen können wir uns jetzt ein wenig genauer anschauen, was beim fork() mit dem Speicher passiert. Da dasselbe Programm bereits in den Speicher geladen ist und unser Betriebssystem das weiß, reserviert es zwar Speicher für das Prozeßabbild, mappt aber in Wirklichkeit das Prozeßabbild des existierenden Prozesses readonly in den neuen Prozeß, der davon jedoch nichts mitbekommt. Als Ergebnis haben wir jetzt zwei Prozesse, für die zwar jeweils Speicher reserviert worden ist, von dem aber nur der Speicher des ersten Prozesses benutzt wird. Erst wenn der zweite Prozeß auf eine der Speicherseiten des ersten Prozesses schreibt, wird diese Speicherseite physikalisch kopiert und verändert. Allerdings ist ein reservierter, aber ungenutzter Speicher nicht verloren. Sobald unserem System der Speicher ausgeht, beginnt es nämlich, den ungenutzten Speicher anderweitig zu benutzen. Dieses Verhalten ist sehr klug, denn es führt teure Kopieroperationen im Speicher nur dann aus, wenn sie wirklich notwendig sind. Andererseits ist es für Menschen, die damit nicht vertraut sind, ziemlich verwirrend, denn aus der Sicht der meisten Werkzeuge sieht es tatsächlich so aus, als ob Speicher für den geforkten Prozesses tatsächlich benutzt würde -- auch wenn das in Wirklichkeit gar nicht der Fall ist. Du siehst auch, daß die Sache aus Betriebssystemsicht vollkommen trivial ist, weil das System sich immer darauf verlassen kann, daß ein fork() nur eine virtuelle Kopie des laufenden Prozesses erzeugt. Die beiden Techniken, auf denen dieses Systemverhalten beruht, heißen übrigens "Copy-On-Write" und "Overcommit Memory". Letzteres wird zwar heute vorwiegend im Kontext von Virtualisierung diskutiert, jedoch in den Kerneln von Linux, Solaris und AIX (sowie mW. auch WinNT) auch für normale Prozesse angewendet. Das bisher Gesagte funktioniert natürlich nur, wenn das Betriebssystem wie im Falle des fork()-Systembefehls weiß, daß der neu erzeugte Prozeß eine exakte Kopie eines existierenden Prozesses ist, beziehungsweise: daß eine neu reservierte Speicherseite eine exakte Kopie einer bereits bestehenden Speicherseite ist. Wenn der geforkte Prozeß eine Funktion aus der exec()-Familie ausführt, ist das aber (meistens) gerade nicht der Fall. Wie kann unser Betriebssystem nun feststellen, daß eine neu geladene Speicherseite denselben Inhalt hat wie eine bereits existierende? Nicht mit vertretbarem Verwaltungsaufwand, das kann es gar nicht. Deswegen wurde die Technik des dynamischen Linkens erfunden. Dabei wird der Code so übersetzt, daß er positionsunabhängig aufgerufen werden kann, mithin also keine absoluten Speicheradressen benutzt, sondern nur relative Sprünge. Außerdem enthält solcher Code eine Sprungtabelle, in welcher die vorhandenen Symbole auf die Einsprungpunkte der jeweiligen Funktionen gemappt werden. Das Ergebnis eines solchen Übersetzungsvorganges nennt sich unter UNIX-Systemen "shared object" (.so) und unter Windows "dynamik link library" (.dll). Neben dem speziell übersetzten Code gehört zum dynamischen Linken auch noch ein dynamischer Linker. Der führt Buch darüber, in welche Speicherseite er welche Bibliothek geladen hat, slädt noch nicht geladene Bibliotheken und tellt den Programmen die darin befindlichen Funktionen bereit. Selbstverständlich müssen Programme, die die Funktionalität des dynamischen Linkers benutzen wollen, dazu entsprechend vorbereitet sein. Sie können nicht einfach, wie bei herkömmlichen Funktionsaufrufen, in die Funktion springen, deren Adresse ihnen bekannt ist. Stattdessen müssen sie die dynamische Lib mit dlopen() laden, mit dlsym() einen Zeiger auf die gewünschte Funktion holen, und diese dann aufrufen -- mit dem gesamten Overhead (Sicherung der Register, Positionierung der Parameter auf dem Stack, ...). Wohlerzogene Compiler verbergen das vor dem Entwickler... :-) ...
Porter schrieb: > Ein Beispiel ist hier: > https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&ved=0ahUKEwjq0uaH96zKAhWLlCwKHQotB8cQFghBMAQ&url=http%3A%2F%2Fwww3.nd.edu%2F~dthain%2Fcourses%2Fclassconf%2Fworts2006%2FWangLiu.ppt&usg=AFQjCNHJpaWhMgpt7OusGNeU53tbiuRwUg&cad=rja > auf Folie 4. > > Ich hatte auch eine andere Quelle, die genau dieses Problem anging... > Die sagte, dass die aktuellen Betriebssysteme das nicht unterstützen. > Ich kann sie leider nicht mehr finden. > > Hier: > http://stackoverflow.com/questions/1993390/static-linking-vs-dynamic-linking > wird das auch angeschnitten (Unless modern OS's are smart enough to > notice identical segments in statically linked binaries. Seems hard, > anyone know?), aber nicht wirklich geklärt. Die beschreiben alle ein anderes Problem als Deines: Viele verschiedene Programme nutzen die selbe Bibliothek. Da ist in der Tat dynamisches Linken die richtige Methode. Du hast aber einen Spezialfall: Du hast ein einziges Programm, welches mehrfach gestartet wird, also als mehrere Prozesse läuft. Zumindest hab ich Dich so verstanden. Dieses eine Programm liegt nur einmal im Dateisystem und wird von dort auch nur einmal in den Arbeitsspeicher geladen. Egal wie häufig Du es startest, egal wieviele Prozesse Du damit erzeugst. Die genauen Schritte hat Fritz oben beschrieben. Lies Dir seinen Post nochmal ganz genau durch. > Theoretisch könnte > man diesn Speicher also auf denselben physikalischen Speicher (RAM) > mappen. Dafür müsste man aber wissen, dass genau das schon im RAM liegt > und wo es liegt. In Deinem Fall geht das nicht nur theoretisch, sondern wird in der Praxis von Linux seit Jahrzehnten so gemacht: Anhand der Inode-Nummer vom Dateisystem kann der Kernel ganz genau wissen, ob dieser Teil schon im RAM vorliegt oder nicht. Und wenn ja, dann lädt er ihn nicht nochmal, sondern verknüpft ihn einfach mit der entsprechenden Page im RAM.
:
Bearbeitet durch User
@ Sheeva Plug: Danke für die ausführliche Beschreibung! Ich befürchte, dass MPI es genau mit exec() ausführt, weil man es ja sogar auf verschiedene PCs verteilen kann. Gerd E. schrieb: > Du hast aber einen Spezialfall: Du hast ein einziges Programm, welches > mehrfach gestartet wird, also als mehrere Prozesse läuft. Zumindest hab > ich Dich so verstanden. Genau richtig. Wie Sheeva Plug es beschrieben hat, hängt es davon ab, ob die Prozesse mit fork() oder exec() gestartet wurden. Ich habe vorher nicht an fork gedacht und dem dazugehörigen copy on write Mechanismus.
Sebastian V. schrieb: > Was jetzt? Viele Prozesse oder Threads? Bei Threads dürfte es egal sein > und ich vermute auch bei Prozessen ist Linux nicht so blöd das es das > gleiche Programm Tausend mal in den RAM läd. Von wie vielen Prozessen > reden wir überhaupt? Und bevor wir hier noch ewig über Performance > reden, hast du schonmal nachgemessen wie schnell es läuft? Beim statisch gelinkten Programm gibt es das .text-Segment auch bei 1000 laufenden Proczessen nur ein mal. Dynamisch gelinkt natürlich auch, nur braucht man zwischen den verschiedenen .text-Segmenten, jede Shared-Lib hat ja ihr eigenes, irgendwelchen Glue-Code. Die Lib's werden ja nicht an für jede Lib eindeutige Adressen geladen, es muß also in jedem Prozess privaten Code dafür geben. Selbst wenn 100 Prozesse das selbe Programm ausführen und somit auch der Glue-Code geshared werden könnte: ohne Glue-Code, sprich statisch gelinkt ist schneller. Resourcenschonend wird "dynamisch" erst wenn unterschiedliche Programme die selbe SharedLib verwenden. BTW, bei WinNT braucht der Glue-Code je DLL mindestens eine 4k-Page, auch wenn es nur um eine exportiert Funktion geht. Oder man weißt der DLL eine eindeutige Adresse zu, die dann in allen Prozess-Adressräumen immer an der selben Stelle eingeblendet wird (falls das heute noch so ist, hab vor 15Jahren zuletzt auf der Ebene mit NT zu tun gehabt). Linux dürfte die Selbe Lösung für das gleiche Problem benutzen. Nur hat man heute nur ungern exakt vorhersehbare Lade-Adressen, denn diese sind vor allem bei Viren beliebt.
Porter schrieb: >> Du hast aber einen Spezialfall: Du hast ein einziges Programm, welches >> mehrfach gestartet wird, also als mehrere Prozesse läuft. Zumindest hab >> ich Dich so verstanden. > > Genau richtig. Wie Sheeva Plug es beschrieben hat, hängt es davon ab, ob > die Prozesse mit fork() oder exec() gestartet wurden. Ich habe vorher > nicht an fork gedacht und dem dazugehörigen copy on write Mechanismus. Nö. Das mit dem Dateisystemcache und dessen Mapping in den Speicher willst Du wohl irgendwie nicht verstehen. Es ist ganz egal ob fork() oder exec() verwendet wird, wenn das ausgeführte Programm nur einmal im Dateisystem liegt.
Gerd E. schrieb: > Porter schrieb: >>> Du hast aber einen Spezialfall: Du hast ein einziges Programm, welches >>> mehrfach gestartet wird, also als mehrere Prozesse läuft. Zumindest hab >>> ich Dich so verstanden. >> >> Genau richtig. Wie Sheeva Plug es beschrieben hat, hängt es davon ab, ob >> die Prozesse mit fork() oder exec() gestartet wurden. Ich habe vorher >> nicht an fork gedacht und dem dazugehörigen copy on write Mechanismus. Die Funktionen der exec()-Familie starten keine Prozesse, sondern ersetzen ein existierendes Prozessabbild durch ein neues. > Nö. Das mit dem Dateisystemcache und dessen Mapping in den Speicher > willst Du wohl irgendwie nicht verstehen. Es ist ganz egal ob fork() > oder exec() verwendet wird, wenn das ausgeführte Programm nur einmal im > Dateisystem liegt. Das oben Beschriebene hat mit dem Dateisystem nur insoweit zu tun, als die Funktionen der exec()-Familie das neue Programm tatsächlich aus dem Dateisystem laden. Daß sich eine ausgeführte Programmdatei bereits im Dateisystempuffer befindet, ist ziemlich wahrscheinlich, aber für den oben erklärten Teil ist das irrelevant. Ein fork() hingegen erzeugt (startet) einen neuen Prozeß als Kopie des aufrufenden Prozesses. Das Betriebssystem weiß deswegen a) daß es das neu gestartete Programm bereits im Arbeitsspeicher hat, sowie b) sogar ganz genau, wo es zu finden ist. Damit haben das Dateisystem und sein Puffer aber nichts zu tun.
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.