c ++ - hurtigste måde at kontrollere om hukommelsen er nulstillet

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et program, der skal kontrollere, om en del af en fil er nulstillet eller har data. Denne alg kører for hele filen for størrelser op til et par koncerter og tager et stykke tid at køre. Er der en bedre måde at tjekke for at se om den er nulstillet?


Platform: Linux og Windows


bool WGTController::isBlockCompleted(wgBlock* block)
{
    if (!block)
        return false;

    uint32 bufSize = (uint32)block->size;
    uint64 fileSize = UTIL::FS::UTIL\_getFileSize(m\_szFile);

    if (fileSize < (block->size + block->fileOffset))
        return false;

    char* buffer = new char[bufSize];

    FHANDLE fh=NULL;

    try
    {
        fh = UTIL::FS::UTIL\_openFile(m\_szFile, UTIL::FS::FILE\_READ);
        UTIL::FS::UTIL\_seekFile(fh, block->fileOffset);
        UTIL::FS::UTIL\_readFile(fh, buffer, bufSize);
        UTIL::FS::UTIL\_closeFile(fh);
    }
    catch (gcException &)
    {
        SAFE\_DELETEA(buffer);
        UTIL::FS::UTIL\_closeFile(fh);
        return false;
    }

    bool res = false;

    for (uint32 x=0; x<bufSize; x++)
    {
        if (buffer[x] != 0)
        {
            res = true;
            break;
        }
    }

    SAFE\_DELETEA(buffer);
    return res;
}

Bedste reference


Hvor lang tid er 'et stykke tid'? ... Jeg siger at forsøge at sammenligne så mange værdier parallelt som muligt, vil hjælpe, måske brug nogle SIMD-instruktioner til at sammenligne mere end 4 byte ad gangen?


Husk dog, at uanset hvor hurtigt du laver sammenligningen, skal dataene i sidste ende læses fra filen. Hvis filen ikke allerede er i cache et sted i hukommelsen, kan du være begrænset til i størrelsesordenen 100-150 MB/s maksimalt, før diskens båndbredde er mættet. Hvis du allerede har ramt dette punkt, skal du måske først se på en tilgang, der undgår at skulle indlæse filen, eller bare acceptere det faktum, at det ikke bliver hurtigere end det.

Andre referencer 1


Er der steder i filen/klumpen, hvor det er mere sandsynligt, at der ikke er nulværdier? Du skal kun finde en ikke-nulværdi (din pause tilstand), så se først på steder hvor du sandsynligvis finder dem - hvilket ikke skal være starten på en fil/chunk. Det kan være fornuftigt at starte i slutningen, eller tjek 1/3 i midten afhængigt af den aktuelle applikation.


Jeg vil dog ikke anbefale at springe tilfældigt til forskellige positioner; læsning fra disk kan blive utroligt;) ..

Andre referencer 2


Jeg vil gerne se montageudgangen til denne funktion.
Noget, som du kunne gøre det, ville fremskynde det med meget, er at bruge SSE-instruktioner. Med disse instruktioner kan du indlæse 8 byte ad gangen, kontrollere dem alle for nul og fortsætte.
Og du kunne også aflede det for løkke et par gange også.

Andre referencer 3


Du algo virker ok, men du kan heuristisk optimere startstedet, hvis du i forvejen vidste hvilken type fil du vil få ... men så igen, hvis det er en bestemt fil, sandsynligvis vil informationen være i overskriften (de første få bytes).


Sørg også for at blok-> størrelse ikke er 1 fra den, der kalder metoden :)


Se også Boosts hukommelseskortede filer faciliteter ... Det kan være en hjælp, afhængigt af hvordan du beregner den optimale blok-> størrelse

Andre referencer 4


Jeg har et 'ud af kassen' svar for dig, men jeg er ikke sikker på, hvor feasabel det er at implementere i din situation.


Hvis du ikke kontrollerer dumpingprocessen: Da det er en stor genoprettelsesfil (dump?), Der produceres på excpetional sag, hvorfor scan ikke filen (for 0 bytes) med lav prioritet lige efter det er dumpet, og marker det på en eller anden måde for hurtigere senere identifikation? (eller du kan zip den og analysere/scan zipfilen senere)


Eller hvis du kontrollerer dumpingprocessen: (En langsom proces du skal gøre), hvorfor ikke angive i slutningen af ​​dumpfilen (eller gå tilbage og skriv i starten af ​​det), hvis dumpfilen er fyldt med 0 eller Har nogle gyldige data (siden du skrev det og du ved hvad der er i det)? sådan skal du ikke betale for I/O overhead to gange.


Målet her er at gøre læsningen meget hurtigere ved at deffere procss til en anden eraliertid, siden da dumpningen sker, er det usandsynligt, at der er en operatør, der venter på at den skal indlæses.

Andre referencer 5


Først må du ikke allokere en ny buffer hver gang. Fordel en (per tråd) og genbruge den. Brug en dejlig stor klump, og gør flere læs/checkpasser.

For det andet skal du ikke sammenligne hvert tegn. Gør sammenligninger på en større integreret type. Sandsynligvis vil du have en 32bit int, men afhængigt af din os/compiler kan det være hurtigere at bruge 64 eller endda 128 bit int. Med en 32bit int du reducerer dit antal sammenligninger med 4x. Din vilje skal selvfølgelig bekymre sig om slutbetingelserne. For det er det nemt, hvis den buffer du sammenligner ikke er lige mange af din int størrelse, skal du bare indstille sidste X bytes til 0 før du gør sammenligningen.
For det tredje kan det hjælpe din compiler lidt med at afrolle sløjfen. Gør 4 eller 8 sammenligninger i loopens krop. Dette skal hjælpe kompilatoren optimere en smule samt reducere antallet af sammenligninger for at gå ud af sløjfen. Sørg for, at din buffer er et multiplum af din sammenligningstype x antallet af sammenligninger i sløjfen.
For det fjerde kan det være hurtigere at bruge (* pBuffer ++) i stedet for buffer [[i]], især hvis bufferen er stor.


For nogen af ​​disse vil du selvfølgelig gerne få nogle beregninger og se, hvad der rent faktisk hjælper.

Andre referencer 6


Jeg vil fortælle dig en beskidt, ikke-bærbar og vanskelig måde, men end det kan være mere effektivt ... Hvis du beskæftiger dig med sparsomme filer, er du virkelig ked af det, og du vil rive med internerne i filsystemerne du bruger, Du kan forsøge at tilføje en ny funktion, der giver dig en bitmap, der angiver hvilke blokke der er kortlagt, og hvilke der ikke er nulstillede (de ikke-kortlagte er nulstillede, resten skal du stadig kontrollere manuelt).


Ja, jeg ved det er vildt, og ingen vil nogensinde gerne gøre noget som denne xD