Wenn Sie eine Milliarde Zahlen und einhundert Computer haben, wie können Sie den Median dieser Zahlen am besten ermitteln?
Eine Lösung, die ich habe, ist:
- Teilen Sie das Set gleichmäßig auf die Computer auf.
- Sortieren Sie sie.
- Finden Sie die Mediane für jeden Satz.
- Sortieren Sie die Sätze nach Medianen.
- Führen Sie zwei Sätze gleichzeitig vom niedrigsten zum höchsten Median zusammen.
Wenn wir m1 < m2 < m3 ...
dann zuerst zusammenführen Set1
und Set2
und in der resultierenden Menge können wir alle Zahlen verwerfen, die niedriger als der Median von Set12
(zusammengeführt) sind. Wir haben also zu jedem Zeitpunkt gleich große Mengen. Dies kann übrigens nicht parallel erfolgen. Irgendwelche Ideen?
Antworten:
Ah, mein Gehirn hat gerade einen Gang eingelegt, ich habe jetzt einen vernünftigen Vorschlag. Wahrscheinlich zu spät, wenn dies ein Interview gewesen wäre, aber egal:
Maschine 1 wird als "Steuermaschine" bezeichnet, und aus Gründen der Argumentation beginnt sie entweder mit allen Daten und sendet sie in gleichen Paketen an die anderen 99 Maschinen, oder die Daten werden gleichmäßig zwischen den Maschinen verteilt, und sie sendet 1/99 seiner Daten an die anderen. Die Partitionen müssen nicht gleich sein, sondern nur schließen.
Jede andere Maschine sortiert ihre Daten auf eine Weise, die es bevorzugt, zuerst die niedrigeren Werte zu finden. Zum Beispiel eine Quicksortierung, bei der immer zuerst der untere Teil der Partition sortiert wird [*]. Es schreibt seine Daten so schnell wie möglich in aufsteigender Reihenfolge auf die Steuerungsmaschine zurück (unter Verwendung von asynchronem E / A, um die Sortierung fortzusetzen, und wahrscheinlich mit eingeschaltetem Nagle: Experimentieren Sie ein wenig).
Die Steuerungsmaschine führt beim Eintreffen eine 99-Wege-Zusammenführung der Daten durch, verwirft jedoch die zusammengeführten Daten und zählt nur die Anzahl der Werte, die sie gesehen hat. Der Median wird als Mittelwert aus den Werten 1/2 1/2 und 1/2 Milliarde plus 1 berechnet.
Dies leidet unter dem Problem "am langsamsten in der Herde". Der Algorithmus kann erst abgeschlossen werden, wenn jeder Wert, der unter dem Median liegt, von einer Sortiermaschine gesendet wurde. Es besteht eine vernünftige Wahrscheinlichkeit, dass ein solcher Wert in seinem Datenpaket ziemlich hoch ist. Sobald die anfängliche Partitionierung der Daten abgeschlossen ist, ist die geschätzte Laufzeit die Kombination aus der Zeit, um 1/99 der Daten zu sortieren und an den Steuercomputer zurückzusenden, und der Zeit, die die Steuerung benötigt, um die Hälfte der Daten zu lesen . Die "Kombination" liegt irgendwo zwischen dem Maximum und der Summe dieser Zeiten, wahrscheinlich nahe am Maximum.
Mein Instinkt ist, dass es ein verdammt schnelles Netzwerk sein muss, damit Daten über ein Netzwerk schneller gesendet werden als sortiert werden (geschweige denn nur der Median ausgewählt wird). Könnte eine bessere Perspektive sein, wenn davon ausgegangen werden kann, dass das Netzwerk sofort verfügbar ist, z. B. wenn Sie über 100 Kerne mit gleichem Zugriff auf den RAM verfügen, der die Daten enthält.
Da Netzwerk-E / A wahrscheinlich gebunden sind, können Sie möglicherweise einige Streiche spielen, zumindest für die Daten, die zur Steuerungsmaschine zurückkehren. Anstatt beispielsweise "1,2,3, .. 100" zu senden, könnte eine Sortiermaschine möglicherweise eine Nachricht senden, die "100 Werte kleiner als 101" bedeutet. Die Steuermaschine könnte dann eine modifizierte Zusammenführung durchführen, bei der sie den geringsten dieser Werte im oberen Bereich findet und dann allen Sortiermaschinen mitteilt, was es war, damit sie (a) der Steuermaschine mitteilen können, wie viele Werte, die unter diesem Wert "gezählt" werden sollen, und (b) das Senden ihrer sortierten Daten von diesem Punkt an fortsetzen.
Im Allgemeinen gibt es wahrscheinlich ein cleveres Rätselraten, bei dem die Steuerungsmaschine mit den 99 Sortiermaschinen spielen kann.
Dies beinhaltet jedoch Hin- und Rückfahrten zwischen den Maschinen, was meine einfachere erste Version vermeidet. Ich weiß nicht wirklich, wie ich ihre relative Leistung blind einschätzen soll, und da die Kompromisse komplex sind, stelle ich mir vor, dass es viel bessere Lösungen gibt als alles, was ich mir vorstellen werde, vorausgesetzt, dies ist jemals ein echtes Problem.
[*] verfügbarer Stapel zulässig - Ihre Auswahl, welcher Teil zuerst ausgeführt werden soll, ist eingeschränkt, wenn Sie nicht über O (N) zusätzlichen Speicherplatz verfügen. Wenn Sie jedoch über genügend zusätzlichen Platz verfügen, können Sie Ihre Wahl treffen. Wenn Sie nicht über genügend Platz verfügen, können Sie zumindest das verwenden, was Sie zum Schneiden einiger Ecken benötigen, indem Sie den kleinen Teil zuerst für die ersten Partitionen ausführen.
quelle
quelle
time
Befehl, der auf die gesamte Pipeline angewendet wurde, dauerte esreal=36m24s
("Wanduhrzeit")user=113m15s
("Parallelzeit", alle Kerne hinzugefügt). Der längste Befehl, weit vor den anderen, warsort
, selbst wenn er zu 100% auf meine vier Kerne traf. Der RAM-Verbrauch war sehr akzeptabel.Ich hasse es, hier der Gegenspieler zu sein, aber ich glaube nicht, dass eine Sortierung erforderlich ist, und ich denke, dass jeder Algorithmus, bei dem eine Milliarde / 100-Zahlen sortiert werden, langsam sein wird. Betrachten wir einen Algorithmus auf einem Computer.
1) Wählen Sie zufällig 1000 Werte aus der Milliarde aus und verwenden Sie diese, um eine Vorstellung von der Verteilung der Zahlen, insbesondere eines Bereichs, zu erhalten.
2) Anstatt die Werte zu sortieren, ordnen Sie sie Buckets basierend auf der soeben berechneten Verteilung zu. Die Anzahl der Eimer wird so gewählt, dass der Computer sie effizient handhaben kann, sollte aber ansonsten so groß wie möglich sein. Die Bucket-Bereiche sollten so sein, dass ungefähr die gleiche Anzahl von Werten in jedem Bucket gespeichert wird (dies ist für den Algorithmus nicht kritisch, trägt jedoch zur Effizienz bei. 100.000 Buckets sind möglicherweise angemessen). Notieren Sie die Anzahl der Werte in jedem Bucket. Dies ist ein O (n) -Prozess.
3) Finden Sie heraus, in welchem Bucket-Bereich der Median liegt. Dies kann durch einfaches Untersuchen der Gesamtzahl in jedem Bucket erfolgen.
4) Ermitteln Sie den tatsächlichen Median, indem Sie die Werte in diesem Bucket untersuchen. Sie können hier eine Sortierung verwenden, wenn Sie möchten, da Sie nur vielleicht 10.000 Zahlen sortieren. Wenn die Anzahl der Werte in diesem Bucket groß ist, können Sie diesen Algorithmus erneut verwenden, bis Sie eine ausreichend kleine Anzahl zum Sortieren haben.
Dieser Ansatz wird trivial parallelisiert, indem die Werte zwischen den Computern aufgeteilt werden. Jeder Computer meldet die Gesamtsummen in jedem Bucket an einen Steuercomputer, der Schritt 3 ausführt. In Schritt 4 sendet jeder Computer die (sortierten) Werte im entsprechenden Bucket an den Steuercomputer (Sie können beide Algorithmen auch parallel ausführen). aber es lohnt sich wahrscheinlich nicht).
Der Gesamtprozess ist O (n), da beide Schritte 3 und 4 trivial sind, vorausgesetzt, die Anzahl der Eimer ist groß genug.
quelle
Eine Milliarde ist eigentlich eine ziemlich langweilige Aufgabe für einen modernen Computer. Wir sprechen hier von 4 GB im Wert von 4 Byte Ganzzahlen ... 4 GB ... das ist der RAM einiger Smartphones.
Ausgabe auf meinem Computer:
Dies ist auf meinem Computer innerhalb von weniger als zwei Minuten (1:43 davon 0:10 sollen Zufallszahlen generieren) mit einem einzigen Kern abgeschlossen und führt sogar eine vollständige Sortierung durch. Eigentlich nichts Besonderes.
Dies ist sicherlich eine interessante Aufgabe für größere Mengen von Zahlen. Ich möchte hier nur einen Punkt hervorheben: Eine Milliarde sind Erdnüsse. Überlegen Sie also zweimal, bevor Sie komplexe Lösungen für überraschend einfache Aufgaben einsetzen;)
quelle
(numbers[numbers.length / 2]+numbers[numbers.length / 2+1])/2
wennnumbers.length
ist gerade undnumbers[numbers.length / 2]
nur wennnumbers.length
ist ungerade.Die Schätzung von Ordnungsstatistiken wie Median und 99. Perzentil kann mit Algorithmen wie T-Digest oder Q-Digest effizient verteilt werden .
Mit beiden Algorithmen erzeugt jeder Knoten einen Digest, der die Verteilung der lokal gespeicherten Werte darstellt. Die Digests werden an einem einzelnen Knoten gesammelt, zusammengeführt (wodurch die Verteilungen effektiv summiert werden), und der Median oder ein anderes Perzentil kann dann nachgeschlagen werden.
Dieser Ansatz wird von elasticsearch und vermutlich BigQuery verwendet ( gemäß der Beschreibung der Funktion QUANTILES).
quelle
Der Median für diesen Satz von Zahlen
2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89, 97
ist 67.
Der Median für diesen Satz von Zahlen
2, 3, 5, 7, 11, 13, 67, 71, 73, 79, 83, 89
ist 40.
Angenommen, die Frage war ungefähr 1.000.000.000 ganze Zahlen (x), wobei 0> = x <= 2.147.483.647, und das OP suchte (Element (499.999.999) + Element (500.000.000)) / 2 (wenn die Zahlen sortiert waren). Auch unter der Annahme, dass alle 100 Computer alle gleich waren.
mit meinem Laptop und GigE ...
Was ich fand, war, dass mein Laptop in 1,3 Sekunden 10.000.000 Int32 sortieren kann. Eine grobe Schätzung wäre also, dass eine Milliardenzahlsortierung 100 x 1,3 Sekunden (2 Minuten 10 Sekunden) dauern würde;).
Eine Schätzung einer Einweg-Dateiübertragung einer 40-MB-Datei auf einem Gigabit-Ethernet beträgt 0,32 Sekunden. Dies bedeutet, dass die sortierten Ergebnisse aller Computer in ungefähr 32 Sekunden zurückgegeben werden (Computer 99 hat seine Datei erst 30 Sekunden nach dem Start erhalten). Von dort sollte es nicht lange dauern, die niedrigsten 499.999.998 Zahlen zu verwerfen, die nächsten 2 zu addieren und durch 2 zu teilen.
quelle
a*(1e7)log(1e7) = 1.3sec
=>a = 1.6e-9sec
=>a*(1e9)log(1e9) ~ 167sec
, also war Ihre Schätzung nicht so falsch.Dies mag die Leute überraschen, aber wenn die Zahlen ganze Zahlen sind, die in 32-Bit (oder kleiner) passen - machen Sie einfach eine Bucket-Sortierung! Benötigt nur 16 GB RAM für eine beliebige Anzahl von 32-Bit-Ints und läuft in O (n), was alle verteilten Systeme für vernünftige n, z. B. eine Milliarde, übertreffen sollte.
Sobald Sie die sortierte Liste haben, ist es trivial, den Median auszuwählen. Tatsächlich müssen Sie die sortierte Liste nicht erstellen, sondern sollten nur die Buckets betrachten.
Eine einfache Implementierung ist unten gezeigt. Funktioniert nur für 16-Bit-Ganzzahlen, die Erweiterung auf 32-Bit sollte jedoch einfach sein.
Verwenden einer Textdatei mit einer Milliarde (10 9 ) Zahlen und Ausführen mit
time
Ähnlichemergibt eine Laufzeit auf meinem Computer 1m49.293s. Die meiste Laufzeit ist wahrscheinlich auch Festplatten-E / A.
quelle
Seltsamerweise denke ich, wenn Sie über genügend Computer verfügen, ist das Sortieren besser als die Verwendung von
O(n)
Median-Finding-Algorithmen. (Wenn Ihre Kerne jedoch nicht sehr, sehr langsam sind, würde ich nur einen verwenden und einenO(n)
Median-Finding-Algorithmus für nur 1e9-Zahlen verwenden. Wenn Sie jedoch 1e12 hätten, wäre dies möglicherweise weniger praktisch.)Nehmen wir an, wir haben mehr als nur log n Kerne, um dieses Problem zu lösen, und wir kümmern uns nicht um den Stromverbrauch, sondern bekommen nur schnell die Antwort. Nehmen wir weiter an, dass dies eine SMP-Maschine ist, auf der alle Daten bereits im Speicher geladen sind. (Die 32-Kern-Maschinen von Sun sind beispielsweise von diesem Typ.)
Ein Thread zerlegt die Liste blind in gleich große Stücke und weist die anderen M-Threads an, sie zu sortieren. Diese Threads tun dies fleißig und
(n/M) log (n/M)
rechtzeitig. Sie geben dann nicht nur ihre Mediane zurück, sondern beispielsweise auch ihre 25. und 75. Perzentile (perverse Worst-Cases sind besser, wenn Sie leicht unterschiedliche Zahlen wählen). Jetzt haben Sie 4 Millionen Datenbereiche. Anschließend sortieren Sie diese Bereiche und arbeiten die Liste nach oben durch, bis Sie eine Zahl finden, bei der Sie die Hälfte Ihrer Daten verworfen haben , wenn Sie jeden Bereich wegwerfen, der kleiner ist oder die Zahl enthält. Das ist Ihre Untergrenze für den Median. Machen Sie dasselbe für die Obergrenze. Dies dauert ungefähr so langeM log M
und alle Kerne müssen darauf warten, also ist es wirklich verschwenderischM^2 log M
mögliche Zeit. Jetzt muss Ihr einzelner Thread die anderen anweisen, alle Daten außerhalb des Bereichs zu werfen (Sie sollten bei jedem Durchgang etwa die Hälfte wegwerfen) und wiederholen - dies ist eine trivial schnelle Operation, da die Daten bereits sortiert sind. Sie sollten dies nicht öfter wiederholen müssen,log(n/M)
bevor es schneller ist, nur die verbleibenden Daten zu erfassen und einen Standard-O(n)
Median-Finder zu verwenden.Die Gesamtkomplexität ist also so etwas wie
O((n/M) log (n/M) + M^2 log M log (n/M))
. Dies ist also schneller als dieO(n)
Mediansortierung auf einem Kern, wennM >> log(n/M)
undM^3 log M < n
, was für das von Ihnen beschriebene Szenario gilt.Ich denke, das ist eine wirklich schlechte Idee, wenn man bedenkt, wie ineffizient es ist, aber es ist schneller.
quelle
n
undM
sind die Variablen, die beliebig skaliert werden können, also enthält man beide. Insbesondere habe ich das postuliertM
>log n
, was bedeutet, dass Sie sich auch darum kümmern müssen, wenn Sie sich dafür interessieren, dass es nichtn log n
nur gerechtn
istM
.Dies kann schneller erfolgen als der gewählte Algorithmus (n log n)
- Verteilter Auswahlalgorithmus für Ordnungsstatistiken - O (n)
Vereinfachen Sie das Problem mit dem ursprünglichen Problem, die k-te Zahl in einem unsortierten Array zu finden.
- Sortierhistogramm zählen O (n)
Sie müssen einige Eigenschaften über den Bereich der Zahlen annehmen - kann der Bereich in den Speicher passen? - Externe Zusammenführungssortierung - O (n log n) - oben beschrieben
Sie sortieren die Zahlen im Grunde genommen beim ersten Durchgang und finden dann den Median beim zweiten Durchgang.
- Wenn etwas über die Verteilung der Zahlen bekannt ist, können andere Algorithmen erzeugt werden.
Weitere Details und die Implementierung finden Sie unter:
http://www.fusu.us/2013/07/median-in-large-set-across-1000-servers.html
quelle
Ein Computer ist mehr als genug, um das Problem zu lösen.
Nehmen wir jedoch an, dass es 100 Computer gibt. Das einzig komplexe, was Sie tun sollten, ist die Liste zu sortieren. Teilen Sie es auf 100 Teile auf, senden Sie ein Teil an jeden Computer, lassen Sie es dort sortieren und führen Sie danach Teile zusammen.
Nehmen Sie dann die Nummer aus der Mitte der sortierten Liste (dh mit dem Index 5 000 000 000).
quelle
Das hängt von Ihren Daten ab. Das schlimmste Szenario ist, dass es sich um gleichmäßig verteilte Zahlen handelt.
In diesem Fall finden Sie den Median in O (N) -Zeit wie in diesem Beispiel:
Angenommen, Ihre Zahlen sind 2,7,5,10,1,6,4,4,6,10,4,7,1,8,4,9,9,3,4,3 (Bereich 1-10) .
Wir erstellen 3 Eimer: 1-3, 4-7, 8-10. Beachten Sie, dass oben und unten gleich groß sind.
Wir füllen die Eimer mit den Zahlen, zählen, wie viele in jede fallen, die maximale und die minimale
Der Mittelwert fällt in den mittleren Eimer, den Rest ignorieren wir
Wir erstellen 3 Eimer: 4, 5-6, 7. Niedrig beginnt mit einer Zählung von 5 und mit einem Maximum von 3 und hoch mit einer Min von 8 und einer Zählung von 5.
Für jede Zahl zählen wir, wie viele in den niedrigen und hohen Eimer fallen, den maximalen und den minimalen, und behalten den mittleren Eimer.
Jetzt können wir den Median direkt berechnen: Wir haben eine solche Situation
Der Median ist also 4,5.
Angenommen, Sie wissen etwas über die Verteilung, können Sie die Definition der Bereiche zur Optimierung der Geschwindigkeit genau einstellen. In jedem Fall sollte die Leistung mit O (N) gehen, da 1 + 1/3 + 1/9 ... = 1,5
Sie benötigen aufgrund von Kantenfällen min und max (z. B. wenn der Median der Durchschnitt zwischen dem Maximum des alten Tiefs und dem nächsten Element ist).
Alle diese Vorgänge können parallelisiert werden. Sie können jedem Computer 1/100 der Daten geben und die 3 Buckets in jedem Knoten berechnen. Anschließend können Sie den Bucket verteilen, den Sie behalten. Dadurch können Sie das Netzwerk wieder effizient nutzen, da jede Nummer durchschnittlich 1,5-mal übergeben wird (also O (N)). Sie können das sogar übertreffen, wenn Sie nur die minimalen Zahlen zwischen den Knoten übergeben (z. B. wenn Knoten 1 100 Zahlen und Knoten 2 150 Zahlen hat, kann Knoten 2 Knoten 1 25 Zahlen geben).
Wenn Sie nicht mehr über die Verteilung wissen, bezweifle ich, dass Sie hier besser als O (N) abschneiden können, da Sie die Elemente tatsächlich mindestens einmal zählen müssen.
quelle
O(n log n)
in diesem Fall ein wäre. Macht das Sinn ? Übrigens mag ich Ihre Ideeo(n)+o(n/3)+o(n/9)+...
was noch isto(n)
und nichto(n log n)
.o(n)
in diesem Fall, mit der naiven Partitionierung.Eine einfachere Methode besteht darin, gewichtete Zahlen zu haben.
quelle
Teilen Sie die 10 ^ 9 Zahlen, 10 ^ 7, auf jeden Computer ~ 80 MB auf jedem. Jeder Computer sortiert seine Nummern. Dann sortiert Computer 1 seine eigenen Zahlen mit denen von Computer 2, Computer 3 und 4 usw. Dann schreibt Computer 1 die Hälfte der Zahlen zurück auf 2, 3 bis 4 usw. Dann sortiert 1 Zusammenführen die Zahlen von Computern 1,2,3,4, schreibt sie zurück. Und so weiter. Abhängig von der Größe des Arbeitsspeichers auf den Computern, bei denen Sie möglicherweise nicht bei jedem Schritt alle Zahlen auf die einzelnen Computer zurückschreiben, können Sie die Zahlen möglicherweise für mehrere Schritte auf Computer 1 akkumulieren, aber Sie rechnen nach.
Oh, endlich den Mittelwert der 500000000. und 500000001. Werte ermitteln (aber überprüfen Sie, ob dort genügend 00s vorhanden sind, habe ich nicht).
EDIT: @Roman - Nun, wenn Sie es nicht glauben können, obwohl es wahr ist, dann macht es keinen Sinn, die Wahrheit oder Falschheit des Satzes zu enthüllen. Was ich damit sagen wollte war, dass Brute Force in einem Rennen manchmal klug schlägt. Ich habe ungefähr 15 Sekunden gebraucht, um einen Algorithmus zu entwickeln, von dem ich überzeugt bin, dass ich ihn implementieren kann, der funktioniert und der an eine Vielzahl von Eingangsgrößen und Computerzahlen angepasst und an die Eigenschaften der Computer und Computer angepasst werden kann Netzwerkvereinbarungen. Wenn Sie oder jemand anderes 15 Minuten brauchen, um einen ausgefeilteren Algorithmus zu entwickeln, habe ich einen Vorteil von 14 Minuten und 45 Sekunden, um meine Lösung zu codieren und zu starten.
Aber ich gebe frei zu, dass dies alles eine Behauptung ist, ich habe nichts gemessen.
quelle
Dies kann auf Knoten erfolgen, die Daten verwenden, die nicht wie folgt nach Knoten sortiert sind (z. B. aus Protokolldateien).
Es gibt 1 übergeordneten Knoten und 99 untergeordnete Knoten. Die untergeordneten Knoten haben zwei API-Aufrufe:
Der übergeordnete Knoten ruft auf allen untergeordneten Knoten stats () auf und notiert das Minimum und Maximum aller Knoten.
Eine binäre Suche kann nun folgendermaßen durchgeführt werden:
Es gibt 1 übergeordneten Knoten und 99 untergeordnete Knoten. Die untergeordneten Knoten haben zwei API-Aufrufe:
Der übergeordnete Knoten ruft auf allen untergeordneten Knoten stats () auf und notiert das Minimum und Maximum aller Knoten.
Eine binäre Suche kann nun folgendermaßen durchgeführt werden:
Wenn die Werte () und compare () mit einer O (N / Mlogn / M) -Sortierung vorberechnet werden könnten, dann eine O (N / M) -Vorberechnung mit einer Speicherkomplexität von O (N) für die Vorberechnung Berechnung. Dann könnten Sie compare () in konstanter Zeit ausführen, sodass das Ganze (einschließlich Vorberechnung) in O (N / MlogN / M) + O (logN) ausgeführt wird.
Lassen Sie mich wissen, wenn ich einen Fehler gemacht habe!
quelle
Wie wäre es damit: - Jeder Knoten kann 1 Milliarde / 100 Zahlen annehmen. An jedem Knoten können die Elemente sortiert und der Median gefunden werden. Finden Sie den Median der Mediane. Wir können durch Aggregation der Anzahl von Zahlen, die kleiner als der Median des Medians auf allen Knoten sind, herausfinden, welche x%: y% Aufteilung der Median des Medians erfolgt. Bitten Sie nun alle Knoten, Elemente zu löschen, die kleiner als der Median der Mediane sind (Beispiel: 30%: 70% Aufteilung). 30% -Zahlen werden gelöscht. 70% von 1 Milliarde sind 700 Millionen. Jetzt können alle Knoten, die weniger als 3 Millionen Knoten gelöscht haben, diese zusätzlichen Knoten an einen Hauptcomputer zurücksenden. Der Hauptcomputer verteilt sich so um, dass jetzt alle Knoten fast die gleiche Anzahl von Knoten haben (7 Millionen). Jetzt, da das Problem auf 700 Millionen reduziert ist, geht es weiter, bis wir einen kleineren Satz haben, der auf einem Comp berechnet werden kann.
quelle
Lassen Sie uns zunächst herausfinden, wie Sie einen Median von n Zahlen auf einer einzelnen Maschine finden: Ich verwende im Grunde eine Partitionierungsstrategie.
Problem: Auswahl (n, n / 2): Finden Sie die n / 2-te Zahl aus der kleinsten Zahl.
Sie wählen beispielsweise das mittlere Element k und partitionieren die Daten in zwei Unterarrays. Die erste enthält alle Elemente <k und die zweite enthält alle Elemente> = k.
Wenn sizeof (1. Unterarray)> = n / 2 ist, wissen Sie, dass dieses Unterarray den Median enthält. Sie können dann das 2. Sub-Array abwerfen. Lösen Sie diese Problemauswahl (Größe des 1. Subarrays, n / 2) .
In diesem Fall werfen Sie dieses 1. Subarray ab und lösen die Auswahl (2. Subarray, n / 2 - Größe von (1. Subarray))
Mach es rekursiv.
Zeitkomplexität ist O (n) erwartete Zeit.
Wenn wir nun viele Maschinen haben, müssen wir in jeder Iteration ein Array zum Teilen verarbeiten und das Array in verschiedene Maschinen verteilen. Jede Maschine verarbeitet ihren Array- Block und sendet die Zusammenfassung an die Hub-Steuerungsmaschine zurück, dh die Größe des 1. Subarrays und die Größe des 2. Subarrays. Die Hub-Maschinen addieren Zusammenfassungen und entscheiden, welches Subarray (1. oder 2.) weiter verarbeitet werden soll und 2. Parameter der Auswahl und senden es an jede Maschine zurück. und so weiter.
Dieser Algorithmus kann sehr sauber mit Map Reduce implementiert werden?
Wie sieht es aus?
quelle
Ich denke, Steve Jessops Antwort wird die schnellste sein.
Wenn die Größe der Netzwerkdatenübertragung der Engpass ist, gibt es hier einen anderen Ansatz.
quelle
Ich würde es so machen:
Am Anfang arbeiten alle 100 daran, die höchste und die niedrigste Zahl zu finden. Jeder Computer hat seinen Teil der Datenbank / Datei, die er abfragt.
Wenn die höchsten und niedrigsten Zahlen gefunden werden, liest ein Computer die Daten und verteilt jede Zahl gleichmäßig an den Rest der 99; die Zahlen werden in gleichen Intervallen verteilt; (einer kann von -100 Millionen bis 0 nehmen, ein anderer - von 0 bis 100 Millionen usw.);
Während des Empfangs von Nummern sortiert jeder der 99 Computer diese bereits.
Dann ist es einfach, den Median zu finden ... Sehen Sie, wie viele Zahlen jeder Computer hat, addieren Sie alle (die Summe der Anzahl der Zahlen, nicht die Zahlen selbst), dividieren Sie durch 2; Berechnen Sie, auf welchem Computer die Nummer und an welchem Index angegeben ist.
:) voilla
PS Es scheint, dass hier viel Verwirrung herrscht. der MEDIAN - ist die ZAHL IN DER MITTE EINER SORTIERTEN LISTE VON ZAHLEN!
quelle
Sie können die Turnierbaummethode verwenden, um den Median zu ermitteln. Wir können einen Baum mit 1000 Urlaubsknoten erstellen, sodass jeder Blattknoten ein Array ist. Wir führen dann n / 2 Turniere zwischen den verschiedenen Arrays durch. Der Wert auf der Wurzel nach den n / 2 Turnieren ist das Ergebnis.
http://www.geeksforgeeks.org/tournament-tree-and-binary-heap/
quelle
Wenn die Zahlen nicht eindeutig sind und nur zu einem bestimmten Bereich gehören, dh wiederholt werden, besteht eine einfache Lösung darin, die Zahlen gleichmäßig auf 99 Maschinen zu verteilen und eine Maschine als Master zu behalten. Jetzt iteriert jede Maschine über die angegebenen Zahlen und speichert die Anzahl jeder Zahl in einem Hash-Satz. Jedes Mal, wenn die Nummer in dem diesem bestimmten Computer zugewiesenen Nummernsatz wiederholt wird, wird die Anzahl im Hash-Satz aktualisiert.
Alle Maschinen geben dann ihren Hash-Satz an die Master-Maschine zurück. Die Master-Maschine kombiniert die Hash-Sätze und summiert die Anzahl des gleichen Schlüssels, der in einem Hash-Satz gefunden wurde. Zum Beispiel hatte der Hash-Satz von Maschine Nr. 1 einen Eintrag von ("1", 7), und der Hash-Satz von Maschine Nr. 2 hatte einen Eintrag von ("1", 9), so dass der Master-Computer beim Kämmen der Hash-Sätze einen Eintrag von macht ("1", 16) und so weiter.
Sobald die Hash-Sets zusammengeführt wurden, sortieren Sie einfach die Schlüssel. Jetzt können Sie das (n / 2) -te Element und das (n + 2/2) -te Element leicht aus dem sortierten Hash-Set finden.
Diese Methode ist nicht vorteilhaft, wenn die Milliardenzahlen unterschiedlich sind.
quelle
Angenommen, Sie wissen, dass die Anzahl der unterschiedlichen Ganzzahlen (sagen wir) 4 Milliarden beträgt. Dann können Sie sie in 64.000 Buckets zusammenfassen und eine verteilte Anzahl für jeden Bucket von jedem Computer im Cluster (100 Computer) erhalten. Kombinieren Sie all diese Zählungen. Suchen Sie nun den Bucket mit dem Median und fragen Sie diesmal nur nach Buckets für die 64k-Elemente, die in Ihrem Ziel-Bucket liegen würden. Dies erfordert O (1) (speziell 2) Abfragen über Ihren "Cluster". : D.
quelle
Mein Penny wert, nach all dem, was schon von anderen angesprochen wurde:
Das Ermitteln des Medians auf einem einzelnen Computer lautet O (N): https://en.wikipedia.org/wiki/Selection_algorithm .
Das Senden von N Nummern an 100 Maschinen ist ebenfalls O (N). Um die Verwendung von 100 Maschinen interessant zu machen, muss entweder die Kommunikation relativ schnell sein oder N ist so groß, dass eine einzelne Maschine nicht damit umgehen kann, solange N / 100 machbar ist, oder wir möchten nur das mathematische Problem betrachten, ohne uns darum zu kümmern Datenkommunikation.
Um es kurz zu machen, gehe ich daher davon aus, dass wir die Zahlen innerhalb angemessener Grenzen senden / verteilen können, ohne die Effizienzanalyse zu beeinflussen.
Betrachten Sie dann den folgenden Ansatz, bei dem eine Maschine als "Master" für eine allgemeine Verarbeitung zugewiesen wird. Dies ist vergleichsweise schnell, sodass der "Master" auch an den allgemeinen Aufgaben teilnimmt, die jede Maschine ausführt.
Zeitkomplexität:
quelle
Teilen Sie die 1 Milliarde Zahlen in 100 Maschinen. Jede Maschine hat 10 ^ 7 Nummern.
Speichern Sie für jede an eine Maschine eingehende Nummer die Nummer in einer Frequenzkarte, Nummer -> Anzahl. Speichern Sie auch die Mindestanzahl in jeder Maschine.
Finden Sie den Median in jeder Maschine: Summieren Sie ausgehend von der Mindestanzahl in jeder Maschine die Anzahl, bis der Medianindex erreicht ist. Der Median in jeder Maschine ist der ca. kleiner und größer als 5 * 10 ^ 6 Zahlen.
Finden Sie den Median aller Mediane, der kleiner und größer als ca. 50 * 10 ^ 7 Zahlen, das ist der Median von 1 Milliarde Zahlen.
Nun einige Optimierung des 2. Schritts: Anstatt in einer Frequenzkarte zu speichern, speichern Sie die Zählwerte in einem Array mit variablen Bits. Zum Beispiel: Nehmen wir an, ab einer Mindestanzahl in einer Maschine sind dies Frequenzzählungen:
Das Obige kann in einem Bit-Array gespeichert werden als:
Beachten Sie, dass es insgesamt ungefähr 10 ^ 7 Bits für jede Maschine kostet, da jede Maschine nur 10 ^ 7 Zahlen verarbeitet. 10 ^ 7 Bits = 1,25 * 10 ^ 6 Bytes, was 1,25 MB entspricht
Mit dem obigen Ansatz benötigt jede Maschine 1,25 MB Speicherplatz, um den lokalen Median zu berechnen. Der Median der Mediane kann aus diesen 100 lokalen Medianen berechnet werden, was zu einem Median von 1 Milliarde Zahlen führt.
quelle
Ich schlage eine Methode zur Berechnung des Medians vor. :) Wenn diese eine Milliarde Zahlen in zufälliger Reihenfolge vorliegen, kann ich 1/100 oder 1/10 einer Milliarde zufällig auswählen, sie mit 100 Maschinen sortieren und dann den Median auswählen. Oder lassen Sie uns Milliardenzahlen in 100 Teile aufteilen, jede Maschine 1/10 jedes Teils zufällig auswählen und den Median davon berechnen. Danach haben wir 100 Zahlen und können den Median der 100 Zahlen einfacher berechnen. Nur ein Vorschlag, ich bin mir nicht sicher, ob es mathematisch korrekt ist. Aber ich denke, Sie können das Ergebnis einem nicht so guten Mathe-Manager zeigen.
quelle
Steve Jessops Antwort ist falsch:
Betrachten Sie die folgenden vier Gruppen:
{2, 4, 6, 8, 10}
{21, 21, 24, 26, 28}
{12, 14, 30, 32, 34}
{16, 18, 36, 38, 40}
Der Median ist 21, der in der zweiten Gruppe enthalten ist.
Der Median der vier Gruppen beträgt 6, 24, 30, 36, der Gesamtmedian beträgt 27.
Nach der ersten Schleife werden die vier Gruppen zu:
{6, 8, 10}
{24, 26, 28}
{12, 14, 30}
{16, 18, 36}
Die 21 wird bereits fälschlicherweise verworfen.
Dieser Algorithmus unterstützt den Fall nur, wenn zwei Gruppen vorhanden sind.
quelle