Scala Scala-Kritik

Landei

Top Contributor
Zu Scala wurde hier schon genug gesagt, aber das hier kann ich beim besten Willen nicht so stehenlassen:

Also ich finde es schön dass es zb in C++/Java primitive Datentypen gibt. Sie sind für mich wie kleine Helfer, wie Bauer im Schach, wie eine Ausnahme eines Regels... Alles unter ein Dach zu bringen, wie in Scala, finde ich überhaupt nicht innovativ, dafür aber ziemlich primitiv.

Tolle Ausnahme, die uns quer im restlichen Getriebe liegt! Generics mit Primitiven? Sorry, geht nicht, aber wir haben ja diese hübschen Wrapper, da können wir ganz fein hin- und herboxen. Na ja, wenigstens solange die Wrapper nicht null sind.

Und die Primitive kann man auch sooo gut verallgemeinern, sie haben ja auch einen gemeinsamen Obertyp, nämlich... Ach halt, das waren nur die Wrapper, für die es Number gibt....

Ehrlich, langsam habe ich das Gefühl, das zu langer Java-Kontakt eine Mischung aus Stockholm-Syndrom und Lobotomie auslöst...
 

Marco13

Top Contributor
Arguing on the net? Win or lose, you're still an ... also, kein Grund polemisch zu werden ;)

Sicher, manche Beiträge lassen Objektivität (und Fundiertheit) vermissen, aber Es gibt unterschiedliche Ansichten und Schwerpunkte und Ziele - und Stellen, an denen man mal einen rohen array von echten bytes (ja, einfach nur 8 bit, kein Byte-Objekt) braucht. Es wäre vielleicht besser, wenn das nicht so wäre, aber die historische Entwicklung von C über C++ bis Java kann man ja nicht einfach ausblenden - und bei der Frage, ob Java diesen Erfolg gehabt hätte, wenn es nicht dieses Zugeständnis an seine C-Wurzeln gemacht hätte, ist schwerer zu beantworten, als die Frage wo oder was Scala wäre, wenn es Java nicht gegeben hätte...

In einer perfekten Welt ... ... :reflect:
 

Dit_

Bekanntes Mitglied
also ich wollte jetzt keinen Scala-fan beleidigen :oops:

dann heisst es also Scala ist mehr so eine Art Forschungssprache? Wer kommt denn sonst auf die Idee unglaublich komplizierte Dinge auf einer höheren Ebene zu beschreiben. Jetzt bitte nicht falsch verstehen, mir geht es nur um die Industrietauglichkeit von Scala im Bereich Web, Mobile (Apps) usw das was halt zur Zeit gefragt ist.
Selbst wenn es Scala erlaubt ein Problem besser zu beschreiben, bin ich mir sicher, es wird einen anderen Programmieren geben der sagen würde: "In Programmiersprache XY geht es noch einfacher und abstrakter..."

Habe ein interessante Umfrage gefunden: Auswertung_der_Scala_Umfrage.pdf

Dabei würde ich folgendes gern zitieren (was ich eigentlich oben sagen wollte):
"Ich kann der Argumentation, dass der immer kürzer werdende Code lesbarer sein soll, nicht folgen. Man braucht immer mehr implizites Wissen, um zu verstehen, was da eigentlich passiert. Was der Entwickler dann ursprünglich wollte, war dann im Zweifel nochmal etwas komplett anderes."

und das hier

Damit eine Sprache wirklich große Akzeptanz erlangt ist es m.E. extrem wichtig und einer der Erfolgsfaktoren von Java, dass fremder Code leicht lesbar ist. Leider gibt es in Scala ein paar Dinge, die dem entgegenstehen. Besonders negativ wirkt sich die Verwendung von mehr oder weniger sinnvollen Zeichenkombinationen als Operatoren aus. So würde ich die Freiheit, Bezeichner als Operatoren zu verwenden, eindeutig wieder einschränken.

Besonders heute finde ich wichtig: "dass fremder Code leicht lesbar ist". Man kann nicht von jedem Programmierer erwarten (selbst wenn es nur ein Student ist) das man sich mit einer Sprache auskennt die nur bei bestimmten, speziellen Problemen eingesetzt wird.
In der Forschung, an der Uni, Profs unter sich... da geht es bestimmt, aber es ist eine andere Liga.


P.S. zum Thema kleine Helfer... du könntest einfach mal nachdenken was ich damit sagen wollte... Das war vielleicht einwenig primitiv ausgedrückt, aber leider kann das nicht komplexer und abstrakter beschreiben...
Wenn ich in einer schleife
Code:
for(int i = 0;...)
Variable i verwende, so ist es für mich viel logischer und intuitiver das i nur eine Zahl ist. Sie soll überhaupt keine anderen Eigenschaften (wozu den auch?) haben. Ich brauche kein Objekt für diese Aufgabe.
Ein Haus ist ein Objekt, eine Zahl dagegen ist für mich etwas kleines, nicht wirklich (physikalisch) existierendes. Warum muss es dann unbedingt in einer Programmiersprache so überbewertet werden?.. Nur eine Zahl, ich möchte es zu einem bestimmten Punkt auf dem Stack ablegen X-mal erhöhen und vielleicht danach nie wieder verwenden. Es ist für mich wirklich ein kleiner, elementarer Helfer.
:oops:
 

Dit_

Bekanntes Mitglied
Und die Primitive kann man auch sooo gut verallgemeinern, sie haben ja auch einen gemeinsamen Obertyp, nämlich... Ach halt, das waren nur die Wrapper, für die es Number gibt....
Falls du irgendwann auf die Idee kommts primitive Typen zu verallgemeinern, dann hast du einfach mißverstanden wo man die primitive Datentypen einsetzen soll und was deren Vorteil ist und warum sie nicht nur in Java unentbehrlich sind.
 
G

Guest2

Gast
Moin,

Weil hier das Stichwork Quicksort gefallen ist, schlage ich nochmal den Bogen zu einem meiner Beiträge weiter oben : Einer der Hauptgründe, weswegen ich mir Scala mal ansehen wollte, war, dass ich gehofft hatte, dass es damit möglich sein könnte, eine Domänenspezifische Sprache zu erstellen, die ähnlich kompakt und mächtig ist wie NESL. Die Frage, warum 10 Zeilen beinahe-Pseudocode (auch wenn sie ein "<%" enthalten) vorteilhaft sein können, stellt sich vielleicht gar nicht mehr, wenn die Alternative dazu aus 1700 Zeilen kryptischem Spezialcode besteht: Making Parallel Programming Easy and Portable . Das geht eben praktisch nur so schön, wenn man eben nicht mit einer for-Schleife auf einem rohen Array rumhantiert (aka Code schreibt, bei dem eine 1:1-Übersetzung in Assembler reine Fleißarbeit wäre) sondern das, was zu tun ist auf einer höheren Ebene beschreibt.

vielleicht verstehe Deinen Einwand nicht ganz, aber die 1700 Zeilen beziehen sich doch auf eine konkrete alternative rohe MPI Quicksort Implementierung. Imho ist der Vergleich so nicht fair. Würde man die 1700 MPI Zeilen in ein "void quicksort(final byte[] values)" "verstecken", wäre der Vergleich 10 Zeilen DSL vs. 1 Zeile Java. Egal wie später die Problemstellung für den Rechner formuliert wird, der Rechenaufwand ist dabei immer gleich. Und die Länge (in Codezeilen) der Aufgabenstellung (evtl. DSL) vermutlich umgekehrt proportional zu den möglichen Freiheitsgraden innerhalb der Problemstellung.

Und bei Scala kann ich mich des Eindrucks nicht erwähren, dass dabei besonders gerne abgefahrene Syntaxspielchen eingesetzt werden. Ich meine ein

Code:
#pragma omp parallel for
for (i = 0; i < N; i++)
    a[i] = 2 * i;

gibt es jetzt seit bald 15 Jahren. Das ist zwar natürlich nicht so mächtig wie eine abgefahrene mit Scala umgesetzte DSL. Der Vorteil ist jedoch, dass es praktisch von jedem Schüler gelesen werden kann, welcher irgendwann und irgendwo schon mal irgendein Programm gelesen hat.

Unabhängig davon halte ich den Vorteil, den funktionale Programmierung im Bezug auf Multi/Manycore Anwendungen haben soll, für überbewertet. Damit daraus ein Vorteil für den normalen Anwendungsentwickler entsteht, müssen imho einige Randbedingungen erfüllt sein: Das Problem sollte

- überhaupt parallelisierbar sein
- eine kritische Problemgröße aufweisen (zu groß für singe core, klein genug für SMP)
- nicht trivial parallelisierbar sein (sonst gibt es effizientere Ansätze)
- nicht sowieso ständig auf IO warten (Benutzer, Daten, ..)

Also zumindest mir fällt da nicht sonderlich viel ein. Die meisten Probleme sind einfach so irrelevant das sie auch auf einem single core noch akzeptabel laufen oder lassen sich eben trivial parallelisieren. Auf der anderen Seite stehen dann doch nur noch die GPU Fetischisten (z.B. mit OpenCL) oder die Leute die richtig rocken wollen (z.B. mit OpenMP / MPI). Das sind aber absolute Nischen, nichts was für die breite Masse der Entwickler von Interesse wäre.

Was die vermeintlichen Vorteile von Scala angeht, also ich habe diesen Thread (und auch all die anderen dazu) gelesen, könnte aber leider nichts entdecken, was für eine general purpose Sprache von Bedeutung wäre. Imho ist Scala ein tolles Projekt und wird auch sicher seine Nische finden, aber als general purpose language sehe ich da nichts.

Und zum Schluss: Der oben erwähnte Abschnitt aus dem Buch Scala für Umsteiger (Seite XII ff.) ist ja wohlwollend höchstens noch polemisch zu verstehen. Ich meine z.B., "Die Befehle zur Concurrent-Programmierung liegen in OO-Sprachen auf Assembler-Niveau." WTF? Der gute Mann sollte sich vielleicht mal einen HPC Kurs in z.B. Java zu Gemüte führen (und versuchen Vergleichbares in Assembler zu realisieren), ehe er merkwürdige Thesen in Büchern niederschreibt.

Viele Grüße,
Fancy
 
B

bygones

Gast
Ein Haus ist ein Objekt, eine Zahl dagegen ist für mich etwas kleines, nicht wirklich (physikalisch) existierendes. Warum muss es dann unbedingt in einer Programmiersprache so überbewertet werden?.. Nur eine Zahl, ich möchte es zu einem bestimmten Punkt auf dem Stack ablegen X-mal erhöhen und vielleicht danach nie wieder verwenden. Es ist für mich wirklich ein kleiner, elementarer Helfer.
:oops:
das ist aber mehr als willkuerlich dann, also was nun ein Objekt sein darf und was nicht (Zahl ist im englischen Number und schwups haben wir ein Objekt). Auch diese "aengstliche" annahme, dass man primitive Typen ja nicht als Objekt sehen sollte versteh ich nicht. Was ist schlimm wenn es nur noch eine Klasse int gibt ?
Neben den Argumenten von Landei kommt noch hinzu dass man aufgrund der Restriktion von primitiven Typen anfaengt statische Elemente einbauen zu muessen (nicht nur ich will, sondern ich muss).
Methode abs() aus Math muss eine statische Methode einer anderen Klasse sein, weil int leider damit nicht umgehen kann. Es ist aber eine Fachlichkeit einer Zahl ihren absolut Betrag zu wissen.

( aber das ist nochmal eine komplett andere Diskussion )

Zu dem quicksort bsp muss ich noch sagen dass ich eher ueberrascht bin, dass das zu lesen ist. Ich habe mich nicht sehr viel mit Scala selbst beschaeftigt, doch als Informatiker sollte man in der lage sein mit etwas denken diesen Code zu verstehen. Ich sage nicht dass man ihn so moegen muss, aber das Argument nicht verstaendlich kann ich nicht nachvollziehen
 

Bronko

Mitglied
Moin,
Und zum Schluss: Der oben erwähnte Abschnitt aus dem Buch Scala für Umsteiger (Seite XII ff.) ist ja wohlwollend höchstens noch polemisch zu verstehen. Ich meine z.B., "Die Befehle zur Concurrent-Programmierung liegen in OO-Sprachen auf Assembler-Niveau." WTF? Der gute Mann sollte sich vielleicht mal einen HPC Kurs in z.B. Java zu Gemüte führen (und versuchen Vergleichbares in Assembler zu realisieren), ehe er merkwürdige Thesen in Büchern niederschreibt.

Viele Grüße,
Fancy

Mir ist klar was er damit aussagen wollte. ich weis zwar nicht was ein HPC Kurs ist aber ich denke den könnte man auch direkt bei dem Informatik Prof. nehmen ;)
Esser Friedrich

Ich fasse mal zusammen:

-Scala ist kryptisch und fremdartig
-Man kann nicht besser damit Entwickeln im vergleich zu Java
-Viele Scala Features sind unnötig
-Yet Another VM Language

Für mich hört sich das an als ob man sich an das althergebrachte klammern möchte. Wer hat sich den wirklich mal damit beschäftigt (Coden) über mehrere Wochen oder Monate? Wer hat sich mal ein Buch zu dem Thema gegönt?

Das Scala performanter als Java ist (Google Ausarbeitung) stört keinen. Das Martin Odersky selber mal ein Mitentwickler der Java VM war und weis wie der Hase läuft oder James Gosling Scala Befürworter ist und die EU mit 2.3 mio Euro Scala fördert ist wahrscheinlich alles kein Argument aber sollte das nicht mal Motivation geben sich mal länger auf das Thema einzulassen?
 

Landei

Top Contributor
Falls du irgendwann auf die Idee kommts primitive Typen zu verallgemeinern, dann hast du einfach mißverstanden wo man die primitive Datentypen einsetzen soll und was deren Vorteil ist und warum sie nicht nur in Java unentbehrlich sind.

Warum ist es eine dumme Idee, einmal sowas zu schreiben...

Java:
public static number square(number n) {
  return n*n;
}

...statt...

Java:
public static byte square(byte n) {
  return n*n;
}
public static short square(short n) {
  return n*n;
}
public static int square(int n) {
  return n*n;
}
...

???

Wie das der Compiler intern umsetzt, ist doch eine ganze andere Frage (wie z.B. Scala sehr schön zeigt).

Ich finde es amüsant, wie man einerseits auf Scalas Schwachstellen herumhackt und sich andererseits Javas kapitale Böcke schönredet. Wie gesagt: Nichts gegen sachliche Scala-Kritik, aber dann muss auch Java auf den Prüfstand...
 
G

Gelöschtes Mitglied 6946

Gast
Ich arbeite mit Java, finde Scala interessant, habe damit aber noch nichts gemacht (außer mir mal ein Scala-Buch durchzulesen und so). Mir gefällt die Möglichkeit, so mehr oder weniger wie in Java zu programmieren, aber weniger Boilerplate-Code zu haben. Dadurch werden die Programme kürzer und lesbarer - ich würde (erstmal) keine abgefahrenen Sachen machen, vom Verständnis wäre es also wie in Java, aber mit weniger Müll drumrum. Mag nicht nach einer Riesensache klingen, aber fände ich schon praktisch. Mal ein Beispiel von mir auf Arbeit, Operationen mit Matritzen:

Java:
SimpleMatrix mS = mD.minus(mB.transpose().mult(mAi).mult(mB));

In Scala oder Sprachen mit Operator-Überladung wird das schon sehr viel lesbarer:

Java:
val mS = mD - (mB.tr * mAi * mB)

Dazu kommen Kleinigkeiten wie kein Schreiben (und Lesen) von Gettern nötig, kein doppeltes Angeben von Typen bei Deklaration + Definition nötig und hie und da mal die Übergabe von einer Funktion zum Sortieren, Filtern oder Umformen von Listen. Das alles erscheint mir erstmal recht praktisch. Aber wie in jeder Sprache kann man es natürlich auch übertreiben - in dieser vielleicht eher, als in anderen, weil man viele Möglichkeiten hat. Aber wenn ich mir manches C++ Programm anschaue... Letztlich hat der Programmierer natürlich eine gewisse Verantwortlichkeit. Ich denke aber auch, dass es in Java schwieriger ist, wirklich abartigen Code zu schreiben (die Möglichkeiten bei C++ oder Scala sind da einfach größer), so dass ich nicht glaube, dass Scala Java in jedem Fall ersetzen sollte.

PS: Ich arbeite selber im akademischen Umfeld (habe daher auch mehr mit mathematischem Zeugs und Algorithmen zu tun, so wie im Beispiel oben). Nichts desto trotz würde ich Scala (oder eine ähnliche Sprache) auch für Webanwendungen oder sowas einsetzen, einfach weil es Schreib- und Lesarbeit spart. Solang man es nicht mit abgefahrenen Konstrukten übertreibt...
 

Marco13

Top Contributor
Ich sehe im Moment auch die fehlende Generizität für primitive Datentypen als eine der größten Schwächen von Java (in bezug auf den echten "Sprachkern"). Wenn man sich die Redundanz in Arrays (Java Platform SE 6) anschaut, rollen sich einem die Fußnägel hoch. Und jeder, der schonmal in Erwägung gezogen hat, sich einen Codegenerator zu schreiben, um einen Satz von Methoden für alle primitiven Typen anzubieten, weiß, dass das ein Krampf ist :autsch:

Ich denke aber, dass die Lösung dafür NICHT (!) darin bestehen sollte, alle primitiven Typen zu Objekten zu erheben. An manchen Stellen braucht man 1 Million bytes als zusammenhängenden Speicherblock, und eben bitteschön nicht 1 Million 4 oder 8 byte große Referenzen, die ins Heap-Nirvana zeigen. Wie Landei ja auch gesagt hat: Da was dran zu machen ist Sache des Compilers. Ob und inwieweit das bei Java noch möglich sein wird, wird sich zeigen. Das Typsystem IST schon komplex, mit Autoboxing und Bounded Wildcards, ... Zumindest hat Brian Goetz mal angedeutet, dass primitive Typen sich vielleicht irgendwann besser dort einfügen, aber verbindliches oder konkretes gibt's dazu AFAIK nicht...


vielleicht verstehe Deinen Einwand nicht ganz, aber die 1700 Zeilen beziehen sich doch auf eine konkrete alternative rohe MPI Quicksort Implementierung. Imho ist der Vergleich so nicht fair. Würde man die 1700 MPI Zeilen in ein "void quicksort(final byte[] values)" "verstecken", wäre der Vergleich 10 Zeilen DSL vs. 1 Zeile Java. Egal wie später die Problemstellung für den Rechner formuliert wird, der Rechenaufwand ist dabei immer gleich. Und die Länge (in Codezeilen) der Aufgabenstellung (evtl. DSL) vermutlich umgekehrt proportional zu den möglichen Freiheitsgraden innerhalb der Problemstellung.

Der letzte Satz ist IMHO der entscheidende Punkt: Dass man beliebig komplexe Dinge im Stile einer Bibliothek hinter einem Methodenaufruf verstecken kann (z.B. eine ganze Anwendung hinter einem [c]main(null);[/c] :D ) bezweifelt ja niemand. Man könnte es grob so formulieren, dass der Unterschied darin liegt, wie mächtig/high-level die Strukturen sind, die tatsächlich der Compiler schluckt - und an denen er, im oben schon angedeuteten Sinn, noch etwas "drehen" kann. Wenn man in diesem NESL-Like Code als Pivotlement jetzt nicht ein zufälliges wählen will, sondern immer das mittlere, kann man das einfach machen....

Unabhängig davon halte ich den Vorteil, den funktionale Programmierung im Bezug auf Multi/Manycore Anwendungen haben soll, für überbewertet. Damit daraus ein Vorteil für den normalen Anwendungsentwickler entsteht, müssen imho einige Randbedingungen erfüllt sein:
...
Auf der anderen Seite stehen dann doch nur noch die GPU Fetischisten (z.B. mit OpenCL) oder die Leute die richtig rocken wollen (z.B. mit OpenMP / MPI). Das sind aber absolute Nischen, nichts was für die breite Masse der Entwickler von Interesse wäre.

Die Bedingungen sind klar, aber ich denke, dass es nicht unbedingt darum geht, dass wir alle in Zukunft nur noch funktional programmieren, sondern nicht zuletzt (oder sogar zuerst) darum, funktionale Aspekte in die alltägliche Programmierung einfließen zu lassen. Sowas wie
Java:
sineList = floatList.applyToAll(sineFunction);
ist das Paradebeispiel, das funktional ist, und in vielen Fällen "trivial parallelisierbar" - trotzdem will der high-Level Java-Programmierer sich dafür keinen OpenCL-Kernel schreiben, sondern er will es genau so schreiben, wie es dort steht. Ich habe es schon mehrfach betont, muss es aber nochmal: Die Anzahl der Kerne wird sich in Zukunft dramatisch erhöhen, und die Zeit des "free lunch", bei dem die Softwareleute immer komplexere Programme geschrieben haben und immer mehr Daten verarbeitet haben, und sich die Hardwareleute darum gekümmert haben, dass es schneller (oder zumindest nicht langsamer) läuft, ist endgültig vorbei. In Zukunft wird niemand mehr um Multi- oder sogar Manycore-Programmierung drumrumkommen, und das ist wirklich nicht trivial - ohne eine gute Unterstützung durch Sprachen und Compiler wird die Programmierung da einfach zu komplex. Ob Scala da die "Silver Bullet" darstellt oder nicht, oder inwieweit das durch Java-Erweiterungen unterstützt wird, weiß ich aber auch nicht...
 
S

SlaterB

Gast
wenn man in Java Number wie Integer oder selbstdefinierte Klassen haben möchte, kann man das doch machen?,
solange nicht die primitiven Datentypen mangels Verwendung von alleine aussterben gibt es absolut keinen Grund sie zu verbieten oder darauf rumzuhacken
 

Gregorrr

Bekanntes Mitglied
... ist das Paradebeispiel, das funktional ist, und in vielen Fällen "trivial parallelisierbar" - trotzdem will der high-Level Java-Programmierer sich dafür keinen OpenCL-Kernel schreiben, sondern er will es genau so schreiben, wie es dort steht. Ich habe es schon mehrfach betont, muss es aber nochmal: Die Anzahl der Kerne wird sich in Zukunft dramatisch erhöhen, und die Zeit des "free lunch", bei dem die Softwareleute immer komplexere Programme geschrieben haben und immer mehr Daten verarbeitet haben, und sich die Hardwareleute darum gekümmert haben, dass es schneller (oder zumindest nicht langsamer) läuft, ist endgültig vorbei. In Zukunft wird niemand mehr um Multi- oder sogar Manycore-Programmierung drumrumkommen, und das ist wirklich nicht trivial - ohne eine gute Unterstützung durch Sprachen und Compiler wird die Programmierung da einfach zu komplex. Ob Scala da die "Silver Bullet" darstellt oder nicht, oder inwieweit das durch Java-Erweiterungen unterstützt wird, weiß ich aber auch nicht...

Sehe ich genauso. Scala's Killer-Technologie kann eigentlich nur parallele Programmierung sein, obs wird steht auf einem anderen Stern...

Java hat sich lange Zeit nicht weiter entwickelt, weil Sun einfach keine Mittel hatte, aber seitdem Oracle ja Sun aufgekauft hat, tut sich dahingehend doch einiges und mit Java 8 und Closures holt Java auch ein wenig auf, mal schauen, ob es erstmal genügt - Denn die "beste" Abstraktion zur parallelen Programmierung hat erst angefangen.

BTW, Scala Bashing geht weiter: Offbeat: Scala by the end of 2011 – No Drama but Frustration is Growing GridGain – Real Time Big Data
 

Antoras

Top Contributor
wenn man in Java Number wie Integer oder selbstdefinierte Klassen haben möchte, kann man das doch machen?
Die kann man aber dank fehlender Operatorüberladung nicht vernünftig einsetzen. Außerdem sind sie nicht effizient, da die JVM kleine Objekte nicht wegoptimiert. In Scala werden zumindest die primitiven JVM-Typen immer optimiert wenn möglich. Und dank spezialisierten parametrisierten Typen ist es auch möglich numerische Berechnungen ohne großen Overhead effizient zu implementieren.
 

escalate

Mitglied
dann heisst es also Scala ist mehr so eine Art Forschungssprache?
Weiß ja nicht, was du unter Forschungssprachen verstehst. Ich würde das mit einem klaren "jein" beantworten...
Java wird auch in der Forschung eingesetzt und es gibt eine Menge wissenschaftlicher Veröffentlichungen dazu,

Wer kommt denn sonst auf die Idee unglaublich komplizierte Dinge auf einer höheren Ebene zu beschreiben.
Naja, die Welt ist leider nicht immer so einfach wie man es gerne hätte. Durchaus möglich, dass Scala nie eine wirklich große Verbreitung haben wird, aber es muss auch passende Werkzeuge für etwas anspruchsvollere Aufgaben (und Programmierer) geben. Wenn ich tonnenweise Java-Code schreiben muss um die Limitationen der Sprache zu umgehen ist das auch alles andere als "lesbar" und fehlerunanfällig.


Ich gehe mal davon aus, dass die Komplexität von Software in den nächsten Jahren eher zunehmen wird und ob man da mit eher "primitiven" Sprachen wie Java noch so weit kommt wird sich zeigen.

Jetzt bitte nicht falsch verstehen, mir geht es nur um die Industrietauglichkeit von Scala im Bereich Web, Mobile (Apps) usw das was halt zur Zeit gefragt ist.
Webanwendungen könnte eher eine Stärke von Scala werden, schau dir mal die Entwicklung vom Play-Framework an. In der nächsten Version kommt Unterstützung für bessere String-Interpolation. Da freue ich mich schon darauf ;)

Habe ein interessante Umfrage gefunden: Auswertung_der_Scala_Umfrage.pdf

"Ich kann der Argumentation, dass der immer kürzer werdende Code lesbarer sein soll, nicht folgen. Man braucht immer mehr implizites Wissen, um zu verstehen, was da eigentlich passiert. Was der Entwickler dann ursprünglich wollte, war dann im Zweifel nochmal etwas komplett anderes."
Jetzt müsste man nur noch wissen, ob das von jemandem kommt, der Scala auch wirklich eingesetzt hat. Das war ja keine Voraussetzung für die Teilnahme.

Sonst sieht das doch schon eher positiv aus, würde ich sagen. Sogar positiver, als ich vorher erwartet hätte.

66% der Befragten sind in einer Softwarefirma oder IT-Abteilung, es haben sich also nicht nur reine Akademiker beteiligt ;)

2% geben an, dass ihre Erfahrungen negativ waren, 61% positiv, 6% neutral und 31% setzen es nicht ein.
22% planen keinen Einsatz von Scala und 28% haben sich noch nicht entschieden. 11% wollen es sogar als hauptgenutzte Sprache einsetzen.

7% finden Scala zu kompliziert und 28% finden nur den Einstieg schwierig.
 

Dit_

Bekanntes Mitglied
Java:
public static number square(number n) {
  return n*n;
}

...statt...

Java:
public static byte square(byte n) {
  return n*n;
}
public static short square(short n) {
  return n*n;
}
public static int square(int n) {
  return n*n;
}
...
Das Beispiel ist einwenig praxisuntauglich...
Du weisst schon dass byte, short, int und long verschiedene Wertebereiche haben und solche zusammenfassung zu
Code:
(if n instance of byte)
führen?
Es gibt auf sowas wie templates...
 

Landei

Top Contributor
Das Beispiel ist einwenig praxisuntauglich...

Dann ein anderes: Hier eine Klasse, die beim Erstellen einer compare-Funktion helfen soll.

Java:
public enum Compare {
    LT, EQ, GT;

    public int toInt() {
       switch(this) {
           case LT: return -1;
           case EQ: return 0;
           case GT: return 1;
           default: throw new AssertionError();    
       }    
    }

    public Compare cp(int v1, int v2) {
        if(this == EQ) return v1 < v2 ? LT : v1 > v2 ? GT : EQ;
        else return this;
    }

    //... Methoden für andere Primitive

    // Methode für Comparable-Objekte
    public <T extends Comparable<T>> Compare cp(T v1, T v2) {
        if(this == EQ) {
            int result = v1.compareTo(v2);
            return result < 0 ? LT : result > 0 ? GT : EQ;
        } else {
            return this;
        }    
    }
}

Anwendung:
Java:
import static somepackage.Compare.*;

class Version implements Comparable<Version> {
    ...
    @Override
    public int compareTo(Version that) {
       return EQ.cp(this.major, that.major)
            .cp(this.minor, that.minor)
            .cp(this.minor2, that.minor2)
            .toInt();
    }
}

Praxistauglich genug?
 
G

Guest2

Gast
Mir ist klar was er damit aussagen wollte. ich weis zwar nicht was ein HPC Kurs ist aber ich denke den könnte man auch direkt bei dem Informatik Prof. nehmen ;)
Esser Friedrich

HPC ist die Abkürzung für High-performance computing. Normalerweise werden in den zugehörigen Vorlesungen / Kursen / Praktika nebenläufige Algorithmen und deren Vor- / Nachteile auf verschiedenen Plattformen behandelt. Bei uns hatte die entsprechende Vorlesung z.B. auch ein zugehöriges Praktikum, bei dem konkrete Beispiele in Java realisiert wurden. Behandelt wurde dabei ein Querschnitt von der einfachen Matrixmultiplikation auf dem 2 Kern Rechner bis zum Cluster mit mehreren Tausend Kernen.

Man darf das Zitierte nur überspitzt polemisch auffassen (sonnst wäre es traurig). Was an sich auch legitim wäre, würde er es anschließend wieder in den richtigen Kontext rücken. Aber so besteht die Gefahr das ein Leser, welcher nicht zufällig mal in dieses Themengebiet reinschnuppern durfte, diese Aussage unreflektiert übernimmt.


Die Bedingungen sind klar, aber ich denke, dass es nicht unbedingt darum geht, dass wir alle in Zukunft nur noch funktional programmieren, sondern nicht zuletzt (oder sogar zuerst) darum, funktionale Aspekte in die alltägliche Programmierung einfließen zu lassen. Sowas wie
Java:
sineList = floatList.applyToAll(sineFunction);
ist das Paradebeispiel, das funktional ist, und in vielen Fällen "trivial parallelisierbar" - trotzdem will der high-Level Java-Programmierer sich dafür keinen OpenCL-Kernel schreiben, sondern er will es genau so schreiben, wie es dort steht.

Das ist doch auch perfekt valide Java Syntax. Zur Deklaration von sineFunction ist zurzeit noch etwas boilerplate notwendig, eine Handvoll Zeilen in einer eingebundenen Bibliothek reichen zur Umsetzung.

Very quick and very dirty und unsinnige Spielerei:
Java:
public interface ParallelFunction<T extends Number> {

    public T call(T value);

}
Java:
import java.util.List;


public interface ParallelList<T extends Number> extends List<T> {

    List<T> applyToAll(ParallelFunction<T> function) throws InterruptedException;

}
Java:
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


@SuppressWarnings("serial")
public class ParallelArrayList<T extends Number> extends ArrayList<T> implements ParallelList<T> {

    private static final int      POOL_SIZE = 4;
    private final ExecutorService pool      = Executors.newFixedThreadPool(POOL_SIZE);


    @Override
    public List<T> applyToAll(final ParallelFunction<T> function) throws InterruptedException {

        @SuppressWarnings("unchecked")
        final T[] results = (T[]) Array.newInstance(get(0).getClass(), size());

        final CountDownLatch latch = new CountDownLatch(size());

        for (int i = 0; i < size(); i++) {

            final int current = i;

            pool.submit(new Callable<Object>() {

                @Override
                public T call() {

                    results[current] = function.call(get(current));

                    latch.countDown();

                    return null;

                }

            });

        }

        latch.await();

        return Arrays.asList(results);

    }

}
Java:
import static org.junit.Assert.assertEquals;

import java.util.List;
import java.util.Random;

import org.junit.Test;


public class TestParallelArrayList {

    @Test
    public void testApplyToAll() throws InterruptedException {

        final int testSize = 2000000;
        final Random random = new Random(0);

        final ParallelFunction<Double> function = new ParallelFunction<Double>() {

            @Override
            public Double call(final Double value) {

                return Math.sin(value);

            }

        };

        final ParallelList<Double> list = new ParallelArrayList<Double>();

        for (int i = 0; i < testSize; i++)
            list.add(random.nextDouble());

        // /////////////////////////////////////////////////////

        final List<Double> sineList = list.applyToAll(function);

        // /////////////////////////////////////////////////////

        for (int i = 0; i < testSize; i++)
            assertEquals(function.call(list.get(i)), sineList.get(i));

    }

}

Das Problem, was ich eben sehe, ist das die aktuelle Rechnerarchitektur Grenzwerte festlegt, ab wann es sich lohnt ein Problem parallel zu lösen und wann es sich eben nicht lohnt. Das ist auch völlig unabhängig davon, wie viele Kerne verwendet werden. Sobald irgendwo eine Synchronisation notwendig wird (und eine ist immer notwendig (z.B. oben "latch" als Signal, das die Liste fertig ist) kommt es zu einem Overhead. Und solange dieser Overhead größer ist als das Problem, lohnt es sich nicht das Problem zu parallelisieren. Und das ist völlig Sprachunabhängig, sondern eine Limitierung durch die Hartware.

Ein konkretes Beispiel: Das Dekodieren eines Videostromes. Vereinfacht betrachtet bestehen viele komprimierte Videos aus einer Folge von Keyframes und "Folgeframes". Will man das Dekodieren parallelisieren, gibt es zwei Ansätze:

1.: Man versucht EIN Keyframe (und seine Folgeframes) mit Hilfe von N Threads zu dekodieren.
2.: Man verteilt N Keyframes (und seine Folgeframes) auf N Threads.

Funktionale Ansätze gehen von der Parallelisierung im Kleinen aus und versuchen jeden Schritt parallel auszuführen. Das führt dann zu Variante 1. Bei dieser Variante sind aber sehr viele Daten voneinander abhängig und es muss sehr viel synchronisiert werden. Der Overhead ist groß und das Verfahren skaliert bescheiden.

Der 2. Ansatz ist das, was ich oben mit trivial parallelisieren meinte. Dort ist praktisch keine relevante Synchronisierung notwendig und das Verfahren skaliert fast linear. Hat aber den Nachteil, dass ich als Entwickler hingehen muss und an einer ganz konkreten Stelle scheiben muss "mach genau DAS jetzt parallel".

Viele Grüße,
Fancy
 

Bronko

Mitglied
Warum hast du nicht Raytracing als Beispiel für Nebenläufige Programmierung genannt? ;)

EDIT: Soviel ich gelesen habe arbeiten AMD und Intel an dem Problem der Core Synchronisation. Ich denke das wird man auch bald gelöst haben.
 
Zuletzt bearbeitet:
G

Guest2

Gast
Ja, stimmt Raytracing wäre ein anderes Beispiel gewesen. ;)

Das die CPU Hersteller versuchen das Problem zu verkleinern, ist zu erwarten. Jedoch ist das Prinzipbedingt und wohl nicht vollständig zu lösen.

Eine Schwangerschaft dauert 9 Monate. Auch wenn Du zwei Frauen hast, schaffst Du kein Kind in 4 1/2 Monaten.

Viele Grüße,
Fancy
 

Marco13

Top Contributor
Der Spoiler wäre nicht nötig gewesen, ich denke, die meisten können sich in etwa vorstellen, wie das aussehen könnte - so, und jetzt bau' das zu einer schönen, flexiblen Bibliothek aus! :bae:

Martin Odersky hat auch schon ein Paper dazu geschrieben, "A Generic Parallel Collection Framework" ( PDF: http://infoscience.epfl.ch/record/150220/files/pc.pdf ), es gibt auch das JSR zu ParallelArray und Dinge wie gpars (Groovy Parallel Systems) - Parallelizer - es wird intensiv daran gearbeitet. Aber die entscheidenden Punkte zu dem Java-Snippet hast du schon angedeutet:
1. Häßlicher Boilerplate code (dürfte mit Java 8 und SAM-Types schon deutlich besser werden!)
2. Abhängigkeit von der Zielarchitektur
Und gerade das zweite kann ja eigentlich nur elegant versteckt und behandelt werden, wenn man den Code, den du gepostet hast, eben nicht selbst per Hand hinschreiben muss, sondern das (oder etwas anderes, ggf. zur Laufzeit an die Architektur angepasstes) dem Compiler überläßt.
 

Bronko

Mitglied
Ja, stimmt Raytracing wäre ein anderes Beispiel gewesen. ;)

Das die CPU Hersteller versuchen das Problem zu verkleinern, ist zu erwarten. Jedoch ist das Prinzipbedingt und wohl nicht vollständig zu lösen.

Eine Schwangerschaft dauert 9 Monate. Auch wenn Du zwei Frauen hast, schaffst Du kein Kind in 4 1/2 Monaten.

Viele Grüße,
Fancy

Das kleine Aufgaben schlecht zu parallelisieren sind hat ja niemand bezweifel.
Das mit der Schwangerschaft hast du falsch dargestellt.
Wenn du zwei unterschiedliche Frauen (Cores) zur selben zeit schwängerst dann hast du nach 9 Monaten auch das doppelte an Leistung ;)

Zu Oracle:
Soviel wir alle wissen planen sie auch eine Enterprise VM. Es ist durchaus möglich das sie da eine bessere Nebenläufigkeit implementieren aber darauf wetten würde ich nicht. Wie gut der Java VM die kostenpflichtig Abspaltung tut ist eine andere frage.

Dazu gibt es übrigens eine interessante News:
Von Haskell und Haswell | c't
 
Zuletzt bearbeitet:

escalate

Mitglied
Und bei Scala kann ich mich des Eindrucks nicht erwähren, dass dabei besonders gerne abgefahrene Syntaxspielchen eingesetzt werden. Ich meine ein

Code:
#pragma omp parallel for
for (i = 0; i < N; i++)
    a[i] = 2 * i;

gibt es jetzt seit bald 15 Jahren. Das ist zwar natürlich nicht so mächtig wie eine abgefahrene mit Scala umgesetzte DSL. Der Vorteil ist jedoch, dass es praktisch von jedem Schüler gelesen werden kann, welcher irgendwann und irgendwo schon mal irgendein Programm gelesen hat.
Ich schreibe lieber

Code:
(1 to n).par.map(_ * 2)
Das ist eigentlich keine abgefahrene DSL, oder? 3 Methoden aus der Standardbibliothek und eine anoyme Funktion, mehr ist es ja nicht.

Falsch machen kann man dabei nicht viel im Vergleich zu Schleife und das sollte auch von jedem halbwegs intelligentem Menschen verstanden werden, spätestens nach 30 Sekunden Erklärung ;)

Finde ich eher traurig, wenn man solche Konstrukte als Programmierer noch nie gesehen hat und nur in Schleifen denken kann. Ich kann das nicht besonders gut, daher nehme ich lieber was anderes, bei dem man nicht so viele Fehler machen kann...
 
G

Guest2

Gast
so, und jetzt bau' das zu einer schönen, flexiblen Bibliothek aus! :bae:

Aber erst wenn es das nächste Mal wieder nachmittags regnet. :D

Nein, ernsthaft hätte ich damit wohl ein richtiges Problem, weil ich nicht glaube, dass die Parallelisierung "aus dem Kleinen heraus" so sonderlich effizient wäre (neben der Zeit zur Umsetzung und so ;)).

Und beim Versuch die Parallelisierung "aus dem Großen heraus" zu abstrahieren würde ich wohl vermutlich bei einer zum Callable ähnlichen Variante landen. Beides halte ich aber langfristig nicht für das Optimum.


Und gerade das zweite kann ja eigentlich nur elegant versteckt und behandelt werden, wenn man den Code, den du gepostet hast, eben nicht selbst per Hand hinschreiben muss, sondern das (oder etwas anderes, ggf. zur Laufzeit an die Architektur angepasstes) dem Compiler überläßt.

Imho ist das der einzig gangbare Weg. Eine Datenflussanalyse und Komplexitätsabschätzung auf dem AST bzw. Zwischencode während des Kompilierens könnte die Bereiche sichtbar machen, die sich sinnvoll auf verschiedene Kerne verteilen lassen. Und das ist imho auch genau das an dem die Compilerbauer gerade basteln. Wenn man das so realisiert, ist das aber unabhängig der Quellsprache und damit kein Vorteil der funktionalen Programmierung mehr.


Das mit der Schwangerschaft hast du falsch dargestellt.
Wenn du zwei unterschiedliche Frauen (Cores) zur selben zeit schwängerst dann hast du nach 9 Monaten auch das doppelte an Leistung ;)

Dann ist es aber kein paralleler Algorithmus mehr, sondern nur das parallele Ausführen zweier voneinander unabhängiger sequenzieller Algorithmen. ;) Das ist dann das was ich oben mit trivial parallelisierbar umschrieben habe. Das ist einfach und skaliert gut. Das Gegenteil wäre eben wenn Du versuchst EINE Schwangerschaft auf 4 1/2 Monate zu drücken, das skaliert nicht und funktioniert auch nicht wirklich. ;)


Code:
(1 to n).par.map(_ * 2)
Das ist eigentlich keine abgefahrene DSL, oder? 3 Methoden aus der Standardbibliothek und eine anoyme Funktion, mehr ist es ja nicht.

Falsch machen kann man dabei nicht viel im Vergleich zu Schleife und das sollte auch von jedem halbwegs intelligentem Menschen verstanden werden, spätestens nach 30 Sekunden Erklärung ;)

Ja, so ist das noch einfach. Es lässt sich aber leider auch nicht ganz vergleichen. Mein obriger Abschnitt bezog sich auf ein Beispiel zu OpenMP. Ganz abstract und vereinfacht gesehen, ist der Ansatz dabei, dass man eigentlich ein sequenzielles Programm schreiben könnte, bei dem man über die OpenMP Direktiven dem OpenMP Preprozessor eben sagen kann: "Mach genau DAS JETZT parallel (und nur DAS!)".

Wenn man Deine Variante umsetzt, stellt sich intern die frage, soll das auf einem Kern oder auf vielen durchgeführt werden? Im Hinblick auf funktionale Manycore-Programmierung führt das dann dazu das alles was möglich ist parallelisiert wird ("Parallelisierung aus dem Kleinen heraus"). Das wiederum führt aber dazu das eigentlich unnötiger Overhead produziert wird, weil das Problem (möglicherweise) auch trivial zu parallelisieren gewesen wäre (und dann ohne Overhead). (Wie in dem Beispiel zum Videodekodieren)

Viele Grüße,
Fancy
 
G

Guest2

Gast
Vielleicht noch als Nachtrag für die, die OpenMP nicht kennen. Man kann die OpenMP Direktiven nicht nur auf Schleifen anwenden ("Parallelisierung im Kleinen"), sondern eben z.B. auch auf Blöcke (was dann ehr "Parallelisierung im Großen" entspricht).

Viele Grüße,
Fancy
 

escalate

Mitglied
Ja, so ist das noch einfach. Es lässt sich aber leider auch nicht ganz vergleichen. Mein obriger Abschnitt bezog sich auf ein Beispiel zu OpenMP. Ganz abstract und vereinfacht gesehen, ist der Ansatz dabei, dass man eigentlich ein sequenzielles Programm schreiben könnte, bei dem man über die OpenMP Direktiven dem OpenMP Preprozessor eben sagen kann: "Mach genau DAS JETZT parallel (und nur DAS!)".
Das mit OpenMP ist mir schon klar, ich sehe nur den Unterschied nicht so wirklich. In meinem Fall habe ich doch auch gesagt, dass genauso diese Operation parallel ausgeführt werden soll. Das ist ja auch nichts Anderes als eine parallelisierte Schleife.
 

Bronko

Mitglied
Dann ist es aber kein paralleler Algorithmus mehr, sondern nur das parallele Ausführen zweier voneinander unabhängiger sequenzieller Algorithmen. ;) Das ist dann das was ich oben mit trivial parallelisierbar umschrieben habe. Das ist einfach und skaliert gut. Das Gegenteil wäre eben wenn Du versuchst EINE Schwangerschaft auf 4 1/2 Monate zu drücken, das skaliert nicht und funktioniert auch nicht wirklich. ;)

Viele Grüße,
Fancy

Ja schon klar ;) Mein Beispiel war dem Raytracing Problem geschuldet und da hast du viele Möglichkeiten wo du wunderbar funktional und parallel arbeiten kannst.
 

Gregorrr

Bekanntes Mitglied
Dann ist es aber kein paralleler Algorithmus mehr, sondern nur das parallele Ausführen zweier voneinander unabhängiger sequenzieller Algorithmen. ;) Das ist dann das was ich oben mit trivial parallelisierbar umschrieben habe. Das ist einfach und skaliert gut. Das Gegenteil wäre eben wenn Du versuchst EINE Schwangerschaft auf 4 1/2 Monate zu drücken, das skaliert nicht und funktioniert auch nicht wirklich. ;)

Wie das ist kein paralleler Algorithmus? Das nennt sich Datenparallelität, Beispiel GPU: Man partitioniert die Daten (also die Anzahl der Frauen im Harem) und führt die Operation "Bumsen" auf allen Frauen im Harem aus. Das ist dann eine SIMD-Operation (Single Instruction Multiple Data). Ein sequentieller Programmfluss auf einer Menge von unabhängigen leichtgewichtigen Threads (CUDA Terminologie für dünne Frauen) oder in OpenCL Terminologie: work-item (wobei man mit obiger Operation nicht unbedingt Arbeit verbindet). Jeder sequentielle Programmfluss kann miteinander kommunizieren, dass wäre dann das "Rudelbumsen". Der sequentielle Programmfluss dauert 9 Monate und bringt je in Abhängigkeit der if-Verzweigungen pro Thread entweder ein Kind zur Welt oder nicht. Des Kind kann man dann zurück an den Host (Vater) zurückgeben, der hat die Operation auch initiiert. Das Zurückgeben ist in der Regel aber nicht ganz billig (GPU - Host Interaktion kostet). Das nennt sich auch Stream-Bumsen, ähm, Computing, sorry.

Das was du meinst ist Task-Parallelität ist aber nur eine Form der Parallelität. In Bezug auf Task-Parallelität lässt sich das wirklich nicht partitionieren, denn eine Schwangerschaft dauert nun mal 9 Monate, und in diesem Modell ist der längste Ausführungsstrang entscheidend (falls man nur eine Menge an gleichzeitig startenden Programmsträngen betrachtet).
 

Gregorrr

Bekanntes Mitglied
Wenn man das so realisiert, ist das aber unabhängig der Quellsprache und damit kein Vorteil der funktionalen Programmierung mehr.
So einfach ist das nicht: Du kannst nicht einfach den Compiler anweisen, dass er "automatisch" parallelisieren soll. Wenn du das schaffst, dann bekommst du mit Sicherheit dern Touring-Award...

Ja, so ist das noch einfach. Es lässt sich aber leider auch nicht ganz vergleichen. Mein obriger Abschnitt bezog sich auf ein Beispiel zu OpenMP. Ganz abstract und vereinfacht gesehen, ist der Ansatz dabei, dass man eigentlich ein sequenzielles Programm schreiben könnte, bei dem man über die OpenMP Direktiven dem OpenMP Preprozessor eben sagen kann: "Mach genau DAS JETZT parallel (und nur DAS!)".
Was ist mit der Scheduling-Strategie? Das ist ein ganz integraler Bestandteil der OpenMP Direktiven. Da fangen die ganz großen Unterschiede an. Man kann das überhaupt nicht miteinander vergleichen...
Du machst es dir ziemlich einfach...

Wenn man Deine Variante umsetzt, stellt sich intern die frage, soll das auf einem Kern oder auf vielen durchgeführt werden? Im Hinblick auf funktionale Manycore-Programmierung führt das dann dazu das alles was möglich ist parallelisiert wird ("Parallelisierung aus dem Kleinen heraus"). Das wiederum führt aber dazu das eigentlich unnötiger Overhead produziert wird, weil das Problem (möglicherweise) auch trivial zu parallelisieren gewesen wäre (und dann ohne Overhead). (Wie in dem Beispiel zum Videodekodieren)
Als ob du bei OpenMP bestimmen könntest, auf welchen !Kern! die Ausführung stattfindet. Du vergleichst Äpfel aber sowas von mit Birnen... Du vertauscht Datenparallelität mit Taskparallelität. Wenn ich eine Parallele Schleife habe, dann habe ich Iterationen, deren Daten man partitionieren kann. Das was du ansprichst, würde man weder in OpenMP noch in Scala wie oben schreiben...
Parallelität ist so ein breites Feld, das könnt ihr nicht einfach mit einer parallelen Schleife abtun...
 

Marco13

Top Contributor
...Eine Datenflussanalyse und Komplexitätsabschätzung auf dem AST... Wenn man das so realisiert, ist das aber unabhängig der Quellsprache und damit kein Vorteil der funktionalen Programmierung mehr.

Ach so - ja, ich meinte das nicht speziell in bezug auf funktionales Programmieren sondern allgemein. Aber die Vorteile (speziell Zustandslosigkeit) der funktionalen Programmierung könnte da einiges (und zwar SEHR) deutlich leichter machen. Das, woran die Compilerbauer da meines Wissens am meisten knabbern sind ja gerade die Abhängigkeiten: Wer liest welche Variable wann, und wo zu Hölle zeigt dieser Pointer gerade hin? :autsch:
Zudem fand ich das Konzept des "nested parallelism", das Blelloch mit NESL beschrieben hat, sehr interessant. Damit könnte vielleicht auch die Trennung zwischen dem "aus dem Großen" und "aus dem Kleinen", die du angesprochen hast, angegangen werden. Richtig fundiert-konkret ist das in meinem Kopf gerade noch nicht, aber etwas plakativ gesagt geht es ja auch um die Frage, ab welchem Punkt man vom Groben, (meistens Task-Parallelen) zum Kleinen (oft Daten-Parallelen) wechselt...

Die Frage mit den 9 vs. 4 1/2 Monaten erinnerte mich jetzt ein bißchen an
Amdahl: Weniger Zeit bei gleicher Eingabegröße vs.
Gustafson: Mehr Daten ("höherer Durchsatz") bei gleicher Zeit
Letzteres hat den schönen Vorteil, nicht durch sequentielle Teile beschränkt zu sein...


EDIT: Gustafson - nicht Gustavson....
 
Zuletzt bearbeitet:
G

Guest2

Gast
Das mit OpenMP ist mir schon klar, ich sehe nur den Unterschied nicht so wirklich. In meinem Fall habe ich doch auch gesagt, dass genauso diese Operation parallel ausgeführt werden soll. Das ist ja auch nichts Anderes als eine parallelisierte Schleife.

Ja genau, wenn man das so fix hinschreibt, ist das Primär eine fixe parallele Schleife. Das Problem dabei ist das dieses harmlos scheinende [c](1 to n).par.map(_ * 2)[/c] dazu führt das alle Kerne für ein Problem belegt werden, bei dem von einer nicht sonderlich effizienten Gesamtlösung auszugehen ist. Ein Algorithmus, der das Problem als Ganzes betrachtet, könnte mit Sicherheit Effizienter arbeiten, er würde aber durch solche vermeintlichen Optimierungen behindert.

Bei OpenMP hast Du die Möglichkeit da viel feingranularer einzugreifen. Statt einem [c]#pragma omp parallel for[/c] schreibst Du halt z.B. ein [c]#pragma omp for schedule(guided)[/c]. (Das ist der Punkt auf den Gregorrr bereits hingewiesen hat.)


Du machst es dir ziemlich einfach...
Parallelität ist so ein breites Feld, das könnt ihr nicht einfach mit einer parallelen Schleife abtun...

Ganz bewusst sogar! ;) Außerdem ist das doch genau der Punkt, auf den ich die ganze Zeit hinauswill und bei dem ich in diesen Thread eingestiegen bin, nämlich inwieweit funktionale Ansätze bei der Multi-/Manycore - Programmierung förderlich sind:


Unabhängig davon halte ich den Vorteil, den funktionale Programmierung im Bezug auf Multi/Manycore Anwendungen haben soll, für überbewertet. Damit daraus ein Vorteil für den normalen Anwendungsentwickler entsteht, müssen imho einige Randbedingungen erfüllt sein: Das Problem sollte

- überhaupt parallelisierbar sein
- eine kritische Problemgröße aufweisen (zu groß für singe core, klein genug für SMP)
- nicht trivial parallelisierbar sein (sonst gibt es effizientere Ansätze)
- nicht sowieso ständig auf IO warten (Benutzer, Daten, ..)

Also zumindest mir fällt da nicht sonderlich viel ein. [...]

Einfach "Funktional = gut für Parallelität" ist dann nämlich wirklich zu einfach gemacht. Und schlimmstenfalls kann ein einfaches [c](1 to n).par.map(_ * 2)[/c] irgendwo versteckt auch eine optimierte Lösung hinrichten.


Ach so - ja, ich meinte das nicht speziell in bezug auf funktionales Programmieren sondern allgemein. Aber die Vorteile (speziell Zustandslosigkeit) der funktionalen Programmierung könnte da einiges (und zwar SEHR) deutlich leichter machen. Das, woran die Compilerbauer da meines Wissens am meisten knabbern sind ja gerade die Abhängigkeiten: Wer liest welche Variable wann, und wo zu Hölle zeigt dieser Pointer gerade hin? :autsch:

Genau, bei den Möglichkeiten der Compileroptimierung hat reine funktionale Programmierung Vorteile. Den Vorteil erkauft man sich aber entweder über komplizierte Datenstrukturen, die eben doch nicht richtig immutable sind, oder durch blankes Byteschupsen in gigantischem Umfang (Da ging es in Deinem verlinkten Thread ja hauptsächlich drum ;))


Zudem fand ich das Konzept des "nested parallelism", das Blelloch mit NESL beschrieben hat, sehr interessant. Damit könnte vielleicht auch die Trennung zwischen dem "aus dem Großen" und "aus dem Kleinen", die du angesprochen hast, angegangen werden. Richtig fundiert-konkret ist das in meinem Kopf gerade noch nicht, aber etwas plakativ gesagt geht es ja auch um die Frage, ab welchem Punkt man vom Groben, (meistens Task-Parallelen) zum Kleinen (oft Daten-Parallelen) wechselt...

Ja genau. Das Problem ist, das beide Seiten nicht nur Einfluss auf das Gesamtlaufzeitverhalten haben, sondern auch das Laufzeitverhalten der anderen Seite beeinflussen können. Ein System das (zumindest unterstützend hilft) das automatisch zu lösen, dürfte nicht ganz trivial werden. ;)
(Und der Compilerbau ist der einzige Ansatzpunkt, den ich dafür überhaupt sehe.)


Die Frage mit den 9 vs. 4 1/2 Monaten erinnerte mich jetzt ein bißchen an
Amdahl: Weniger Zeit bei gleicher Eingabegröße vs.
Gustafson: Mehr Daten ("höherer Durchsatz") bei gleicher Zeit
Letzteres hat den schönen Vorteil, nicht durch sequentielle Teile beschränkt zu sein...

Genau. Schwangere wirken nur plakativer als die beiden Formeln der Herrn ;)

Viele Grüße,
Fancy
 

Bronko

Mitglied
Landei hat recht. Egal in welcher Sprache Automatismus aus einer Schleife heraus kann nur wenig oder nichts bringen wegen den bereits geposteten dingen wie... Seiteneffekte, Aufgabe zu schnell erledigt und vor allem kann immer nur ein Core einen Speicherbereich abarbeiten. Wenn Aufgaben parallel effektiv abgearbeitet werden sollen geht das sicher nur funktional und mit individuellen Threads welche die Arbeit ordentlich aufteilen.

Sollte es mal einen Zauber Compiler geben der das automatisch generiert dann wäre ich mehr als erstaunt.
 
Zuletzt bearbeitet:

Marco13

Top Contributor
An solchen "Zaubercompilern" wird gearbeitet. Sicher ist aparapi - API for data parallel Java. Allows suitable code to be executed on GPU via OpenCL. - Google Project Hosting nur der Anfang, aber so gesehen steckt "Multi/Manycore für die breite Masse" ja noch in den Kinderschuhen. Da wird sich noch einiges tun.

Und, um mal wieder grob zu Scala zurückzukommen: Ich denke eben, dass nur mit "high level building blocks" ein Großteil dieser Arbeit auf den Compiler abgewälzt werden kann. Wenn man in C oder Java hinschreibt
Java:
int sum = 0;
for (int i=0; i<10; i++)
{
    sum += array[i];
}
dann wird das direkt übersetzt - man kann sich praktisch 1:1 den Assembler- bzw. Bytecode dafür zusammenfrickeln. Da kann man nichts dran drehen, und insbesondere: Man kann dort nichts parallelisieren! Selbst mit [c]parallel for[/c] von OpenMP würde dort nichts gehen. Das, was dort gemacht wird, ist einfach nicht parallelisierbar.

Oder?

DOCH! Das ist ein Scan/Reduction, und einer der wichtigsten Bausteine für viele parallele Programme! Aber das kann eben praktisch* nur erkannt und vom Compiler ausgenutzt werden, wenn dort nicht diese for-Schleife steht, sondern ein ganz abstraktes
[c]var sum = array.reduce();[/c]
oder so...

* praktisch, weil es theoretisch durch Codeanalyse erkannt werden könnte, aber dafür bräuchte man dann den angedeuteten "Zaubercompiler"...
 
G

Guest2

Gast
Wenn ich z.B. etwas in einer Menge suche und die Suche abgebrochen werden kann, sobald einer der Tasks etwas gefunden hat, ist eine parallele Schleife nur die halbe Miete.

Natürlich. Imho gibt es zwei Herangehensweisen ein Problem zu parallelisieren:

1. Man sucht kleine Einheiten heraus (z.B. eine Schleife) parallelisiert diese, kreuzt die Finger und hofft das es schneller geworden ist. (Das ist AUCH das, was ich immer wieder mit "parallelisieren aus dem Kleinen" heraus meine (und trifft in der Tat meistens die Daten-Parallelen Teile zuerst)

2. Man vergisst alles was man über die bisherige Problemlösung weiß, zieht sich in sein dunkles Kämmerlein zurück und betrachtet das Problem als großes Ganzes. (Das ist AUCH das, was ich mit "parallelisieren aus dem Großen" meine (und trifft eben meistens die Task-Parallelen Teile zuerst)

Meiner Erfahrung nach bringt Variante 2 die wesentlich besseren Ergebnisse. Funktionale Programmierung verleitet jedoch oft zu Variante 1. (Variante 1 kann das Laufzeitverhalten von Variante 2 negativ beeinflussen!)


Sollte es mal einen Zauber Compiler geben der das automatisch generiert dann wäre ich mehr als erstaunt.

Sieh Dir z.B. mal den Intel Parallel Advisor an. Insbesondere auch das Overview Viedeo. Das Ding ist aufgebaut wie ein Wizard und führt Dich in mehreren Schritten von einem sequenziellen Programm zu einem parallelen. Die Ergebnisse sind dabei wohl beachtlich (auch wenn ein Profi im dunklen Kämmerlein immer noch bessere Lösungen finden kann). Das Teil ist auch keine Zukunftsmusik, sondern ganz regulär im Handel erhältlich. (und funktioniert auch ganz ohne funktionale Programmierung der Quellsprache :D)


Man kann dort nichts parallelisieren! Selbst mit [c]parallel for[/c] von OpenMP würde dort nichts gehen.

Ohne dem Rest widersprechen zu wollen und von der Vermutung ausgehend das Du das eh bereits weißt (imho war das): [c]#pragma omp parallel for reduction(+:sum)[/c] ;)

Viele Grüße,
Fancy
 

Bronko

Mitglied
Das Intel Video sieht für mich wie eine GUI aus womit ich Threads zusammenfassen kann?! Nicht mehr nicht weniger. Wenn man es böse ausdrücken will ist es nur eine Krücke. Ich denke aber das sich Funktionen mit festen Zuständen und oder immutable Daten immer NOCH erheblich besser parallelisieren lassen werden. Interessante ist das Video alle mal.

Deine zweite variante ist das wovon ich eigentlich spreche (und die anderen auch). Das Problem als ganzes sehen!
Sowas wird kein Compiler der Welt hinbekommen. Vielleicht in weiter Zukunft mittels KI ;-)
"Programmabschnitte" ohne Seiteneffekte lassen sich sehr gut parallelisieren.

FP mittels Rekursion, finalen Variablen und Immutablen Funktionen ist im vergleich zu OOP "merkwürdig" aber auch interessant,elegant und hat als süssen Beigeschmack das man kaum oder keine Seiteneffekte hat.
 

Marco13

Top Contributor
Ohne dem Rest widersprechen zu wollen und von der Vermutung ausgehend das Du das eh bereits weißt (imho war das): [c]#pragma omp parallel for reduction(+:sum)[/c] ;)

Wußte ich nicht :oops: Zugegeben: Ich habe mich mit OpenMP noch nicht so intensiv beschäftigt, wie ich sollte. Das sollte in erster Linie ein Beispiel sein, für etwas, wo für das Parallelisieren nicht das "feingranulare" Wissen relevant ist ("Das ist eine for-Schleife") sondern das "grobgranulare" ("Das ist eine reduction"). Vermutlich wurde dieses 'reduction' wegen seiner besonderen Bedeutung für parallele Programme eingeführt - es gibt sicher ähnliche Beispiele, die nicht so direkt unterstützt werden.

Und außerdem.. sieht dieses OpenMP-Konstrukt im Vergleich zu einem
[c]list.foldLeft(0)(add)[/c]
in Scala dann SO komplizert aus, wie das Scala-Quicksort im Vergleich zu einem Collections.sort :D
 
G

Guest2

Gast
Das Intel Video sieht für mich wie eine GUI aus womit ich Threads zusammenfassen kann?! Nicht mehr nicht weniger. Wenn man es böse ausdrücken will ist es nur eine Krücke.

Nein. Das Tool ist in der Lage das parallele Laufzeitverhalten eines sequenziellen Programms zu simulieren! Und es kann Vorschläge machen, welche Quellcodestellen eine effiziente Parallelisierung versprechen sowie dabei helfen, die zugehörigen Daten- und Laufzeit- Synkonisationspunkte zu bestimmen.


FP mittels Rekursion, finalen Variablen und Immutablen Funktionen...

So einfach ist das in der realen Welt dann aber nicht. Such z.B. mal nach "structural sharing", nur weil etwas immutable aussieht, ist es noch lange nicht so trivial, wie es den Anschein hat. Da sind zum Teil sehr ausgeklügelte Algorithmen im Einsatz. Landei kann Dir da aber bestimmt kompetentere Auskunft geben.


Wußte ich nicht :oops: Zugegeben: Ich habe mich mit OpenMP noch nicht so intensiv beschäftigt, wie ich sollte.

Mal ein wenig mit OpenMP zu "spielen" kann ich nur empfehlen (wir haben damals imho JOMP genutzt (glaube das war noch 0.1 damals ;)). Da die OpenMP Direktiven nur so "locker" in den Quelltext eingestreut werden, hat man die Möglichkeit auch schnell mal verschiedene Varianten eines größeren Problems zu vergleichen. Dabei fällt dann auch auf, das "einfach alles parallel machen" (bei praxisrelevanten Problemen) fürchterlich ineffizient werden kann. (= bei Problemen, die eben nicht "nur" aus Quicksort bestehen, sondern z.B. die Berechnung der Flugbahnen von Satelliten)


Und außerdem.. sieht dieses OpenMP-Konstrukt im Vergleich zu einem [c]list.foldLeft(0)(add)[/c] in Scala dann SO komplizert aus, wie das Scala-Quicksort im Vergleich zu einem Collections.sort :D

Ich weiß, was Du meinst. ;)

Das Problem, was ich dabei sehe, ist das [c]list.foldLeft(0)(add)[/c] alleine wieder fest parallel verdrahtet wäre. Das ist aber eben nicht immer schneller, sondern hängt vom Gesamtkontext ab. Man müsste das dann entweder aufblassen zu einem z.B. [c]list.schedule(dynamic, 15).foldLeft(0)(add)[/c] (OpenMP Style) oder ein (verstecktes) komplexes Runtime-/Build- Ressourcenmanagement entwickeln, welches diese Einstellungen automatisch vornehmen kann (was nicht einfach werden könne ;)).

Viele Grüße,
Fancy
 
G

Guest2

Gast
Ateji PX kannte ich noch nicht ;) (ToDo hat jetzt wieder einen neuen Punkt)

(das Zeitproblem kenne ich hingeben leider auch...)

Viele Grüße,
Fancy
 

Bronko

Mitglied
Ateji sieht erstmal interessant aus. Interessant ist auch:

With Ateji PX, a source code written in message-passing style will also run without modifications on computer clusters, MPI-based supercomputers, across a network, and in the Cloud. A distributed version of Ateji PX is in preparation, where parallel branches can be run at remote locations. Watch Java Parallel Programming, Portfolio Optimization Software & Java Threads Made Simple - Ateji PX for announcements.
Message-passing at the language level also enables a simple expression of a wide range of parallel programming paradigms, including data-flow, stream programming, the Actor model, and the MapReduce algorithm.
 

Bronko

Mitglied
Nun gut das zur Parallelität ;)
Ups... noch ein kleine Ergänzung.Die Spielindustrie hat jahrelang an der MultiCore Auslastung gearbeitet. Ich denke gute Parallelität läßt sich weder mit Zauber-Compilern noch mit Tools realisieren und funktioniert sicherlich am besten mittels Designe im Quellcode.

Abschliessend kann man noch sagen das man vor Scala keine angst haben braucht. Wer sich mittels Scala ins Knie schießen will kann das sicherlich tun, wer seine Kollegen "ärgern" will mit unlesbaren Sourcecode der kann das sicher auch machen. Man sollte dabei aber auch die ganzen vorteile nicht vergessen. Wer hat gesagt man MUSS alles via FP lösen? Wer hat gesagt man MUSS kryptischen Code schreiben ? Gibt den krams eine Chance und ihr werdet merken das es eigentlich keine nachteile sondern nur vorteile in Scala gegenüber Java gibt. Scala ist wie die "Macht" aus StarWars. Man kann viel gutes damit tun aber auch viel schlechtes ;)


IMHO :bae:
 
S

SlaterB

Gast
Nun gut das zur Parallelität ;)
Man sollte dabei aber auch die ganzen vorteile nicht vergessen. Wer hat gesagt man MUSS alles via FP lösen? Wer hat gesagt man MUSS kryptischen Code schreiben ? Gibt den krams eine Chance und ihr werdet merken das es eigentlich keine nachteile sondern nur vorteile in Scala gegenüber Java gibt. Scala ist wie die "Macht" aus StarWars. Man kann viel gutes damit tun aber auch viel schlechtes ;)
die letzten Seiten nicht gelesen,
aber einfach um mal wieder irgendwas reinzuschießen:
nach der Begründung könnte man auch zu C++ oder was auch immer mit Pointern direkt im Speicher zurückgehen,
muss man ja nicht verwenden..
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
K Unterschied funktionial <-> OO anhand von Scala <-> Java JVM Sprachen: Kotlin, Scala, Groovy, Jython... 5
M Experten für Scala-Play- Programmierung gesucht!! JVM Sprachen: Kotlin, Scala, Groovy, Jython... 3
M Scala-Programm mit Netbeans compilieren JVM Sprachen: Kotlin, Scala, Groovy, Jython... 1
M Suche Scala Entwickler (Umsteiger [JAVA]) für Zusammenarbeit an privatem Projekt JVM Sprachen: Kotlin, Scala, Groovy, Jython... 7
R Frage zu Scala Code JVM Sprachen: Kotlin, Scala, Groovy, Jython... 2
Landei Scala Scala 2.10 RC JVM Sprachen: Kotlin, Scala, Groovy, Jython... 3
schlingel Scala Schulung - Gratis vom Scala-Schöpfer JVM Sprachen: Kotlin, Scala, Groovy, Jython... 2
Spin Scala Eclipse IDE JVM Sprachen: Kotlin, Scala, Groovy, Jython... 7
Spin Funktionen vs Methods in Scala JVM Sprachen: Kotlin, Scala, Groovy, Jython... 9
Landei Scala Freies eBook "Scala for the impatient" JVM Sprachen: Kotlin, Scala, Groovy, Jython... 2
Spin Arithmetik in Scala JVM Sprachen: Kotlin, Scala, Groovy, Jython... 32
0x7F800000 Numerik in Scala (Performance) JVM Sprachen: Kotlin, Scala, Groovy, Jython... 14
Spin Scala MenuListener JVM Sprachen: Kotlin, Scala, Groovy, Jython... 5
Spin Scala in Eclipse will nicht. JVM Sprachen: Kotlin, Scala, Groovy, Jython... 15
Landei Scala Deutsches Scala-Tutorial JVM Sprachen: Kotlin, Scala, Groovy, Jython... 3
B Scala oder Clojure JVM Sprachen: Kotlin, Scala, Groovy, Jython... 6
Landei Scala "Programming in Scala" - erste Ausgabe kostenlos JVM Sprachen: Kotlin, Scala, Groovy, Jython... 1
W Scala *.Scala to *.jar JVM Sprachen: Kotlin, Scala, Groovy, Jython... 6
H Scala und Aspekte JVM Sprachen: Kotlin, Scala, Groovy, Jython... 4
S Scala Klasse.class in Scala? JVM Sprachen: Kotlin, Scala, Groovy, Jython... 4
B Scala Scala und Netbeans GUI Editor JVM Sprachen: Kotlin, Scala, Groovy, Jython... 15
S Scala: Parser und Lexical JVM Sprachen: Kotlin, Scala, Groovy, Jython... 2
D Wie manche ich das in Scala JVM Sprachen: Kotlin, Scala, Groovy, Jython... 12
S Scala: Static - Konstruktor?? JVM Sprachen: Kotlin, Scala, Groovy, Jython... 5
G Scala IDE JVM Sprachen: Kotlin, Scala, Groovy, Jython... 18
A Scala und J2ME JVM Sprachen: Kotlin, Scala, Groovy, Jython... 2
S Scala Fragen zu Scala JVM Sprachen: Kotlin, Scala, Groovy, Jython... 21
D (Mathe-) Vektoren in Scala JVM Sprachen: Kotlin, Scala, Groovy, Jython... 4
Landei Scala im Kommen :-) JVM Sprachen: Kotlin, Scala, Groovy, Jython... 4

Ähnliche Java Themen

Neue Themen


Oben