Wie benutze ich die Übertrag-lose Multiplikation (PCLMULQDQ) in zlib CRC32?

8

Ich habe kürzlich mit CloudFlares optimiertem zlib gespielt und die Ergebnisse sind wirklich beeindruckend.

Leider scheinen sie angenommen zu haben, dass die Entwicklung von Zlib aufgegeben wurde, und ihre Gabel brach ab. Ich war schließlich in der Lage, manuell ihre Änderungen auf die aktuelle Zlib-Entwicklung Zweig, obwohl es ein echter Schmerz in den Arsch war.

Wie auch immer, es gibt immer noch eine große Optimierung im CloudFlare-Code, die ich nicht nutzen konnte, nämlich die schneller CRC32-Code implementiert mit den PCLMULQDQ Übertragslosen Multiplikationsanweisungen, die in neueren (Haswell und später, glaube ich) Intel-Prozessoren enthalten sind, weil:

  1. Ich bin auf einem Mac, und weder der clam integrierte Assembler noch Apples altes GAS verstehen die neueren GAS-Mnemonics, und

  2. Der Code wurde aus dem Linux-Kernel entfernt und ist GPL2, was die gesamte Bibliothek GPL2 macht und damit für meine Zwecke praktisch nutzlos macht.

Also habe ich ein wenig herumgejagt und nach ein paar Stunden bin ich auf einen Code gestoßen, den Apple in ihrem bzip2 verwendet: handgeschriebene, vektorisierte CRC32-Implementierungen für beide arm64 und x86_64 .

Seltsamerweise sind die Kommentare für die x86_64-Assembly (nur) in der arm64-Quelle, aber es scheint darauf hinzuweisen, dass dieser Code mit zlib verwendet werden könnte:

%Vor%

Aber leider, nach ein paar Versuchen, scheint mir an diesem Punkt etwas zu sein. Und ich bin mir nicht sicher, wie ich das eigentlich machen soll . Also ich hatte gehofft, jemand könnte mir zeigen, wie / wo man die angebotene Funktion nennen würde.

(Es wäre auch fantastisch, wenn es eine Möglichkeit gäbe, die notwendigen Features zur Laufzeit zu finden und auf die Software-Implementierung zurückgreifen könnte, wenn die Hardware-Funktionen nicht verfügbar wären, sodass ich nicht mehrere verteilen müsste Wenn aber irgendjemand mir helfen könnte, herauszufinden, wie man die Apple PCLMULQDQ-basierte CRC32 richtig benutzen kann, würde das sehr lange dauern.

    
Geoff Nixon 22.05.2016, 11:30
quelle

1 Antwort

4

Wie es heißt, müssen Sie die CRC-Summe auf einem 16-Byte ausgerichteten Puffer berechnen, der eine Länge von mehreren 16 Bytes hat. Daher würden Sie den aktuellen Pufferzeiger als uintptr_t darstellen und solange die 4 LSB-Bits nicht Null sind, erhöhen Sie den Zeiger, der die Bytes in eine normale CRC-32-Routine einspeist. Sobald Sie eine Adresse mit 16 Byte ausgerichtet haben, runden Sie die verbleibende Länge auf ein Vielfaches von 16 ab, und geben Sie dann diese Bytes an die schnelle CRC-32 und wieder die verbleibenden Byte an die langsame Berechnung.

Etwas wie:

%Vor%     
Antti Haapala 22.05.2016 12:27
quelle