Python in Fortran 90 einbetten

7

Ich habe mir die Option angesehen, Python in fortran90 einzubetten, um meinem vorhandenen fortran90-Code Python-Funktionalität hinzuzufügen. Ich weiß, dass es umgekehrt gemacht werden kann, indem ich python mit fortran90 unter Verwendung des f2py von numpy erweitere. Aber ich möchte meine superoptimierte Hauptschleife in Fortran behalten und Python hinzufügen, um einige zusätzliche Aufgaben zu erledigen / weitere Entwicklungen zu evaluieren, bevor ich es in Fortran machen kann, und auch die Codewartung zu erleichtern. Ich suche nach Antworten für die folgenden Fragen:

1) Gibt es bereits eine Bibliothek, aus der ich Python in Fortran einbetten kann? (Ich bin mir bewusst, f2py und es macht es umgekehrt) 2) Wie kümmern wir uns um den Datentransfer von Fortran zu Python und zurück? 3) Wie können wir eine Rückruffunktion implementiert haben? (Lassen Sie mich das Szenario ein wenig beschreiben .... Ich habe mein Programm main_fortran in Fortran, das Func1_Python Modul in Python aufrufen. Nun, von diesem Func1_Python möchte ich eine andere Funktion aufrufen ... sagen Func2_Fortran in fortran) 4) Was wäre der Einfluss der Einbettung des Interpreters von Python in Fortran in Bezug auf die Leistung .... wie Ladezeit, Laufzeit, Senden von Daten (ein großes Array in doppelter Genauigkeit) über etc.

Vielen Dank im Voraus für Ihre Hilfe !!

Edit1: Ich möchte die Richtung der Diskussion richtig einstellen, indem ich einige weitere Informationen über meine Arbeit hinzufüge. Ich beschäftige mich mit wissenschaftlichen Daten. Also würde ich viel an großen Arrays / Matrizen mit doppelter Genauigkeit arbeiten und Fließkommaoperationen durchführen. Es gibt also nur wenige Möglichkeiten, die Arbeit für mich zu erledigen. Der Grund, warum ich Python in meinen Code aufnehmen möchte, ist, dass ich NumPy für einige grundlegende Berechnungen verwenden kann, wenn nötig und die Fähigkeiten des Codes mit minimalem Aufwand erweitern. Zum Beispiel kann ich mehrere Bibliotheken verwenden, die für die Verbindung zwischen Python und einem anderen Paket verfügbar sind (zB OpenFoam mit der PyFoam-Bibliothek).

    
Ravi 12.06.2013, 21:09
quelle

5 Antworten

6

1. Tu es nicht

Ich weiß, dass Sie Python-Code in einem Fortan-Programm hinzufügen möchten, anstatt ein Python-Programm mit Fortran-Erweiterungen zu verwenden. Mein erster Ratschlag ist, dies nicht zu tun. Fortran ist bei Arithmetik schneller als Python, aber Python ist einfacher zu schreiben als Fortran, es ist einfacher, Python-Code mit OOP-Techniken zu erweitern, und Python hat möglicherweise Zugriff auf Bibliotheken, die für Sie wichtig sind. Sie erwähnen in Fortran eine superoptimierte Hauptschleife. Fortran eignet sich hervorragend für superoptimierte innere Loops. Die Logik zum Weitergeben eines Fortran-Arrays in einem Python-Programm mit Numpy ist viel einfacher als das, was Sie tun müssten, um ein Python-Objekt in Fortran korrekt zu behandeln.

Wenn ich ein wissenschaftliches Computerprojekt von Grund auf neu starte, schreibe ich immer zuerst in Python, identifiziere Leistungsengpässe und übersetze diese in Fortran. Die Möglichkeit, Fortran-Code schneller mit validiertem Python-Code zu testen, macht es einfacher zu zeigen, dass der Code korrekt funktioniert.

Da Sie bereits vorhandenen Code haben, müssen Sie den Python-Code mit einem in Fortran erstellten Modul erweitern, aber dieser Prozess sollte unkompliziert sein. Trennen Sie den Initialisierungscode von der Hauptschleife, brechen Sie die Schleife in logische Teile, wickeln Sie jede dieser Routinen in eine Python-Funktion, und dann kann Ihr Haupt-Python-Code die Fortran-Subroutinen aufrufen und diese mit Python-Funktionen verschachteln. In diesem Prozess können Sie möglicherweise einen Großteil der Optimierungen in Ihrer Hauptschleife in Fortran beibehalten. F2PY ist ein vernünftiges Standardwerkzeug dafür, so dass es nicht schwierig sein wird, Leute zu finden, die Ihnen bei allen auftretenden Problemen helfen können.

2. Systemaufrufe

Wenn Fortran-Code unbedingt Python-Code aufrufen muss, ist es am einfachsten, wenn der Fortran-Code einige Daten auf den Datenträger schreibt und den Python-Code mit SYSTEM ausführt. oder EXECUTE_COMMAND_LINE . Wenn Sie EXECUTE_COMMAND_LINE verwenden, können Sie den Python-Code als stdout ausgeben lassen, und der Fortran-Code kann ihn als Zeichendaten lesen. Wenn Sie viele Ausgaben haben (z. B. eine große Matrix), wäre es sinnvoller, wenn der Python-Code eine Datei ausgibt, die der Fortran-Code dann liest. Der Disk-Lese- / Schreib-Overhead könnte dazu führen, dass dies unerheblich signifikant ist. Außerdem müssten Sie Fortran-Code schreiben, um Ihre Daten auszugeben, Python-Code, um es zu lesen, Python-Code, um es wieder auszugeben, und Fortran-Code, um die Daten erneut einzugeben. Dieser Code sollte einfach zu schreiben und zu testen sein, aber diese vier Teile synchron zu halten, während Sie den Code bearbeiten, kann zu Kopfschmerzen führen.

(Dieser Ansatz wird in dies versucht Stapelüberlauffrage )

3. Einbetten von Python in C in Fortran

Es gibt keine Möglichkeit, ein Python-Objekt im Speicher direkt an Fortran zu übergeben. Fortran-Code kann jedoch C-Code aufrufen, und in C-Code kann Python eingebettet sein. (Siehe das Python-Tutorial zum Erweitern und Einbetten .) Im Allgemeinen ist das Erweitern von Python (wie ich es in Punkt 1 empfehle) vorzuziehen, es in C / C ++ einzubetten. (Siehe Erweiterung gegen Einbetten: Es gibt nur eine richtige Entscheidung .) Damit dies funktioniert, wird ein Alptraum, weil Kommunikationsprobleme zwischen Python und Fortran zwischen Python und C oder zwischen C und Fortran auftreten können. Ich weiß nicht, ob jemand Python tatsächlich in C in Fortran einbettet, und deshalb wird es schwierig, Hilfe zu bekommen.

    
Alex Szatmary 13.06.2013, 19:00
quelle
4

Wenn Sie Python in Fortran einbetten möchten, müssen Sie es über Fortran's C-Schnittstelle tun; Dafür ist ISO_C_BINDING zuständig. Ich warne vor der Einbettung von Python, nicht wegen der technischen Schwierigkeit dabei, sondern weil Python (die Sprache oder die Gemeinschaft) hartnäckig dagegen pocht, dass Python als untergeordnete Sprache verwendet wird. Die gängige Ansicht ist, dass jede nicht Python-Sprache, in der der Code gerade geschrieben ist, in Bibliotheken aufgeteilt und zur Erweiterung von Python verwendet werden sollte, niemals umgekehrt. Sie werden also (wie hier) mehr Antworten sehen, die versuchen, Sie davon zu überzeugen, dass Sie wirklich nicht das tun wollen, was Sie eigentlich tun möchten, als die tatsächliche technische Unterstützung.

Das ist nicht flammend oder redigierend oder moralisch urteilend; Das ist eine einfache Feststellung der Tatsache. Sie erhalten keine Hilfe von der Python-Community, wenn Sie versuchen, Python einzubetten.

Wenn Sie eine Funktionalität benötigen, die über die Fortran-Sprache selbst hinausgeht (z. B. Dateisystemoperationen) und Sie Python nicht besonders brauchen und möchten Sie eine Sprache, die aussagekräftiger ist C, möchten Sie vielleicht stattdessen Lua einbetten. Im Gegensatz zu Python ist Lua speziell dafür gedacht, eingebettet zu werden, so dass Sie wahrscheinlich viel weniger sozialen und technischen Widerstand ausgesetzt sind.

Es gibt eine Reihe von Projekten, die Fortran und Lua integrieren, die umfassendste, die ich bisher gesehen habe Aotus . Der Autor ist sehr reaktionsschnell und der Integrationsprozess ist einfach.

Zugegeben, dies beantwortet nicht die ursprüngliche Frage (wie man einen Python-Interpreter in eine Fortran-90-Anwendung einbindet), aber um fair zu sein, keine der anderen Antworten. Ich benutze Python als meine portable universelle Sprache der Wahl und würde es vorziehen, bei der Erweiterung unserer primären Produkte (in Fortran geschrieben) zu bleiben. Aus den oben genannten Gründen habe ich meine Versuche, Python einzubetten, aufgegeben und bin dazu übergegangen, Lua einzubetten; Aus sozialen Gründen empfinde ich Lua als eine viel bessere technische Wahl. Es ist nicht meine erste Wahl, aber es funktioniert, zumindest in meinem Fall.

Entschuldigung, wenn ich jemanden beleidigt habe; Ich versuche nicht, einen Kampf auszutragen, sondern erzähle nur meine Erfahrung, wenn ich dieses spezielle Thema erforsche.

    
arclight 05.08.2013 00:08
quelle
3

Ich habe mehrere Ansätze ausprobiert, um das Problem zu lösen, und ich habe einen möglicherweise optimalen Weg gefunden, dies zu tun. Ich werde kurz die Ansätze und Ergebnisse auflisten.

1) Einbetten über Systemaufruf: Jedes Mal, wenn wir von Fortran auf Python zugreifen wollen, verwenden wir den Systemaufruf, um ein Python-Skript auszuführen und Daten zwischen ihnen auszutauschen. Die Geschwindigkeit in diesem Ansatz ist durch das Lesen der Festplatte begrenzt, schreiben (in diesem Zeitalter der Cache-Level-Optimierung von Code, gehen auf die Festplatte ist eine Todsünde). Außerdem müssen wir den Interpreter jedes Mal initialisieren, wenn wir das Skript ausführen wollen, was einen beträchtlichen Overhead darstellt. Eine einfache Runge-Kutta-Methode 4. Ordnung, die 300 Mal ausgeführt wurde, dauerte ganze 59 Sekunden.

2) Von Fortran zu Python über C: Wir verwenden die ISO_C-Bindungen, um zwischen Fortran und C zu kommunizieren; und wir haben den Python-Interpreter in C eingebettet. Teile davon funktionierten, aber in der Zwischenzeit habe ich einen besseren Weg gefunden und diese Idee fallen gelassen. Ich möchte dies jedoch der Vollständigkeit halber noch auswerten.

3) Verwenden von f2py zum Importieren von Fortran-Subroutinen nach Python (Extending): Hier nehmen wir die Hauptschleife von Fortran und programmieren sie in Python (dieser Ansatz heißt Python mit Fortran erweitern); und wir importieren alle Fortran Subroutinen in Python mit f2py ( Ссылка ). Wir haben die Flexibilität, die wichtigsten Daten in jeder wissenschaftlichen Anwendung zu haben, d. H. Die äußerste Schleife (in der Regel die Zeitschleife) in Python, damit wir sie mit anderen Anwendungen koppeln können. Aber wir haben auch den Nachteil, dass wir mehr als nur benötigte Daten zwischen Fortran und Python austauschen müssen. Das gleiche Runge Kutta 4.Ordnungsbeispiel benötigte 0,372 Sekunden für die Ausführung.

4) Einbetten durch Erweiterung nachahmen: Bis jetzt haben wir die zwei reinen Ansätze der Einbettung (die Hauptschleife bleibt in Fortran und wir nennen Python wie benötigt) und Extending (die Hauptschleife bleibt in Python und wir nennen Fortran je nach Bedarf) gesehen. Es gibt einen anderen Weg, es zu tun, den ich für den optimalsten halte. Das Übertragen von Teilen der Hauptschleife in Python würde zu einem Overhead führen, der nicht immer notwendig ist. Um diesen Overhead loszuwerden, können wir die Hauptschleife in Fortran behalten, die ohne Änderungen in eine Subroutine umgewandelt wird, eine Pseudohauptschleife in Python haben, die nur die Hauptschleife in Fortran aufruft und das Programm so ausführt, als wäre es unsere unberührtes Fortran-Programm. Bei Bedarf können wir eine Callback-Funktion verwenden, um mit den erforderlichen Daten zu Python zurückzukehren, ein Skript auszuführen und wieder zu Fortran zurückzukehren. Bei diesem Ansatz benötigte die Runge Kutta 4. Ordnung-Methode 0,083 Sekunden. Ich profilierte den Code und fand heraus, dass die Initialisierung des Python-Interpreters und das Laden 0,075 Sekunden dauerte und das Programm nur 0,008 Sekunden benötigte (was 300 Callback-Funktionen für Python beinhaltet). Der ursprüngliche Fortran-Code benötigte 0,007 Sekunden. So erhalten wir fast Fortran-ähnliche Leistung mit Python wie Flexibilität mit diesem Ansatz.

    
Ravi 21.06.2013 10:08
quelle
3

Es gibt eine sehr einfache Möglichkeit, dies mit f2py zu tun. Schreiben Sie Ihre Python-Methode und fügen Sie sie als Eingabe in Ihre Fortran-Subroutine ein. Deklariere es sowohl in dem cf2py -Hook als auch der Typdeklaration als EXTERNAL und auch als seinen Rückgabewerttyp, z.B. %Code%. Ihr Fortran-Code wird dann einen Zeiger auf die Adresse haben, an der die Python-Methode gespeichert ist. Es wird LANGSAM ALS MELASSEN sein, aber zum Testen von Algorithmen kann es nützlich sein. Ich mache das oft (ich portiere eine Menge alter Spaghetti Fortran zu Python-Modulen ...) Es ist auch eine großartige Möglichkeit, Dinge wie optimierte Scipy-Aufrufe in Legacy-Fortran zu verwenden.

    
Paul Wells 18.05.2014 19:21
quelle
2

Ich habe Python gerade erfolgreich in unser hauseigenes ~ 500 KLOC Fortran-Programm eingebettet mit cffi . Ein wichtiger Aspekt war, den bestehenden Code nicht zu berühren. Das Programm ist in Fortran 95 geschrieben. Ich schrieb einen dünnen 2003 Wrapper mit dem Modul iso_c_binding , das einfach Daten aus den verschiedenen Modulen importiert, C-Zeiger auf diese Daten und / oder Fortran-Typen in C-Strukturen einfügt, alles in einen einzigen zusammenfasst type / struct und sendet an eine C-Funktion. Diese C-Funktion ist eine Python-Funktion, die mit cffi umhüllt ist. Es entpackt die C-Struktur in ein benutzerfreundlicheres Python-Objekt, umschließt Fortran-Arrays als Numpy-Arrays (kein Kopieren) und dann entweder in eine interaktive Python-Konsole oder führt ein Python-Skript basierend auf der Benutzerkonfiguration aus. Es gibt keine Notwendigkeit, C-Code außer für eine einzelne Header-Datei zu schreiben. Es gibt offensichtlich einige Gemeinkosten, aber diese Funktionalität ist für die Erweiterbarkeit und nicht für die Leistung gedacht.

Ich würde von f2py abraten. Es ist nicht gut und streng begrenzt die öffentliche Schnittstelle Ihres Fortran-Codes.

    
azag0 25.04.2016 20:16
quelle

Tags und Links