Parallel Assign() ist auf bestimmten Geräten langsamHallo zusammen,
es scheint ein Problem mit Parallel Assign() in Kombination mit bestimmten Systemen zu geben.
Ich habe Zugriff auf 3 Windows 10 PCs mit JMP 16.1.:
- Laptop: Core i5-8350U (4 Kerne) @ 1,9 GHz, 16GB Ram
- Alte Workstation: Xeon E5-1660 v4 (8Kerne) @ 3,2 GHz, 256GB Ram
- Neue Workstation Xeon W-2145 (8 Kerne) @3,7 GHz, 128GB Ram
Ich habe die Leistung der parallelen und der sequentiellen Version meines Testskripts mit unterschiedlichen Problemgrößen auf allen Systemen verglichen (Skript unten).
Das Ergebnis war überraschend schlecht. Nur auf meinem Laptop ist die parallele Version etwas schneller als die sequentielle Version, aber auf den Workstations bis zu mehr als 2 mal langsamer.
Hat jemand ähnliche Leistungsprobleme mit Parallel Assign() erlebt? Oder verwende ich es falsch? Was geht hier vor sich?
rauben


n_different_ids = 100000;
<BR />// Just generate random data. Every 15 rows must be processed at the same time.
DT_Data = J( 15*n_different_ids, 9, 0 );
For ( i = 1, i <= n_different_ids, i++,
DT_Data[15*(i-1)+(1::15),0] = i + J( 15, 9, Random Normal() );
);
<BR />// some function
F_percentile = Function( {x , p},
x = Sort Ascending(x);
n = N Rows(x);
index = 1 + (n - 1) * p;
index_ibelow = Floor(index);
index_iabove = Ceiling(index);
h = index - index_ibelow;
result = (1 - h) * x[index_ibelow] + h * x[index_iabove];
result;
);
<BR />// parallel version
DT_Features = J( n_different_ids, 16, 0 );
start=tick seconds();
Parallel Assign( {
DT_Data = DT_Data,
F_percentile = Name Expr( F_percentile )
},
DT_Features[i,j] = (
i_same_group = Loc(DT_Data[15*(i-1)+(1::15), 1]);
data = DT_Data[15*(i-1)+i_same_group, 1+Ceiling(j/2)];
If (mod(j,2),
result = F_percentile(data, 0.95);
,
result = F_percentile(data, 0.05);
);
result;
)
);
time_parallel = tick seconds()-start;
Show(time_parallel);
Wait(0.1);
<BR />// sequential version
DT_Features = J( n_different_ids, 16, 0 );
start=tick seconds();
for(i=1,i<=n_different_ids,i++,
for(j=1,j<=16,j++,
i_same_group = Loc(DT_Data[15*(i-1)+(1::15), 1]);
data = DT_Data[15*(i-1)+i_same_group, 1+Ceiling(j/2)];
If (mod(j,2),
result = F_percentile(data, 0.95);
,
result = F_percentile(data, 0.05);
);
DT_Features[i,j] =result;
);
);
time_sequential = tick seconds()-start;
Show(time_sequential);
SkriptingBetreff: Parallel Assign() ist auf bestimmten Geräten langsamDies ist eine 4-CPU 16GB ~3GHz Maschine JMP16/win10 unter VirtualBox. Ich sehe die Geschwindigkeit, die ich erwarten würde (nicht 4X, aber immer noch gut.)
n_verschiedene_ids = 100.000;
time_parallel = 13,9833333333333;
time_sequential = 37,73333333333333;
n_unterschiedliche_ids = 1.000.000;
time_parallel = 141.233333333333;
time_sequential = 375.016666666667;
Die parallele Zuweisung kopiert eine große Matrix für jede CPU, aber die linearen Diagramme deuten bei diesen Größen nicht auf ein Paging-Problem hin.
Beobachten Sie den Windows-Taskmonitor für CPU- und Speicher- (und Datenträger-) Nutzung und sehen Sie, ob er etwas erklärt. Ich habe 100 % beim parallelen Zuweisen und 25 % beim sequentiellen Test gesehen. Ich habe auch gesehen, dass 7 GB während der größeren parallelen Zuweisung verwendet wurden.
Taskmanager
Betreff: Parallel Assign() ist auf bestimmten Geräten langsamHallo Craige,
Ich schaue mir gerade meine Workstation mit der schlechtesten Leistung an (unten). Im Taskmanager habe ich nichts Verdächtiges gesehen. Außer der CPU ist nichts annähernd voll belegt.
Was mir auch aufgefallen ist, ist, dass JMP 15.2.1 in den parallelen und sequentiellen Versionen immer schneller ist. Bei n=100.000 benötigt JMP 16.1 etwa 36s/18s (parallel/sequentiell) und JMP 15.2.1 31s/15s, was etwas besser ist, aber immer noch weit weg von einer guten Parallelleistung. Leider habe ich keine ältere Version mehr zur Verfügung. Ich habe diesen Code mit JMP 12 geschrieben und habe damals keine Leistungsprobleme festgestellt (und die PCs, die ich verwendet habe, waren auch anders).
rauben

Betreff: Parallel Assign() ist auf bestimmten Geräten langsamIch kann dieses Verhalten auf meinem Laptop (Win 10, JMP 16.1) bestätigen:
time_parallel = 158,7;
time_sequential = 157.76666666667;
n=1000000
Betreff: Parallel Assign() ist auf bestimmten Geräten langsamNicht sicher. Ich habe JMP eine Notiz zu diesem Thread geschickt; Vielleicht möchten Sie auch mit dem technischen Support sprechen.
Meine Vermutung (und das ist alles!) ist, dass JMP etwas ändern muss, um die Leistung auf der neuen Hardware zurückzubekommen. Mit nur 4 virtuellen CPUs kann ich nicht dasselbe sehen, was Sie sehen.
Betreff: Parallel Assign() ist auf bestimmten Geräten langsamAußerdem habe ich die Anzahl der Kerne im Task-Manager, die JMP zur Verfügung stehen, auf der neuen Workstation auf 2, 4 und 8 beschränkt. Die parallele Version bleibt immer noch langsamer als die sequentielle. Ich vermute, dass JMP veraltete Bibliotheken im Hintergrund verwendet, die auf neuen Hardwarearchitekturen schlecht laufen.
Danke Craige, ich werde mich diesbezüglich an den technischen Support wenden.
Betreff: Parallel Assign() ist auf bestimmten Geräten langsamFür meinen 3,6 GHz 4-Kern-Rechner und N = 100k:
Ich erhalte eine 1,4-fache Beschleunigung mit dem parallelen Code über sequentiell (12,8s parallel vs 17,8s sequentiell). Dies ist nicht so gut wie die 2,7-fache Beschleunigung, die Craige gesehen hat, aber es ist besser als das Verlangsamungsverhalten, das Sie auf den Workstations gesehen haben. Ich wollte jedoch sehen, ob ich damit etwas mehr Leistung herausholen kann, also habe ich einige Änderungen vorgenommen.
Ich habe den Funktionsaufruf-Overhead (Kopien von Matrixargumenten usw.) entfernt, indem ich stattdessen Ausdrücke verwendet habe. Dies brachte mich auf eine 2,5-fache Geschwindigkeit (4,5s parallel vs 11,3s sequentiell) und ein gutes Stück schneller als das Original. Und schließlich habe ich versucht, die Loops ein wenig umzuordnen und die sequentielle Version auf 4s herunterzuschrauben. Dies ist schneller als die parallele Version, aber die Neuordnung ist mit Parallel Assign nicht so einfach zu bewerkstelligen. Ich habe einige verschiedene N getestet und diese Muster schienen zu halten, aber ich habe keinen vollständigen Sweep wie in Ihrer obigen Tabelle durchgeführt. Finden Sie den angehängten Code.
Parallel: 12.78
Sequenziell: 17.80
Parallel_Ausdruck: 4.50
Sequential_Expr: 11.27
Sequential_Expr_Opt: 3.98
Betreff: Parallel Assign() ist auf bestimmten Geräten langsamOh, wow danke! Ausführen Ihres Skripts auf meiner neueren Workstation, die ich bekomme
Parallel: 37.0833333333139
Sequenziell: 19.7166666666453
Parallel_Ausdruck: 6.93333333331975
Sequential_Expr: 12.5333333333256
Sequential_Expr_Opt: 4.5499999999836
Betrachten wir Sequential_Expr_Opt nicht, weil es ein unfairer Vergleich ist. 
Sie haben gerade die Funktion durch einen Ausdruck ersetzt und ich bekomme eine Beschleunigung von ungefähr 1,5 für die sequentielle und mehr als 5 (!!!) für die parallele Version? Das ist eine großartige Problemumgehung. Was lerne ich also daraus? Nie Funktionen in JSL verwenden? Das ist ein bisschen unangenehm, weil Funktionen Code lesbarer machen und für andere einfacher und sicherer zu verwenden und zu ändern. Ich denke jedoch, dass es irgendwo hinter den Kulissen immer noch ein Problem gibt, da meine ursprüngliche parallele Version immer noch doppelt so lange dauert wie die ursprüngliche sequentielle und dies ist bei Craiges virtueller Maschine nicht der Fall.
Update: Hier ist der vollständige Scan auf der neuen Workstation:


Betreff: Parallel Assign() ist auf bestimmten Geräten langsamIch habe Craiges Ratschläge befolgt und vor zwei Wochen den technischen Support kontaktiert. Nach einigen Anfragen zu meinen PCs erhielt ich heute die Antwort, dass Entwickler eingebunden wurden, um das Verhalten zu untersuchen und Probleme in einer zukünftigen JMP-Version zu beheben.
Trotzdem nochmals vielen Dank Evan für die Beschleunigung dieses speziellen Skripts.
Betreff: Parallel Assign() ist auf bestimmten Geräten langsamHi @Robbb , zwei gedanken:
Geschwindigkeit programmieren
Das Ziel Ihres Codes kann einen großen Einfluss darauf haben, wie Sie ihn schreiben.Für die überwiegende Mehrheit der Skripte spielt die zusätzliche Zeit, die zum Aufrufen einer Funktion oder zum Kopieren eines Symbols benötigt wird, keine Rolle, also sollten Sie Funktionen verwenden und den Code leicht interpretierbar machen.Auf der anderen Seite, wenn Sie an einem Projekt arbeiten, das groß ist und so oft wiederholt wird, dass es Ihnen wichtig ist, wie lange es dauert, dann möchten Sie vielleicht ein paar Feinheiten gegen die rohe Leistung eintauschen.Ich ermutige Sie, nur Zeit damit zu verbringen, Dinge zu optimieren, die wirklich wichtig sind.Verbringen Sie jetzt keine zusätzliche Stunde damit, etwas zu programmieren, und müssen Sie dann eine zusätzliche Stunde damit verbringen, herauszufinden, was Sie nach einem Jahr getan haben, weil Sie es komplizierter gemacht haben, es zu beschleunigen, nur um den Benutzern einmal pro Tag zusätzliche 20 Sekunden zu sparen .
Paralleler Trade-off
Bei der Entscheidung, ob eine parallele Ausführung erfolgen soll, müssen Sie den Aufwand für die Einrichtung dieses 'untergeordneten' Threads mit der Arbeit, die er ausführen wird, abwägen.Stellen Sie sich vor, Sie würden parallele Jobs ausführen, indem Sie eine weitere Kopie von JMP öffnen, eine Datentabelle öffnen und auf Ausführen klicken. Wenn Sie es eine Stunde lang laufen lassen, dann sparen Sie eine Menge Zeit, anstatt nur ein Skript alles erledigen zu lassen, aber wenn dieses Skript 20 Sekunden lang ausgeführt wird, haben Sie wahrscheinlich mehr Zeit damit verbracht, es zu starten, als Sie gespart haben.Ja, der Overhead ist hier viel geringer, aber das Kopieren von Symbolen und das Zuweisen von Speicher nimmt Zeit in Anspruch.Stellen Sie sicher, dass die Arbeit Ihres Skripts nach der Einrichtung der Umgebung erheblich ist.Eine Möglichkeit, dies zu erreichen, besteht darin, die Schleife in nur 4 Teile aufzuteilen und jeden Thread gleichzeitig mit einem Viertel der Werte arbeiten zu lassen.Teilen Sie Ihre Liste also in vier Teile mit jeweils einem Viertel der Zeilen auf und lassen Sie dann Ihr Skript jede Unterliste nacheinander verarbeiten. Auf diese Weise reduzieren Sie den Zeitaufwand für das Einrichten von untergeordneten Threads von n row()-mal auf 4.
Betreff: Parallel Assign() ist auf bestimmten Geräten langsamHi @ich h ,
zustimmen.
Der Aufwand für die Einrichtung eines Kindes spielt in meinem Fall keine große Rolle, daher habe ich nicht viel Zeit damit verbracht, dies so effektiv wie möglich zu gestalten. Dieses Skript soll nicht nur ein paar Minuten laufen. Bevor ich mit diesem Thema angefangen habe, habe ich genau das gemacht, was Sie vorgeschlagen haben. Ich habe meinen Datensatz in 8 Teile zerlegt und er war innerhalb von 0,5 Tagen fertig. Aus Interesse habe ich später auch Evans "Sequential_Expr_Opt"-Version ausprobiert, und es dauerte zwischen 1,5 und 4 Tage, bis mein Datensatz fertig war (begann Donnerstagmorgen, war nicht Freitagnachmittag, sondern Montagmorgen fertig).
Dieser Thread sollte zeigen, dass hinter den Kulissen generell etwas nicht stimmt. In der Vergangenheit habe ich hin und wieder eine schlechte Parallelperformance von JMP bemerkt und das hat mich gestört. Ich mag JMP und probiere gerne Dinge damit aus, von denen andere sagen, dass sie mit JMP nicht möglich sind. Und ich bin mehr als froh, dass Entwickler sich damit beschäftigen.
Ich muss jedoch sagen, dass es bessere Tools gibt, um mit wirklich großen Datensätzen umzugehen, als JMP. Zumindest im Moment. 