Frage: Was wissen wir über den Hamming-Abstand d (x, y)?
Antworten:
- Es ist nicht negativ: d (x, y) ≥ 0
- Es ist nur Null für identische Eingaben: d (x, y) = 0 ⇔ x = y
- Es ist symmetrisch: d (x, y) = d (y, x)
- Es gehorcht der Dreiecksungleichung , d (x, z) ≤ d (x, y) + d (y, z)
Frage: Warum interessiert es uns?
Antwort: Weil dies bedeutet, dass der Hamming-Abstand eine Metrik für einen metrischen Raum ist . Es gibt Algorithmen zum Indizieren von Metrikräumen.
Sie können auch Algorithmen für „räumliche Indizierung“ im Allgemeinen sehen, bewaffnet mit dem Wissen , dass Ihr Raum nicht euklidischen ist , aber es ist ein metrischer Raum. Viele Bücher zu diesem Thema behandeln die Indizierung von Zeichenfolgen mithilfe einer Metrik wie der Hamming-Entfernung.
Fußnote: Wenn Sie den Hamming-Abstand von Strings mit fester Breite vergleichen, können Sie möglicherweise eine signifikante Leistungsverbesserung erzielen, indem Sie Assembly- oder Prozessor-Intrinsics verwenden. Mit GCC ( manuell ) tun Sie beispielsweise Folgendes :
static inline int distance(unsigned x, unsigned y)
{
return __builtin_popcount(x^y);
}
Wenn Sie dann GCC darüber informieren, dass Sie für einen Computer mit SSE4a kompilieren, sollte sich dies meiner Meinung nach auf nur ein paar Opcodes reduzieren.
Bearbeiten: Laut einer Reihe von Quellen ist dies manchmal / oft langsamer als der übliche Mask / Shift / Add-Code. Das Benchmarking zeigt, dass auf meinem System eine C-Version die GCCs __builtin_popcount
um etwa 160% übertrifft .
Nachtrag: Ich war selbst neugierig auf das Problem und habe drei Implementierungen profiliert: lineare Suche, BK-Baum und VP-Baum. Beachten Sie, dass VP- und BK-Bäume sehr ähnlich sind. Die untergeordneten Elemente eines Knotens in einem BK-Baum sind "Schalen" von Bäumen, die Punkte enthalten, die jeweils einen festen Abstand vom Baumzentrum haben. Ein Knoten in einem VP-Baum hat zwei untergeordnete Elemente, von denen eines alle Punkte innerhalb einer Kugel enthält, die auf der Mitte des Knotens zentriert ist, und das andere untergeordnete Element alle Punkte außerhalb. Sie können sich also einen VP-Knoten als einen BK-Knoten mit zwei sehr dicken "Schalen" anstelle vieler feinerer vorstellen.
Die Ergebnisse wurden auf meinem 3,2-GHz-PC erfasst, und die Algorithmen versuchen nicht, mehrere Kerne zu verwenden (was einfach sein sollte). Ich habe eine Datenbankgröße von 100M Pseudozufallszahlen gewählt. Die Ergebnisse sind der Durchschnitt von 1000 Abfragen für die Entfernung 1..5 und 100 Abfragen für die Entfernung 6..10 und die lineare Suche.
- Datenbank: 100 Millionen pseudozufällige Ganzzahlen
- Anzahl der Tests: 1000 für Abstand 1..5, 100 für Abstand 6..10 und linear
- Ergebnisse: Durchschnittliche Anzahl der Abfragetreffer (sehr ungefähr)
- Geschwindigkeit: Anzahl der Abfragen pro Sekunde
- Abdeckung: Durchschnittlicher Prozentsatz der pro Abfrage untersuchten Datenbank
- BK-Baum - - VP-Baum - - Linear -
Dist Ergebnisse Geschwindigkeit Cov Geschwindigkeit Cov Geschwindigkeit Cov
1 0,90 3800 0,048% 4200 0,048%
2 11 300 0,68% 330 0,65%
3 130 56 3,8% 63 3,4%
4 970 18 12% 22 10%
5 5700 8,5 26% 10 22%
6 2,6e4 5,2 42% 6,0 37%
7 1.1e5 3.7 60% 4.1 54%
8 3,5e5 3,0 74% 3,2 70%
9 1,0e6 2,6 85% 2,7 82%
10 2,5e6 2,3 91% 2,4 90%
beliebige 2,2 100%
In Ihrem Kommentar haben Sie erwähnt:
Ich denke, BK-Bäume könnten verbessert werden, indem ein Haufen BK-Bäume mit verschiedenen Wurzelknoten erzeugt und verteilt wird.
Ich denke, dies ist genau der Grund, warum der VP-Baum (etwas) besser abschneidet als der BK-Baum. Da es eher "tiefer" als "flacher" ist, vergleicht es mit mehr Punkten, anstatt feinkörnigere Vergleiche mit weniger Punkten zu verwenden. Ich vermute, dass die Unterschiede in höherdimensionalen Räumen extremer sind.
Ein letzter Tipp: Blattknoten im Baum sollten für einen linearen Scan nur flache Anordnungen von Ganzzahlen sein. Bei kleinen Sätzen (möglicherweise 1000 Punkte oder weniger) ist dies schneller und speichereffizienter.