Ich möchte eine parallele wissenschaftliche Berechnungssoftware von Grund auf neu entwickeln. Ich möchte ein paar Gedanken darüber haben, welche Sprache ich anfangen soll. Das Programm beinhaltet das Lesen / Schreiben von Daten in TXT-Dateien und das parallele Ausführen umfangreicher Berechnungen mit vielen LU-Faktorisierungen und der Verwendung sparsamer linearer Löser. Die möglichen Lösungen, an die ich dachte, sind Fortran 2003/2008 mit OpenMP oder Co-Array, C ++ mit OpenMP Cilk + oder TBB, Python. Alle anderen dokumentierten Vorschläge sind willkommen! Ich kenne C, Fortran und Java (in dieser Reihenfolge) sehr gut. Ich habe ein paar Skripte in Python geschrieben, aber grundlegende Dinge.
Ich weiß, dass Fortran sehr schnell ist, aber schwer zu warten und zu parallelisieren. C ++ soll langsam sein, es sei denn, Sie verwenden externe Bibliotheken usw. Python gefällt mir, aber ist es realistisch, eine vollständige Software auf industrieller Ebene zu schreiben?
Die Software muss in der Lage sein, große Datenmengen zu verarbeiten und mit wissenschaftlichen Berechnungen effektiv umzugehen. Die Leistung ist von entscheidender Bedeutung.
Für den Hintergrund habe ich bereits eine funktionierende Software in Fortran geschrieben. Viele Leute waren über viele Jahre an der Entwicklung beteiligt und der Code ist wirklich schmutzig. Das Verwalten und Parallelisieren des Codes hat sich als Alptraum erwiesen, und ich denke über Alternativen nach.
Petros
Antworten:
Lassen Sie mich versuchen, Ihre Anforderungen aufzuschlüsseln:
Aus dieser Liste würde ich die folgenden Sprachen betrachten:
C, C ++, Fortran, Python, MATLAB, Java
Julia ist eine vielversprechende neue Sprache, aber die Community formiert sich immer noch darum herum und sie wurde in keinen größeren neuen Codes implementiert.
Lesen / Schreiben von Textdaten
Dies ist in jeder Programmiersprache leicht zu erreichen. Stellen Sie sicher, dass Sie Ihren E / A-Zugriff in geeigneter Weise puffern und zusammenführen, und dass alle Sprachen, die Sie berücksichtigen sollten, eine gute Leistung erbringen. Vermeiden Sie die Stream-Objekte in C ++, es sei denn, Sie wissen, wie Sie sie performant verwenden.
Starke Schnittstellen / Fähigkeit für LU-Faktorisierungen
Wenn Sie dichte LU-Faktorisierungen durchführen, sollten Sie LAPACK oder ScaLAPACK / Elemental für die parallele Funktionalität verwenden. LAPACK und ScaLAPACK sind in Fortran geschrieben, Elemental ist in C ++ geschrieben. Alle drei Bibliotheken sind performant und gut unterstützt und dokumentiert. Sie können aus jeder Sprache, die Sie berücksichtigen sollten, eine Schnittstelle zu ihnen herstellen.
Sparsame lineare Löser
Die führenden frei verfügbaren linearen Sparse-Löser sind fast alle über PETSc erhältlich , das in C geschrieben ist und gut dokumentiert und unterstützt wird. Sie können aus jeder Sprache, die Sie berücksichtigen sollten, eine Schnittstelle zu PETSc herstellen.
Leistung und Skalierbarkeit für große Datenmengen
Die einzigen Paradigmen für die parallele Programmierung, die Sie erwähnen, sind Shared Memory-basierte, was bedeutet, dass Sie keinen MPI-basierten Ansatz (Message-Passing) für die verteilte Speicherberechnung in Betracht ziehen. Nach meiner Erfahrung ist es mit einer Lösung mit verteiltem Speicher viel einfacher, Code zu schreiben, der weit über ein Dutzend Kerne skaliert. Fast alle "Universitätscluster" basieren heutzutage auf MPI, große Shared-Memory-Maschinen sind teuer und dementsprechend selten. Sie sollten MPI für Ihre Herangehensweise in Betracht ziehen, aber mein Rat gilt unabhängig von dem von Ihnen gewählten Programmierparadigma.
In Bezug auf die Leistung auf dem Knoten ist es in Fortran am einfachsten, eine gute serielle Leistung zu erzielen, wenn Sie selbst numerische Routinen schreiben. Wenn Sie ein wenig Erfahrung mit C, C ++ oder Python haben, können Sie eine sehr vergleichbare Leistung erzielen (C und C ++ sind sogar mit Fortran, Python und MATLAB innerhalb von 25% des Zeitaufwands ohne großen Aufwand tot). MATLAB tut dies durch einen JIT-Compiler und eine sehr gute lineare Algebra-Expressivität. Sie müssen wahrscheinlich entweder Cython, numpy, numexpr oder eingebettete numerische Kernel verwenden, um die beanspruchte Leistung von Python zu erhalten. Ich kann die Leistung von Java nicht kommentieren, da ich die Sprache nicht sehr gut kenne, aber ich vermute, dass es nicht weit von Pythons ist, wenn es von einem Experten geschrieben wird.
Ein Hinweis zu Schnittstellen
Ich hoffe, ich habe Sie überzeugt, dass Sie in jeder der von Ihnen in Betracht gezogenen Programmiersprachen alles tun können, was Sie wollen. Wenn Sie Java verwenden, sind die C-Schnittstellen eine kleine Herausforderung. Python bietet eine hervorragende Unterstützung für C- und Fortran-Interfaces durch ctypes, Cython und f2py. LAPACK ist bereits verpackt und über scipy erhältlich. MATLAB verfügt über alle Funktionen, die Sie in seinen nativen Bibliotheken benötigen, ist jedoch nicht leicht skalierbar oder auf Clustern besonders einfach auszuführen. Java kann C- und Fortran-Schnittstellen mit dem JNI unterstützen , ist jedoch nicht häufig in Clustern und in paralleler Software für wissenschaftliches Rechnen zu finden.
Wartbarkeit
Vieles davon hängt vom persönlichen Geschmack ab, aber der allgemeine Konsens über die Wartbarkeit besteht darin, dass Sie die Anzahl der Codezeilen in Ihrer Software minimieren, modularen Code mit genau definierten Schnittstellen schreiben und für Computersoftware bereitstellen möchten Tests, die die Richtigkeit und Funktionalität der Implementierung überprüfen.
Empfehlung
Ich persönlich hatte viel Glück mit Python und empfehle es für viele Computerprojekte. Ich denke, Sie sollten es für Ihr Projekt stark in Betracht ziehen. Python und MATLAB sind wahrscheinlich die ausdrucksstärksten Sprachen für das wissenschaftliche Rechnen. Sie können Python auf einfache Weise mit jeder anderen Programmiersprache verbinden. Mit f2py können Sie Ihre aktuelle Fortran-Implementierung verpacken und die gewünschten Teile in Python stückweise neu schreiben, während Sie sicherstellen, dass die Funktionalität erhalten bleibt. Zu diesem Zeitpunkt würde ich eine Kombination der offiziellen Python 2.7-Implementierung mit scipy empfehlen . Mit diesem Stack können Sie ganz einfach über die frei verfügbare Enthought Python Distribution loslegen .
Sie können das meiste auch in C, C ++ oder Fortran tun. C und C ++ sind sehr ansprechende Sprachen für professionelle Entwickler mit viel Erfahrung, stellen jedoch häufig neue Entwickler in Frage und sind in diesem Sinne wahrscheinlich keine gute Idee für einen akademischeren Code. Fortran und MATLAB sind im akademischen Bereich sehr beliebt, sie sind jedoch schwach in Bezug auf die erweiterten Datenstrukturen und die Expressivität, die Python bietet (denken Sie beispielsweise an ein Python-Diktat-Objekt).
Verwandte Fragen:
quelle
Neben der sehr umfassenden Antwort von Aron möchte ich einen Blick auf die verschiedenen Themen auf scicomp.stackexchange werfen, die sich mit der Frage befassten, welche Programmiersprache verwendet werden sollte - sowohl in Bezug auf die Programmgeschwindigkeit als auch auf die Frage, wie einfach oder schwierig Es soll Software in diesen Sprachen schreiben und warten.
Abgesehen von dem, was dort geschrieben steht, möchte ich einige Anmerkungen machen:
(i) Sie nehmen Co-Array-Fortran in Ihre Liste auf. Meines Wissens nach ist die Anzahl der Compiler, die es tatsächlich unterstützen, sehr gering - und meine tatsächlich Null. Der am weitesten verbreitete Fortran-Compiler ist GNU gfortran, und während die aktuellen Entwicklungsquellen eine Untergruppe von Co-Arrays analysieren, glaube ich, dass er keines davon unterstützt (dh er akzeptiert die Syntax, implementiert aber keine der Semantiken). . Dies ist natürlich eine allgemeine Beobachtung über neuere Fortran-Standards: Die Verzögerung, mit der Compiler tatsächlich neue Standards unterstützen, wird in mehreren Jahren gemessen. Compiler haben Fortran 2003 in den letzten Jahren erst vollständig implementiert und unterstützen Fortran 2008 nur teilweise. Dies sollte Sie nicht davon abhalten, etwas davon zu verwenden, wenn Sie einen Compiler haben, der unterstützt, was Sie verwenden.
(ii) Dasselbe gilt sicherlich für C ++ / Cilk +: Ja, Intel entwickelt dies auf einem Zweig von GCC, aber es ist in keinem der GCC-Releases verfügbar und wird wahrscheinlich für eine Weile nicht verfügbar sein. Sie können davon ausgehen, dass es noch mindestens 2-3 Jahre dauern wird, bis Sie Cilk + mit den auf typischen Linux-Computern installierten GCC-Versionen finden.
(iii) C ++ / TBB ist eine andere Geschichte: Das TBB gibt es schon eine Weile, es hat eine sehr stabile Oberfläche und ist mit den meisten C ++ - Compilern kompatibel, die es in den letzten Jahren gab (sowohl unter Linux als auch unter Windows). . Wir haben es in deal.II bereits seit mehreren Jahren mit guten Ergebnissen eingesetzt. Es gibt auch ein sehr gutes Buch darüber.
(iv) Ich habe meine ganz eigene Meinung zu OpenMP, nämlich dass es eine Lösung auf der Suche nach einem Problem ist. Es eignet sich gut zum Parallelisieren der inneren Schleifen, was bei sehr regelmäßigen Datenstrukturen von Interesse sein kann. Aber es ist selten, was Sie tun möchten, wenn Sie etwas parallelisieren müssen - denn was Sie wirklich tun möchten, ist, die äußeren Schleifen zu parallelisieren . Und dafür sind Lösungen wie TBB viel bessere Lösungen, da sie die Mechanismen der Programmiersprache nutzen, anstatt zu beschreiben, was außerhalb der Sprache geschieht (über #pragmas) und so, dass Sie keinen Zugriff auf Thread-Handles haben , Ergebnisstatusanzeigen usw. in Ihrem Programm.
(v) Wenn Sie experimentieren, können Sie auch einen Blick auf die neuen Programmiersprachen werfen, die für die parallele Programmierung und insbesondere für Aufgaben wie die von Ihnen beschriebenen entwickelt wurden. Es gibt im Wesentlichen zwei, die ich mir ansehen würde: X10 und Chapel . Ich habe nette Tutorials über Chapel gesehen, und es scheint gut gestaltet zu sein, obwohl beide heutzutage natürlich auch Insellösungen sind.
quelle
Im Allgemeinen würde ich, wenn Sie dieses Softwareprojekt wirklich ernst nehmen, eine vollständige Neuschreibung in der Sprache vorschlagen, in der Sie sich am wohlsten fühlen. Es hört sich so an, als würden Sie die Arbeit alleine erledigen, und daher erzielen Sie die besten Ergebnisse in der Sprache, in der Sie sich am wohlsten fühlen.
Im Hinblick auf die Parallelität möchte ich Sie jedoch dazu ermutigen, etwas über den Tellerrand hinaus zu denken. OpenMP hat seine Stärken, steckt jedoch in der Denkweise, hier und da einen sequentiellen Code zu verwenden und Parallelität herzustellen. Dasselbe gilt im Wesentlichen für Intel TBB.
Cilk ist definitiv ein Schritt in die richtige Richtung, dh es zwingt Sie dazu, Ihr Problem / Ihre Lösung in einem von Natur aus parallelen Aufbau zu überdenken. Was ich jedoch nicht mag, ist, dass es eine weitere Sprache ist . Da nur grobe Rückschlüsse auf die Beziehungen zwischen parallelen Tasks gezogen werden können, kann der Scheduler auch recht konservativ sein und sich bei bestimmten Problemen möglicherweise nicht gut skalieren lassen.
Die gute Nachricht ist jedoch, dass Sie, wenn Sie Ihre Implementierung ernst nehmen, das tun können, was Cilk tut, z. B. Ihr Problem in eine Reihe von voneinander abhängigen Aufgaben umschreiben und diese auf eine Reihe von Prozessoren verteilen. Kerne, ganz alleine, entweder mit Hilfe von Pthreads oder durch Missbrauch von OpenMP, um Prozesse zu erzeugen. Ein schönes Beispiel dafür ist der in der PLASMA- Bibliothek verwendete QUARK- Scheduler . Ein schöner Vergleich der Leistung mit Cilk ist hier zu finden .
quelle
pthreads-win32
oder innerhalb descygwin
Projekts.In den obigen Kommentaren wurde Coarray Fortran nur wenig diskutiert. Derzeit sieht die Unterstützung von Coarrays in Compilern meines Wissens nach ungefähr wie folgt aus:
Im Allgemeinen wäre ich vorsichtig, wenn ich einen Coarray-basierten Code starten würde. Die Syntax ist einfach und viel praktischer als bei Fortran / C / C ++ mit MPI, aber dann ist sie einfach nicht so umfassend. Zum Beispiel unterstützt MPI viele Reduktionsoperationen usw., die für Sie sehr praktisch sein könnten. Es würde wirklich von Ihrem Bedürfnis nach viel Kommunikation abhängen. Wenn Sie ein Beispiel wollen, lassen Sie es mich wissen und ich kann Ihnen ein paar zur Verfügung stellen, wenn ich die Dateien ausgraben kann.
quelle
Sehen Sie sich Spark an, ein verteiltes Framework für Berechnungen im Speicher, das die funktionale Programmierung nutzt. Die Struktur eines Programms in Spark unterscheidet sich stark von der in MPI. Im Grunde schreiben Sie einen Code wie für einen einzelnen Computer, der automatisch als Funktion auf Daten im Speicher verteilt wird. Es unterstützt Scala, Java und Python.
Logistische Regression (scala):
Es gibt eine Erweiterung namens MLib (Machine Learning Library), die eine Fortran-Bibliothek für einige Low-Level-Berechnungen verwendet (für Python wird vermutlich numpy verwendet). Die Idee ist also einfach, konzentrieren Sie sich auf Ihren Algorithmus und überlassen Sie Optimierungen niedrigeren Ebenen (Reihenfolge der Verarbeitung, Datenverteilung usw.).
quelle