Frage

‚Simple‘ Frage, was ist der schnellste Weg, um den Binomialkoeffizienten zu berechnen? - Einige Gewinde Algorithmus

Ich bin auf der Suche nach Hinweisen :) - nicht Implementierungen:)

War es hilfreich?

Lösung

Nach der Gleichung unten (von wikipedia ) dem schnellsten Weg spalten würde die reich i 1, k für die Anzahl der Threads = gibt jedes Thread ein Bereichssegment und jeden Thread aktualisiert das Endergebnis in einem Schloss. „Academic Weg“ wäre, den Bereich in Aufgaben aufgeteilt, jede Aufgabe zu berechnen ist (n - k + i) / i, und dann, egal wie viele Threads Sie haben, sie alle laufen in einer Schleife für die nächste Aufgabe zu stellen. Erstens ist schneller, zweitens ist ... akademisch.

alt text

EDIT: eine weitere Erklärung - in beide Richtungen wir eine beliebige Anzahl von Threads. Normalerweise ist die Anzahl der Threads ist gleich der Anzahl der Prozessorkerne, weil es keinen Nutzen mehr Fäden in hinzufügen. Der Unterschied zwischen zwei Möglichkeiten, was die Fäden tun.

Im ersten Weg jeder Thread gegeben N, K, I1 und I2, wobei I1 und I2 das Segment im Bereich 1..K ist. Jeder Thread hat dann alle Daten, es NEADS, so dass er seinen Teil des Ergebnisses berechnet und auf Finish aktualisiert das Endergebnis.

In zweite Weg ist jeder Thread gegeben N, K, und der Zugang zu gewissen syncronized Zähler, der zählt von 1 bis K. Jeder Thread dann einen Wert aus diesem gemeinsam geteilten Zähler erwirbt, einen Bruchteil des Ergebnisses berechnet, aktualisiert das Endergebnis, und Schleifen auf diese, bis der Zähler informiert der Faden, dass es keine weitere Artikel. Wenn es passiert, dass einige Prozessorkerne schneller sind, dass andere dann diese zweite Möglichkeit, alle Kerne auf maximal genutzt werden. Nachteil zweite Weg ist, zu viel Synchronisation dass effektiv blockiert, sagen wir, 20% der Fäden die ganze Zeit.

Andere Tipps

Nun ist der schnellste Weg, ich rechne, wäre sie aus einer Tabelle zu lesen, anstatt sie berechnen.

Ihre Anforderungen an integer Genauigkeit von einer doppelten Darstellung Mitteln, dass C (60,30) ist alles andere als zu groß, um sein 1E17, so dass (vorausgesetzt, Sie wollen C (m haben, n) für alle m bis zu einige Grenze, und alle n <= m), würde Ihre Tabelle nur um 1800 Einträge. Wie für das Ausfüllen der Tabelle denke ich Pascals Dreieck ist der Weg zu gehen.

Hinweis: Sie wollen so wenig Multiplikationen wie möglich zu tun. Die Formel ist n! / (k! * (n-k)!). Sie sollten weniger als 2m Multiplikationen tun, wo m das Minimum von k und n-k ist. Wenn Sie mit (ziemlich) großen Zahlen arbeiten möchten, sollten Sie eine Sonderklasse für die Zahlendarstellung verwenden (Java hat BigInteger zum Beispiel).

Hier ist eine Art und Weise, die nie überläuft, wenn das Endergebnis ausdrückbar ist nativ in der Maschine, beinhaltet keine Multiplikationen / Faktorisierungen ist leicht parallelisieren und verallgemeinert zu BigInteger-Typen:

Zunächst ist zu beachten, dass die Binomialkoeffizienten erfüllen folgende:

.

Dies ergibt eine einfache Rekursion zur Berechnung des Koeffizienten: die Basis Fälle “ und , beide sind 1.

Die einzelnen Ergebnisse aus den Unteraufrufen ganze Zahlen sind und wenn \ binom {n} {k} durch einen int dargestellt werden, können sie auch; so, Überlauf ist kein Problem.

Naiv implementiert, die Rekursion führt zu wiederholten und Unteraufrufe exponentielle Laufzeiten.

Dies kann durch Caching Zwischenergebnisse festgelegt werden. Es gibt n ^ 2 Subprobleme, die in O (1) Zeit, kombiniert werden können, wodurch man eine O (n ^ 2) Komplexität gebunden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top