Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » XOR mit strings?

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 <
010
29.07.2005, 02:05 Uhr
tabin



ne darum gehts ja auch nicht - anstatt alle zeichen einzelen zu betrachten schau ich mir halt ganze bereiche an daher suche ich ja auch eine einfache schnelle funktion - das verfahren ähnelt halt binärer suche - das lohnt natürlich nur wenn es so billige vergleiche gibt - ich geh mal davon aus das memcmp schneller oder zumindest gleich so schnell ist wie eine for-schleife - daher hat die überlegung mir dem speicher

--tabin--
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
29.07.2005, 09:16 Uhr
virtual
Sexiest Bit alive
(Operator)


Mich hat der Thread angeregt, mal nahzudenken, die man memcmp "verschnellern" kann.
Hier das Ergebnis:

C++:
int fmemcmp(const void* p1, const void* p2, size_t n) {
    const signed char* a = (const signed char*)p1;
    const signed char* b = (const signed char*)p2;
    if (a==b) {
        return 0;
    }
    else if ((a-b)%sizeof(int)) {
        return memcmp(a,b,n);
    }
    else {
        const signed char* ea = a+n;
        while(((long)a)%sizeof(int)) {
            int res = *a++ - *b++;
            if (res) return res;
        }
        while (ea-a>=sizeof(int)) {
            if (*(int*)a!=*(int*)b) {
                return *(int*)a>*(int*)b? 1:-1;
            }
            a += sizeof(int);
            b += sizeof(int);
        }
        while (ea!=a) {
            int res = *a++ - *b++;
            if (res) return res;
        }
    }
    return 0;
}


Ein normales memcmp wird normalerweise byteweise vergleichen. Diese Routine probiert einen möglichst großen Bereich int weise (bei mir: 4 Byte) zu vergleichen. Dabei sollten die Anfangsadressen der zu vergleichenden Speicherbereiche durch sizeof(int) teilbar sein: Sind sie es nicht, kann es je nach Prozessor zu geschwindigkeitseinbußen kommen. ( in diesem Fall switcht die Routine über zum normalen memcmp, ist also nach wie vor universell einsetzbar.
Optimiert ist das Ganze für grosse Speicherblöcke, dh ich erwarte eigentlich Nachteile für kleine Speicherbereiche, weil sich da der Overhead von den ganzen if Abfragen bemerkbar machen dürfte. Getestet habe ich das mit 40000 Vergleiche von zwei Inhaltsgleichen Arrays so um die 1MB Größe, mit folgenden Programm (stopwatch ist eine kleine Klasse zur Zeitmessung, kann ich bei Bedarf schicken):

C++:
int main() {
    char a[1000004];
    char b[1000004];
    
    memcpy(a, b, sizeof(a));

    stopwatch stdsw;
    stopwatch fastsw;
    
    for(int i=0; i<10000; ++i) {
        for(int j=0; j<4; ++j) {
            stdsw.start();
            memcmp(a+j, b+j, 1000000-j);
            stdsw.stop();

            fastsw.start();
            fmemcmp(a+j, b+j, 1000000-j);
            fastsw.stop();
        }
    }
    
    std::cout<<"Standard: "<<stdsw<<std::endl;
    std::cout<<"Fast:     "<<fastsw<<std::endl;
}


Die ergebnisse sind:

Code:
Standard: 290.698460
Fast:     206.034660


Dh nach meiner Lesart kommt meine Version mit 70% der Rechenzeit des normalen memcpy aus. Ich halte das nicht für die ultimative Lösung, zumal ich - wie gesagt - meine, daß die fmemcmp Funktion mit abnehmender Arraylänge möglicherweise Langsamer als das memcmp arbeitet.
Ich wollte ao eigentlich nur beweisen, daß ich zumindestens probiere, früh aufzustehen.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
29.07.2005, 09:30 Uhr
virtual
Sexiest Bit alive
(Operator)


PS:
Ich habe vergessen zu erwähnen, daß es sicherlich nicht übertragbar ist, das ergebnis. Ich habe eine GNU Implementierung von memcmp benutzt und die GNU RuntimeLibrary zeichnet sich durch hohe portabilität, weniger durch hohe optimierung aus...

Bzgl. tabin Problem kann man sich durachausvorstellen die Routine dahingehend zu modifierzieren, daß sie bei gleichheit -1, sonst jedoch den Index des ersten unterschieds zurückgibt, um eben prefixe zu bestimmen.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
29.07.2005, 09:47 Uhr
ao

(Operator)



Zitat von virtual:
Ein normales memcmp wird normalerweise byteweise vergleichen.

Ich hätte schon gedacht, dass die meisten memcmp-Implementierungen, die so im Umlauf sind, eben nicht *byte*-weise vergleichen, sondern in der größtmöglichen Breite, in der die CPU vergleichen kann.

Zitat:
Ich habe vergessen zu erwähnen, daß es sicherlich nicht übertragbar ist, das ergebnis. Ich habe eine GNU Implementierung von memcmp benutzt und die GNU RuntimeLibrary zeichnet sich durch hohe portabilität, weniger durch hohe optimierung aus...

Das glaube ich gern, dass bei GNU solche Kompromisse gemacht werden. (soll kein GNU-Bashing sein, Portabilität *ist* bei GNU ein wichtiger Punkt, und da haben viele Nischen-CPU-Benutzer schon von profitiert).

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
29.07.2005, 17:55 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat von ao:

Ich hätte schon gedacht, dass die meisten memcmp-Implementierungen, die so im Umlauf sind, eben nicht *byte*-weise vergleichen, sondern in der größtmöglichen Breite, in der die CPU vergleichen kann.



Nö, guck mal hier, das ist die Implementieruing vom VC, welcher nun wirklich nicht großartig portabel sein muß:

C++:
int __cdecl memcmp (
        const void * buf1,
        const void * buf2,
        size_t count
        )
{
        if (!count)
                return(0);

        while ( --count && *(char *)buf1 == *(char *)buf2 ) {
                buf1 = (char *)buf1 + 1;
                buf2 = (char *)buf2 + 1;
        }

        return( *((unsigned char *)buf1) - *((unsigned char *)buf2) );
}


Je mehr ich drüber nachdenke, desto mehr komme ich zum Schluß, daß das Byteweise kopieren die bessere Lösung ist:
1. Mein Code mag zwar (manchmal) nur 70% der Laufzeit haben, aber 2-4 Mal soviel Platz benötigen, und manchmal ist eben der Platz entscheidend.
2. Mein Code funktioniert nur dann schneller, wenn die Speicherbereiche eine bestimmte Lage haben. Der Geschwindigkeitsvorteil ist also nicht verläßlich.
3. Der Code ist hochgradig unportabel; die wahl der größtmöglichen Speicherbreite ist nicht immer die Richtige Wahl: Kompiliere ich das auf einem 32 Bit system, werde ich auf einem 64 Bitter mit dem gleichen Binary probleme bekommen, bei Byteweisen Vergleichen aber nicht.

Ich will damit sagen, daß ich mir normalerweise nicht die Arbeit mache, gut und schnell funktionierende RuntimeLibrary Funktionen nachzuprogrammieren. die 70% sind bei Licht betrachtet eine Illusion.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
29.07.2005, 19:15 Uhr
(un)wissender
Niveauwart


Meine VC 7.1 memcmp vergleicht 4 byte und ist sehr schnell. Ist in Asm.
--
Wer früher stirbt ist länger tot.

Dieser Post wurde am 29.07.2005 um 19:16 Uhr von (un)wissender editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: