Wie schnell können Sie lineare Suche?
Ich bin auf der Suche um dies zu optimieren, lineare Suche:
static int
linear (const int *arr, int n, int key)
{
int i = 0;
while (i < n) {
if (arr [i] >= key)
break;
++i;
}
return i;
}
Das array sortiert ist und die Funktion zurückgeben sollte, wird der index des ersten Elements größer oder gleich dem Schlüssel. Sie-array ist nicht groß (unter 200 Elemente) und wird bereit sein, einmal für eine große Anzahl von Suchanfragen. Array-Elemente nach dem n-TEN kann bei Bedarf initialisiert werden, um etwas passendes, wenn das beschleunigt die Suche.
Keine, binäre Suche ist nicht erlaubt, nur lineare Suche.
Bearbeiten: All mein wissen über dieses Thema ist jetzt zusammengefasst in diesem blog-post.
- Wo ist die Frage?
- Die einzige Sache, die Sie tun können, ist, profitieren Sie von allen SIMD-Befehle zur Verfügung, die auf Ihre Plattform. (Test vier gleichzeitig, zum Beispiel.) Obwohl, warum würden Sie nicht die binäre Suche, weiß ich nicht.
- Sie nicht haben, um zu testen, jedes element; Sie können testen, alle kth-element, wenn Sie sind dann erlaubt, wieder zu gehen. Auch, wenn Sie wissen, die Anzahl der Elemente, die Sie können ein array / hash-Tabelle, die nur gibt Ihnen die Antwort. Aber, könnte man nicht überlegen, diese "lineare Suche".
- Warum ist die binäre Suche (willkürlich?) nicht erlaubt ist? Ist das ein echtes problem oder irgendeine Art von Hausaufgaben? Denn wenn du gehst, zu gehen durch die Mühe der Sortierung der Daten, wird eine binäre Suche ist dein bester Darsteller.
- (Random thought: eins, zwei, überspringen Sie ein paar-aber das könnte fallen in 'nicht-linear', und wenn es schon sortiert, da jede nicht-triviale n ohne das match zu erwarten in der Nähe der front und der zugehörigen Lokalität Fragen ...)
- Das ist im Grunde eine binäre Suche, wobei "ein paar" ist die "verbleibenden array-Größe / 2".
- Binäre searsh wird am besten ausgeführt werden, nur wenn Sie wissen, dass das element, das Sie suchen, befindet sich in einem komplett unvorhersehbaren position. Wenn Sie wissen, dass die target-element ist wahrscheinlich in der Nähe der Anfang des Arrays, lineare Suche besser abschneiden werden als die binäre Suche. Klassisches Beispiel ist der bekannte Algorithmus für das Zusammenführen von zwei sortierten arrays. Wenn die arrays haben in etwa die gleiche Länge, die Verschmelzung erfolgt mit linearen Suche, da binäre wird viel langsamer.
- Denken Sie daran binäre Suche erfordert Ihre eingestellten Daten sortiert werden.
- tatsächlich, ich habe irgendwo gelesen, dass für kleine Arrays, lineare Suche schneller sein können: lwn.net/Articles/255364 - (Diskussion in den Kommentaren)
- Wäre es als Cheaten angesehen, wenn Sie gescannt werden (jedes zehnte element erste und nach dem finden der ersten nicht weniger als der Schlüssel, gehen Sie zurück und Scannen letzten zehn element eins nach dem anderen? Wie wäre es mit einer Quadratwurzel von n anstelle von 10?
- Das ist toll für bestimmte Fälle, aber es gibt nichts zu zeigen, dass es etwas besonderes über diesen Datensatz. Im generischen Fall, ein sortiert, aber sonst Fußgänger Satz von Daten wird am besten funktionieren in den meisten Anwendungsfällen mit einer binären Suche.
- Ja, nicht das Scannen jedes element wäre Cheaten. @GMan: Es gibt eine MENGE Sie tun können, bevor Rückgriff auf SIMD. @Joe: Das ist der "Hausaufgaben", die ich gegeben habe, mich, den hab ich auch schon gemacht. Ich bin nur neugierig, was die Leute kommen mit, die ich noch nicht gedacht.
- Alles, was Sie tun, im Grunde genommen ein umsponnen binäre Suche.
- Finden Sie die top-bewerteten Antwort, zum Beispiel. Viel schneller als die einfache lineare Suche (ich weiß, ich habe gemessen).
- Ich bin überrascht, dass. Was würde das abrollen vier machen?
- Abrollen von vier Geschwindigkeiten um fast 50% bei N=100 auf einem Core i7. Abrollen, indem vier mit einer sentinel-Geschwindigkeiten von bis von mehr als 50%.
- Noch keine Lösungen, die mehrere threads verwenden?
- Probst: Ja abrollen können die Sache beschleunigen, ich glaube ich muss wieder Lesen mein Code Complete Buch 🙂 Hier ist das abrollen Thema aus diesem Buch stevemcconnell.com/cctune.htm
- Ja, aber sehen Sie das problem: Sie haben zu implementieren lineare Suche in einem sortierten array. Dies ist bereits ausreichend nicht-generische. Diese bereits schon etwas besonderes. Warum würde jemand darauf bestehen, eine lineare Suche in einem sortierten array? Vielleicht tun Sie es, weil die Struktur der Abfragen bevorzugt lineare Suche speziell? Zum Beispiel, wenn Sie eine geordnete Reihe von N Elemente haben, um in der Nähe N bestellt, Suche, Abfragen, inkrementelle lineare Suche besser abschneiden werden als binäre Suche um ein Vielfaches, mindestens.
- Probst: Sie erarbeiten mit Optimierungen aktiviert, richtig?
- binäre Suche mit einigen a-priory Kenntnis der Verteilung werden die Daten noch schneller als die lineare Suche in den meisten Fällen; die einfachste ist die Verwendung der Abstände zu Linear interpoliert den splitting-Punkt für die nächste iteration statt in die Mitte der Reihe (das funktioniert am besten, wenn die Daten gleichmäßig verteilt, in anderen Fällen ist die interpolation Formel sollte ähnlich der Verteilung)
- Wenn jemand Bestand auf der Verwendung einer linearen Suche auf sortierten Daten, ich möchte einfach nur wieder ein zufälliges Ergebnis, weil jemand so dumm wäre das nicht wissen, den Unterschied.
- Nun, wenn Sie haben, um M sortiert Abfragen in ein array der N Elemente sortiert, die asymptotisch optimale algoirithm verläuft wie folgt: zunächst führen wir gegrätschten lineare Suche mit Schritt [N/M], d.h. lineare Suche überspringen, um jedes [N/M]-te element und führen Sie dann die binäre Suche in den gefundenen segment der Länge [N/M]. Wenn M in der Nähe N, [N/M] wird zu klein und die binäre Suche wird "deaktiviert". Also, keine binarey Suche, unter den oben genannten Bedingungen (d.h. ausreichend Dichte sortiert Abfragen der gleichen Daten) nicht schneller als eine lineare Suche. Lineare Suche sehr viel schneller.
- Die obige Mischung aus gegrätschten-linear-Suche gefolgt von der binären Suche ist erwiesen, um asymptotisch optimalen Algorithmus erreicht das theoretische limit der Suche nach Effizienz. Also, keine binäre Suche ist nur schneller, wenn die Abfragen sind spärlich. Mit der dichten Abfragen, lineare Suche, gewinnt durch eine riesige Marge. Und, wieder, für die zwischen-Fällen, die der optimale Algorithmus verwendet die Mischung der beiden. Das theoretische Ergebnis ist von diesem Artikel: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.22.5750
- Die würde wahrscheinlich machen es viel mehr überraschend für Sie, um herauszufinden, dass inkrementelle lineare Suche auf sortierten Daten absolut Sinn macht, wenn wir haben, um mehrere sortiert Abfragen. Wenn die Anzahl der Abfragen Ansätze die Größe der Daten, lineare Suche als die binäre Suche um ein Vielfaches. Darüber hinaus werden aus diesem Grund praktisch jeder kann es benutzen (d.h. lineare Suche) beim mischen von sortierten Daten. Sie einfach nicht erkennen, dass.
- dies ist nicht eine
[code-golf]
problem. Wenn es Links tagged wie, dass es geschlossen werden würde, weil die code-golf-Probleme, die nicht CW bekommen ständig geschlossen - Zusammenführen der sortierten Daten dauert lineare Zeit, aber es ist nicht eine lineare Suche. Sie sind richtig, über die Suche nach mehreren Werten auf einmal, aber das war nicht Teil der OP die Problematik.
- Ja, es ist die lineare Suche 🙂 Die klassische merging-Algorithmus für sortierte arrays basiert auf der aktuellen minimales element aus dem array und sendet es zur Ausgabe. Es ist nicht offensichtlich, aber dies ist in der Tat nichts anderes als eine einfache lineare Suche eines elements von einem array in ein anderes array. Es ist einfach verschleiert ein wenig, so dass Sie nicht sehen es sofort, aber es Wirklichkeit ist es schlicht und unkompliziert lineare Suche.
- Darüber hinaus ist die gleiche Logik gilt auch für die Zusammenführung so gut: wenn Sie das Zusammenführen von zwei arrays von deutlich unterschiedlicher Länge, es ist besser zu wechseln, um binäre Suche für die Zusammenführung aus. Aber wenn die Länge etwa gleich sind, nutzen wir die klassischen Algorithmus mit linearer Suche.
- Ich bin nicht einverstanden, da die Listen sortiert sind, haben Sie die Zeiger auf die kleinste (oder größte) element im einzelnen, so sind Sie nie auf der Suche für das nächste element von einer der Teillisten, Sie sind nur zu entscheiden, welche Teilliste zu nehmen, das element aus.
- Nein, Sie sind einfach das beharren auf eine bestimmte vision von dem, was passiert. Hier ist die althernative vision für Sie: zum ausführen der merge-wir nehmen das erste element
a
aus sortierten arrayA
und führen Sie die lineare Suche nach element im sortierten arrayB
. Das gibt uns eine [eventuell leer] Reihenfolge der führenden Elemente inB
, die kleiner sind alsa
. Wir bewegen uns, die gesamte Sequenz zu Ausgabe, gefolgt vona
. Dann wiederholen wir: nehmen Sie das nächste elementa
ausA
... und so weiter. Das ist es. - Auf den ersten Blick klingt es vielleicht wie einen anderen Algorithmus, während, wenn Sie ein wenig darüber nachdenken, werden Sie sehen, dass dies genau der selben Klassiker-merging-Algorithmus, beschrieben nur in unterschiedliche Begriffe 🙂 Wieder, die klassische merging-Algorithmus ist nichts anderes als eine leicht verschleierte lineare Suche. Und wieder, wenn die arrays haben unterschiedliche Länge, die richtige Art und Weise zu tun, die Verschmelzung ist die Verwendung von binärer Suche: nehmen
a
ausA
, binäre Suche inB
verschieben Sie den Anfang der Sequenz vonB
Ausgabe, bewegena
Ausgabe, wiederholen. - Und wieder, der universal-asymptotisch optimale Strategie ist eine Mischung aus linearer und binärer Suche, wie beschrieben in meiner Antwort weiter unten.
- Ich werde die Abstimmung zu schließen, ist diese Frage off-topic, weil es besser passt auf Code Überprüfen.
- dies ist keine Frage für ein code-review der einfache Skalare lineare Suche, es ist mit das zu beschreiben/zeigen, dass der Algorithmus vektorisiert werden. Und außerdem, es ist zu alt, zu migrieren und die vorhandenen Antworten, also wenn das erste argument nicht überzeugen, dann würde ich noch vorschlagen, machen eine Ausnahme von der Regel für diese historische Frage.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gut, es macht ungefähr so viel Sinn wie eine lineare Suche durch ein sortiertes array!
(Mehr ernsthaft, können Sie uns ein paar Hinweise, warum keine binäre Suche?)
So weit Sie erhielt mehrere Ratschläge, die meisten, die behaupten, dass die lineare Suche keinen Sinn macht, auf sortierten Daten, wenn binäre Suche wesentlich effizienter arbeiten statt. Dies geschieht oft zu einer der beliebtesten "richtig klingt" Aussagen von Leuten, die keine Pflege zu geben, das problem zu viel zu denken. In der Realität, wenn man bedenkt, das größere Bild, gegeben der richtigen Umstände, lineare Suche kann sehr viel effizienter als die binäre Suche.
Beachten Sie, dass, wenn wir betrachten ein single Suchanfrage für ein sortiertes array binäre Suche ist deutlich effizientere Methode als die lineare Suche. Es gibt keinen Streit darüber. Auch, wenn Sie führen Sie mehrere komplett random Abfragen der gleichen Daten binären Suche noch gewinnt gegenüber der linearen Suche.
Jedoch beginnt das Bild zu ändern, wenn wir betrachten die sequentielle Suche Abfragen und diese Abfragen sind nicht ganz zufällig. Vorstellen, dass Anfragen eintreffen, in der Reihenfolge sortiert, d.h. der jeweils nächste Abfrage ist für einen höheren Wert als die Vorherige Abfrage. I. e. die Abfragen sind auch sortiert. BTW, Sie haben nicht Global und streng sortiert, von Zeit zu Zeit der Abfrage-Sequenz könnte "zurücksetzen", d.h. einen niedrigen Wert abgefragt wird, aber im Durchschnitt ist die konsequente Abfragen sollte dann in aufsteigender Reihenfolge. In anderen Worten, die Abfragen kommen in Serie, jede Serie in aufsteigender Reihenfolge sortiert. In diesem Fall, wenn die Durchschnittliche Länge der Serie ist vergleichbar mit der Länge der Arrays, lineare Suche übertreffen binäre Suche durch eine riesige Marge. Jedoch, um die Vorteile dieser situation, müssen Sie implementieren Ihre Suche im inkrementelle Art und Weise. Es ist einfach: wenn die nächste Abfrage ist größer als die Vorherige, die Sie nicht brauchen, um die Suche zu starten von Anfang an der Reihe. Stattdessen können Sie die Suche von der Stelle, wo die Vorherige Suche gestoppt. Die meisten vereinfachten Umsetzung (nur um den Gedanken zu verdeutlichen) könnte wie folgt Aussehen
(Disclaimer: die oben genannten Umsetzung ist furchtbar hässlich für die offensichtliche Grund, dass das array eintrifft, von außen als parameter, während die Vorherige Suche Zustand ist intern gespeichert. Natürlich, dies ist der falsche Weg, es zu tun in der Praxis. Aber noch einmal, die oben sollen verdeutlichen die Idee und nicht mehr).
Beachten, dass die Komplexität der Verarbeitung jeder Reihe bestellt-Abfragen mit dem obigen Ansatz ist immer
O(N)
unabhängig von der Länge der Serie. Mithilfe der binären Suche, die Komplexität wäreO(M * log N)
. So, aus offensichtlichen Gründen, wennM
ist in der NäheN
, d.h. Abfragen kommen in ausreichend langen Serie bestellt, die über die lineare Suche wird deutlich stärker als binäre Suche, während für kleineM
die binäre Suche wird gewinnen.Auch dann, wenn der geordnete Reihe von Abfragen sind nicht sehr lang, die oben genannten änderungen könnte es noch geben Sie eine spürbare Verbesserung auf der Suche nach Leistung, wenn man bedenkt, dass Sie haben lineare Suche.
P. S. Als zusätzliche information über die Struktur des Problems:
Wenn Sie brauchen, um die Suche in einem geordneten array der Länge
N
und Sie wissen im Voraus, dass die Abfragen kommen in geordnete Reihe von [Ungefähre, Durchschnittliche] LängeM
, der optimale Algorithmus wird wie folgt AussehenS = [N/M]
. Es könnte auch Sinn machen, um "snap" den WertS
auf die [nächste] Potenz von 2 ist. Denken Sie an Ihre sortierten array als eine Sequenz von Blöcken der LängeS
- so genannte S-Blöcke.S
(natürlich, denken Sie daran, start aus dem block, wo die Vorherige Suche Links aus).Oben ist die optimale inkrementelle Suche-Algorithmus möglich, in einem Sinn, der es erreicht die theoretische Grenze für die asymptotische Effizienz wiederholte Suche. Beachten Sie, dass wenn der Wert von
M
ist viel kleiner dannN
der Algorithmus "automatisch" verschiebt sich in Richtung binäre Suche, während, wennM
nahe kommtN
den Algorithmus "automatisch" begünstigt lineare suchen. Letzteres macht Sinn, da in solcher Umgebung die lineare Suche ist wesentlich effizienter als die binäre Suche.All dies ist nur zur Veranschaulichung der Tatsache, dass die Decke Aussagen wie "lineare Suche auf einem sortierten array ist immer sinnlos" zeigen, nichts anderes als Mangel an wissen auf Seiten derer, die solche Aussagen machen.
Da können Sie stellen Sie den bekannten Werten nach dem letzten gültigen Eintrag, fügen Sie ein zusätzliches element n+1 = max, um sicherzustellen, dass die Schleife geht nicht über das Ende des Arrays, ohne zu testen, für i < n.
Könnte man auch versuchen abrollen der Schleife, mit dem gleichen sentinel-Wert:
i
bei-1
und dann pre-Inkrement in die array-Indizierung in Ihrer ent-Schleife Beispiel. Das erspart Ihnen das zusätzliche--i
am Ende.Zunächst keine schnelle Lösung verwenden müssen, Vektorisierung zu vergleichen, die viele Elemente auf einmal.
Jedoch alle die vektorisierte Implementierungen geschrieben, so weit leiden unter einem gemeinsamen problem: Sie haben Niederlassungen. Als Ergebnis, werden Sie haben, um einzuführen blockwise Verarbeitung von array (overhead reduziert der Verzweigung), die führt zu low-performance für kleine arrays. Für große arrays-linear-Suche ist schlimmer, als eine gut optimierte binäre Suche, so gibt es keinen Punkt in der Optimierung von it.
Jedoch lineare Suche realisiert werden können, ohne Zweige. Die Idee ist sehr einfach: der index, den Sie wollen, ist genau die Anzahl der array-Elemente, die kleiner sind als der Schlüssel, den Sie suchen. Damit Sie vergleichen können jedes element des Arrays mit dem key-Wert und die Summe aller flags:
Einen Spaß an dieser Lösung ist, dass würde es wieder die gleiche Antwort, auch wenn Sie die shuffle-array =) Obwohl diese Lösung scheint zu sein, eher langsam, kann es sein, vektorisiert aus. Die Umsetzung, sofern unten erfordert array auf 16 byte ausgerichtet. Auch, das array muss aufgefüllt werden mit INT_MAX Elemente, weil es verbraucht 16 Elemente auf einmal.
Die endgültige Reduktion einer einzelnen SSE2-register implementiert werden können, mit SSE2 nur wenn nötig, es sollte nicht wirklich Einfluss auf die Gesamtleistung.
Habe ich es getestet mit Visual C++ 2013 x64-compiler auf Intel Core2 Duo E4700 (ziemlich alt, ja). Der array der Größe 197 generiert wird, mit Elementen versehen, die von rand(). Den vollständigen code, mit all den Tests ist hier. Hier ist die Zeit zum ausführen 32M Suche:
Den OP ' s original-code Prozesse 10.6 Millionen-array pro Sekunde (2,1 Milliarden Elemente pro Sekunde). Die vorgeschlagene code-Prozesse 29.5 Millionen von arrays pro Sekunde (5,8 Milliarden Elemente pro Sekunde).
Auch der vorgeschlagene code funktioniert gut für kleinere arrays: auch für arrays von 15 Elementen, ist es immer noch fast drei mal schneller als die OP ' s original-code.
Hier ist die generierte assembly:
Schließlich möchte ich zu beachten, dass eine gut optimierte binäre Suche kann schneller gemacht werden, durch die Umstellung auf die beschrieben vektorisiert lineare Suche, sobald das Intervall wird kleiner.
UPDATE: Weitere Informationen finden Sie in mein blog-post auf die Sache.
Falls ein target-spezifische Lösung ist akzeptabel, dann können Sie ganz einfach nutzen SIMD (SSE, AltiVec, oder was auch immer Sie zur Verfügung haben) zu bekommen ~ 4x speed-up durch Tests 4 Elemente zu einer Zeit, anstatt nur 1.
Aus Interesse ich habe einen einfachen SIMD-Implementierung wie folgt:
Auf 2,67 GHz Core i7 mit OpenSUSE x86-64 und gcc 4.3.2, erhalte ich rund
7x - 8x
Verbesserung um einen Recht breiten "sweet spot", wo n = 100000 mit dem Schlüssel, gefunden in der Mitte des Arrays (d.h. Ergebnis = n /2). Die Leistung fällt ab rund3.5x
wenn n wird groß und das array daher übersteigt cache-Größe (vermutlich immer Speicherbandbreite-in diesem Falle beschränkt). Die Leistung fällt auch ab, wenn n klein ist, aufgrund der Ineffizienz der SIMD-Implementierung (es wurde optimiert für große n natürlich).8x
schneller als Skalare code, am besten mit array-Größen von der Ordnung 100000 und der Wert des Schlüssels gefunden auf halbem Weg durch die Reihe. Es fällt auf rund3.5x
für sehr große arrays.gcc -O3
und es ist ein x86-64 ausführbare Datei (doppelt so viele SSE-Register als x86). Wenn ich Zeit mache ich es in einer Schleife (100 Iterationen) und unter dem minimalen Zeit - dies bedeutet, dass für alle, aber die erste iteration die caches, die grundiert werden. Wenn Sie nur das timing eine iteration dann Ihre Messungen verzerrt sein. Und ja natürlich, die Leistung wird schlechter für kleine arrays - das ist rechnen, da die routine wertet blocks des Arrays, anstatt einzelne Elemente oder Vektoren.Haben Sie erhalten viele Anregungen für Verbesserungen, aber Sie brauchen, um zu Messen, jede Optimierung zu sehen, welche ist am besten gegeben, Ihre hardware-und compiler -.
Als ein Beispiel, in der ersten version dieser Antwort, ich vermutete, dass von 100-200 array-Elemente, die etwas höhere Aufwand der binären Suche sollte einfach bezahlt werden von weitaus weniger Sonden in dem array. Jedoch, unten in den Kommentaren, Mark Probst berichtet, dass er sieht, lineare Suche vor bis zu 500 Einträge auf seiner hardware. Dies verstärkt die Notwendigkeit, zu Messen bei der Suche nach der besten Leistung.
Hinweis: Bearbeitet folgende Daneben auch die Kommentare unten auf seine Messungen von linearen versus binäre Suche für relativ kleine N.
Du kannst es in parallel.
Wenn die Liste klein ist, ist es vielleicht nicht Wert sind, teilen Sie die Suche, aber wenn, müssen Prozess viele sucht, dann kann man definitiv laufen Sie parallel. Das wäre nicht verringern die Latenz der Operationen, sondern verbessern den Durchsatz.
Wenn Sie auf einer Intel-Plattform:
aber das findet nur genaue übereinstimmungen, nicht größer als oder gleich entspricht.
In C können Sie auch Duff ' s Device:
repne scasd
hat erhebliche startup-overhead, und nicht einmal alle, die schnell im Vergleich zu SIMD. (rep stos
undrep movs
sind gut (vor allem für die großen Blöcke zu amortisieren sich die startup-overhead), und intern betreiben in 16-byte-oder 32-byte-Blöcken, aber AFAIK die bedingte rep-string-Anweisungen (scas und cmps) sind nicht viel mehr als ein Skalar-Schleife implementiert, die in microcode.) Siehe Agner Fog ist insn Tabellen und Optimierung von Montage-Anleitung, und auch andere links in die x86-wiki-tag, wie die Intel-Optimierung Handbuch.repne scasd
macht nicht Schnelle Streicher-Unterstützung auf alle vorhandenen CPUs. Es funktioniert am besten 1 DWORD vergleichen pro Uhr nach dem Start, noch auf den letzten Skylake / Ryzen CPUs. Im Jahr 2010, als diese Antwort gepostet wurde, Nehalem aktuell war und tun konnte, ein 16-byte-SIMD-Last pro Uhr. Intel seit Haswell und AMD seit Zen2, kann 2x 32-byte-loads pro Takt, zusammen mit der SIMD-ALU-Arbeit zu vergleichen und zu überprüfen für den Schlüssel. (Oder stgatilov die astfreie version gerade gilt es zu finden, wo der Schlüssel war). Gehen zu müssen, downvote: es ist nicht optimal für irgendetwas, außer vielleicht, code-Größe.Wenn Sie hatte einen Quanten-computer, den Sie verwenden konnten, Grover ' s Algorithmus um Ihre Daten zu durchsuchen, die in O(N1/2) Zeit und mit O(log N) Speicherplatz. Ansonsten, deine Frage ist ziemlich albern. Binäre Suche (binary) oder einer seiner Varianten (trinary search, zum Beispiel) ist wirklich die beste Wahl. Tut Mikro-Optimierungen der linearen Suche ist dumm, wenn Sie können wählen Sie ein superior-Algorithmus.
Ich weiß, dass dieses Thema alt ist, aber ich konnte nicht halten mich von der Buchung. Meine Optimierung für eine sentinel-linear-Suche:
Den sentinel-Suche große Verbesserung ist, dass seine iteration verwendet nur eine bedingte Verzweigung (key) anstelle von zwei (index und Schlüssel).
Rollen mit festen array-Indizes.
Diese Antwort ist ein wenig dunkler als meine anderen, so bin ich Entsendung es separat. Es beruht auf der Tatsache, dass C garantiert eine Boolesche Ergebnis false=0 und true=1. X86 produzieren können booleans ohne Verzweigung, so könnte es schneller sein, aber ich habe es noch nicht getestet. Mikro-Optimierungen wie diese werden immer stark abhängig von Prozessor und compiler.
Als vor der Aufrufer ist dafür verantwortlich, dass eine sentinel-Wert am Ende des Arrays, um sicherzustellen, dass die Schleife beendet.
Bestimmung der optimalen Menge der loop-unrolling ein wenig Experimentieren. Suchen Sie den Punkt Abnehmender (oder negative) gibt. Ich werde nehmen eine BEUTE und versuchen 8 diese Zeit.
Edit: Als die Punkte Markieren, die diese Funktion stellt eine Abhängigkeit in jeder Zeile auf der vorhergehenden Zeile, die Grenzen der Fähigkeit der Prozessor-pipeline zum ausführen von Operationen parallel. So versuchen wir eine kleine änderung an der Funktion zum entfernen der Abhängigkeit. Nun die Funktion erfordert in der Tat 8 sentinel-Elemente am Ende.
Könnte man vermeiden n prüft, ähnlich wie loop unrolling macht es
Schleife nach hinten, könnte dies übersetzt werden...
...auf diese( "könnte" schneller ):
Andere als die, nur binary search kann die Suche schneller
loop
nicht schnell; in den meisten komplexen Anweisungen sind langsamer als mehrere einfache Anweisungen heute. Auch, woudln nicht diese machen einen schlechten Gebrauch von caches?diese könnten es erzwingen, Vektor-Anweisungen (vorgeschlagen von Gman):
dadurch auch weniger branch-Instruktionen.
Sie helfen, durch die Gewährleistung der Eingabe-array ist ausgerichtet auf die 16-byte-Grenze
andere Sache, die helfen können, Vektorisierung (tut vertikal max-Vergleich):
Suchen Sie für eine größere element als int in einer Zeit, die Plattform - spezifisch sind, kann dies viel schneller oder langsamer, je nachdem, wie es mit der größeren Daten Lesen. Zum Beispiel, auf einem 64-bit-system, das Lesen in das array 2 Elemente zu einer Zeit und überprüfen die hi/low Elemente einzeln konnte schneller laufen, da weniger I/O. Dennoch ist dies eine O(n) verschiedene Art, egal was.
In einem der Kommentare, die Sie sagte, die array-Länge ist 64.
Gut, wenn Sie muss tun es Linear, die Sie tun können:
Aber ich bezweifle ernsthaft, wenn es das ist schneller als diese binäre Suche: *
*Dank Jon Bentley für eine.
Fügte hinzu: da Sie gesagt haben, ist diese Tabelle bereit ist, sobald Sie für eine große Anzahl von Suchanfragen, und Sie wollen schnell, konnte Sie weisen Sie einige Raum irgendwo und generieren Computer-code mit den Werten der hard-wired, in es. Es kann entweder die lineare oder binäre Suche. Wenn binäre, der Computer-code Aussehen würde, was würde der compiler daraus generieren:
Dann einfach kopieren, in einen Ort, wo man das so nennen kann.
ODER Sie können drucken Sie den obigen code, kompilieren Sie und verknüpfen Sie es on-the-fly in eine dll und lädt die dll.
In der Realität, die Antwort auf diese Frage ist zu 100% abhängig von der Plattform, Sie schreiben den code für. Zum Beispiel:
Gut, könnte man Zeiger verwenden...
i
variable. Verwendenreturn p - array
zur Berechnung der Länge von einem Zeiger Subtraktion, wenn Sie wollen, um tatsächlich mit der hand halten der compiler, in eine engere innere Schleife. Es sei denn, Sie zeigen compiler output zeigt, dass dies ein schöner innere Schleife, obwohl, haben Sie noch einei++
sowiearray++
.