Schnellster Weg, um sicher zu sein, dass die Speicherregion leer ist (alles NULL)?

8

Wenn ich einen unsigned char *data -Zeiger habe und prüfen möchte, ob size_t length der Daten an diesem Zeiger NULL ist, was wäre der schnellste Weg, das zu tun? Mit anderen Worten, was ist der schnellste Weg, um sicherzustellen, dass eine Speicherregion leer ist?

Ich implementiere in iOS, also kann man davon ausgehen, dass iOS-Frameworks verfügbar sind, wenn das hilft. Auf der anderen Seite sind einfache C-Ansätze ( memcmp und dergleichen) ebenfalls OK.

Beachten Sie, dass ich nicht versuche, den Speicher zu löschen, sondern versuche, zu bestätigen, dass es bereits klar ist (Ich versuche herauszufinden, ob es irgendetwas gibt alles in einigen Bitmap-Daten, wenn das hilft). Zum Beispiel denke ich, dass das Folgende funktionieren würde, obwohl ich es noch nicht ausprobiert habe:

%Vor%

Ich möchte jedoch lieber kein Tester-Array erstellen, da die Quelldaten sehr groß sein können und ich es eher vermeiden möchte, Speicher für den Test zuzuweisen, auch nur vorübergehend. Aber ich bin dort vielleicht zu konservativ.

UPDATE: Einige Tests

Danke an alle für die tollen Antworten unten. Ich entschloss mich, eine Test-App zu erstellen, um zu sehen, wie diese Ergebnisse erzielt wurden. Die Antworten haben mich überrascht, also dachte ich, ich würde sie teilen. Zuerst zeige ich Ihnen die Version der Algorithmen, die ich verwendet habe (in einigen Fällen unterscheiden sie sich geringfügig von den vorgeschlagenen) und dann teile ich einige Ergebnisse aus dem Feld.

Die Tests

Zuerst habe ich einige Beispieldaten erstellt:

%Vor%

Jeder Test bestand aus einem Schleifenlauf loop mal. Während der Schleife wurden einige Zufallsdaten zum data byte-Datenstrom hinzugefügt und daraus entfernt. Beachten Sie, dass in der Hälfte der Zeit keine Daten hinzugefügt wurden. Die Hälfte der Zeit sollte also keine Daten ungleich Null finden. Beachten Sie, dass der Aufruf testZeros ein Platzhalter für Aufrufe der folgenden Testroutinen ist. Ein Timer wurde vor der Schleife gestartet und nach der Schleife gestoppt.

%Vor%

Test A: nullToLength. Dies war mehr oder weniger meine ursprüngliche Formulierung oben, debuggte und vereinfachte ein wenig.

%Vor%

Test B: allZero. Vorschlag von Carrotman.

%Vor%

Test C: is_all_zero. Vorgeschlagen von Lundin.

%Vor%

Test D: sumArray. Dies ist die beste Antwort aus der fast doppelten Frage , vorgeschlagen von vladr.

%Vor%

Test E: lulz. Vorgeschlagen von Steve Jessop.

%Vor%

Test F: NSData. Dies ist ein Test mit dem NSData-Objekt, das ich im iOS-SDK entdeckt habe, während ich an all diesen Dingen gearbeitet habe. Es stellt sich heraus, dass Apple eine Idee hat, wie Byte-Streams zu vergleichen sind, die Hardware-unabhängig sein soll.

%Vor%

Ergebnisse

Wie haben diese Ansätze verglichen? Hier sind zwei Datensätze, die jeweils 5000 Schleifen durch den Check darstellen. Zuerst habe ich dies auf dem iPhone Simulator versucht, der auf einem relativ alten iMac läuft, dann habe ich es auf einem iPad der ersten Generation versucht.

Auf dem iPhone 4.3 Simulator läuft auf einem iMac:

%Vor%

Auf einem iPad der ersten Generation:

%Vor%

Das sind nur zwei Beispiele, ich habe den Test viele Male mit nur leicht variierenden Ergebnissen durchgeführt. Die Reihenfolge der Leistung war immer die gleiche: A & amp; F sehr nah, E nur hinter, C, B und D. Ich würde sagen, dass A, F und E virtuelle Verbindungen sind, auf iOS würde ich F bevorzugen, weil es den Schutz von Apple vor Prozessorwechselproblemen nutzt, aber A & amp; E sind sehr nah. Der memcmp-Ansatz überzeugt den Simple-Loop-Ansatz deutlich, im Simulator fast zehnmal schneller und am Gerät doppelt so schnell. Seltsamerweise, D, hat die Gewinnantwort des anderen Threads in diesem Test sehr schlecht abgeschnitten, wahrscheinlich weil sie nicht aus der Schleife ausbricht, wenn sie den ersten Unterschied trifft.

    
EFC 01.07.2011, 06:01
quelle

6 Antworten

2

Nicht sicher, ob es das Beste ist, aber ich würde wahrscheinlich so etwas tun:

%Vor%

Wenn Sie diesen Speicher gerade zugewiesen haben, können Sie immer Calloc statt Malloc aufrufen (Calloc erfordert, dass alle Daten auf Null gesetzt werden). (Edit: Lesen Sie Ihren Kommentar zum ersten Post, Sie brauchen das nicht wirklich. Ich werde es nur für den Fall lassen)

    
Carrotman42 01.07.2011, 06:15
quelle
3

Ich denke, du solltest es mit einer expliziten Schleife machen, aber nur für lulz:

%Vor%

Im Gegensatz zu memcpy , erfordert memcmp nicht, dass die beiden Datenabschnitte nicht überlappen.

Es kann durchaus sein, dass es langsamer als die Schleife ist, weil die Unausgerichtetheit der Eingabezeiger bedeutet, dass die Implementierung von memcmp wahrscheinlich nicht viel zu optimieren braucht, und dass es Speicher mit Speicher und nicht mit Speicher vergleicht mit einer Konstante. Einfach genug, um es zu profilieren und herauszufinden.

    
Steve Jessop 01.07.2011 09:24
quelle
2

Wenn Sie den Speicher selbst zuweisen, würde ich vorschlagen, calloc() Funktion. Es ist genau wie malloc() , außer dass zuerst der Puffer gelöscht wird. Es wird verwendet, um Speicher für Objective-C-Objekte zuzuweisen. Dies ist der Grund dafür, dass alle ivars standardmäßig auf 0 gesetzt sind.

Wenn dies jedoch ein statisch deklarierter Puffer oder ein Puffer ist, den Sie nicht selbst zuweisen, ist memset() die einfache Möglichkeit, dies zu tun.

    
Dave DeLong 01.07.2011 06:14
quelle
1

Logic, um einen Wert zu erhalten, überprüfen Sie es und stellen Sie es mindestens so teuer wie nur einstellen. Sie möchten, dass es null ist, also setzen Sie es mit memset () auf null.

    
djna 01.07.2011 06:06
quelle
1

Dies wäre der bevorzugte Weg, dies in C zu tun:

%Vor%

(Beachten Sie, dass eine Speicherzelle, die einen NULL-Zeiger enthält, nicht notwendigerweise 0 sein muss, solange eine Nullzeiger-Umwandlung den Wert Null ergibt und eine Umwandlung von Null in einen Zeiger resultiert ein NULL-Zeiger In der Praxis sollte dies keine Rolle spielen, da alle bekannten Compiler 0 oder (void *) 0 für NULL verwenden.)

    
Lundin 01.07.2011 06:59
quelle
0

Beachten Sie die Änderung der ersten Frage oben. Ich habe einige Tests durchgeführt und es ist klar, dass der memcmp -Ansatz oder Apples NSData -Objekt und seine isEqualToData: -Methode die besten Ansätze für die Geschwindigkeit sind. Die einfachen Loops sind für mich klarer, aber langsamer auf dem Gerät.

    
EFC 02.07.2011 07:41
quelle

Tags und Links