memcpy in assembly



  • Dass das Problem ziemlich kompliziert ist, zeigt schon was AMD zur Optimierung von Kopierroutinen empfiehlt:

    Software Optimization Guide for AMD64 Processors schrieb:

    5.13 Memory Copy
    Optimization
    ❖ For a very fast general purpose memory copy routine, call the libc memcpy() function included
    with the Microsoft or gcc tools. This function features optimizations for all block sizes and
    alignments.

    Von daher wiederhol ich noch malen Vorschlag, Agner Fogs lib zu verwenden: das ist ein hoch optimierte, Quelloffene All-In-One Lösung – besser werdet ihr es nie hinbekommen.



  • hoch optimierte, Quelloffene All-In-One Lösung

    Klingt gut! Wie aus der Werbung. Werde ich mir merken diesen maximalen Spruch. 😃



  • This is my memcpy, I also have clear and set if you want them.

    memfunc.asm

    global _memcpy
    
    _memcpy:
    	push edi
    	push esi
    	mov ecx, [esp+20]
    	mov edi, [esp+12]
    	mov esi, [esp+16]
    	;Move (E)CX bytes from [(E)SI] to ES:[(E)DI]
    	cld
    	rep movsb
    	pop esi
    	pop edi
    	ret
    

    memory.h

    void memcpy(void *dest, void *src, uint32_t len);
    


  • Jarvix schrieb:

    This is my memcpy, I also have clear and set if you want them.

    Unfortunately a bad solution



  • ... was würde gegen eine einfache Implementierung der memcpy() Funktion sprechen:

    void* memcpy(void* dst, const void* src, size_t total_bytes)
    {
        uint32_t i = 0u;
        uint8_t* a = dst;
        const uint8_t* b = src;
    
        for (i = 0u; i < total_bytes; ++i)
        {
            a[i] = b[i];
        }
    
        return dst;
    }
    

    - das war's. Ich stelle mir vor, das ist die schnellste Variante, weil einfach und simpel. Inline-Assembler - zu kompliziert, Zeiger-Arithmetik - zu kompliziert, SSE, MMX & Co. - auch zu kompliziert 🙂



  • abc.w schrieb:

    das war's. Ich stelle mir vor, das ist die schnellste Variante, weil einfach und simpel.

    so einfach ist es aber leider nicht ...



  • Zum memset

    Ihr werdet ja wahrscheinlich größtenteils Seiten benötigen, welche mit 0 beschrieben sind. Dann könntet ihr euch die Mühe ersparen zu optimieren, wenn ihr einen Task mit sehr niedriger Priorität erstellt, der zum Beispiel immer 10 genullte Pages bereitstellt, und auch nur arbeitet, sollte eine dieser 10 Seiten fehlen. (weiteres steht im Tanenbaum)



  • Die memcpy funktion benutzt in der Implementierung bei Visual C++ den rep move befehl und prüft ausserdem, ob die Länge eine ganzahlige vielfache von 4 ist, dann können in einen Takt bis zu 4 Bytes kopiert werden. Für den Rest wird dann rep movesb benutzt.

    Wenn ich dann also z.B. 256 Bytes kopiere, dann brauche ich dafür nur 64 Takte statt 256, wenn ich nur Byteweise kopieren würde, also mind. 4x schneller als die Lösung von abc.w und Jarvix.

    Ebenso analog arbeitet auch memmove.


Anmelden zum Antworten