Seite 1 von 1

Alternatives Copymemory()

Verfasst: 07.10.2006 22:26
von Hellhound66
Ich hab mir mal hier ein anderes copymemory zusammengebastelt. Bei mir auf dem Athlon ist es bis zu 100% schneller. Mich würden eure Ergebnisse interessieren.

Code: Alles auswählen



Macro __cpya() ; __cpy#A1#()
    !MOVDQA [Edi+Eax]    ,xmm1
    !MOVDQA [Edi+Eax+16] ,xmm2
    !MOVDQA [Edi+Eax+32] ,xmm3
    !MOVDQA [Edi+Eax+48] ,xmm4
    !ADD Eax,64
EndMacro


Macro __cpyu()
    !MOVDQU [Edi+Eax]    ,xmm1
    !MOVDQU [Edi+Eax+16] ,xmm2
    !MOVDQU [Edi+Eax+32] ,xmm3
    !MOVDQU [Edi+Eax+48] ,xmm4
    !ADD Eax,64
EndMacro

Macro __cpys()
    !MOVNTDQ [Edi+Eax]    ,xmm1
    !MOVNTDQ [Edi+Eax+16] ,xmm2
    !MOVNTDQ [Edi+Eax+32] ,xmm3
    !MOVNTDQ [Edi+Eax+48] ,xmm4
    !ADD Eax,64
EndMacro

Macro __cpyblock(A1)
    !MOVDQ#A1# xmm1,[Esi+Eax]
    !MOVDQ#A1# xmm2,[Esi+Eax+16]
    !MOVDQ#A1# xmm3,[Esi+Eax+32]
    !MOVDQ#A1# xmm4,[Esi+Eax+48]
EndMacro

Prototype Memcpy(*Source,*Dest,Size.l)
Global MemCpy.MemCpy


Goto __JUMPOVER
__MemCpy:
!PUSH Esi
!PUSH Edi

!MOV Ecx,[Esp+20]
!MOV Esi,[Esp+12]
!MOV Edi,[Esp+16]
!XOR Eax,Eax
!MOV Ebx,Ecx
!SHR Ecx,6
!JZ @Parity

!TEST Esi,15
!JZ @okay1
!TEST Edi,15
!JZ @version01
!JMP @version00

!@okay1:
!TEST Edi,15
!JZ @Version11
!TEST Esi,15
!JZ @version10
!JMP @version00


!@Version11:
!@inner_loop11:
__cpyblock(a)
__cpys()
!DEC Ecx
!JNZ @inner_loop11
!JMP @Parity

!@version01:
!@inner_loop01:
__cpyblock(u)
__cpya()
!DEC Ecx
!JNZ @inner_loop01
!JMP @Parity

!@version10:
!@inner_loop10:
__cpyblock(a)
__cpyu()
!DEC Ecx
!JNZ @inner_loop10
!JMP @Parity

!@version00:
!@inner_loop00:
__cpyblock(u)
__cpyu()
!DEC Ecx
!JNZ @inner_loop00
; !JMP @Parity


!@Parity:
!AND Ebx,15
!JZ @retxxx
!MOV Ecx,Ebx
!REP movsb
!@retxxx:
!POP Edi
!POP Esi
!RET 12

__JUMPOVER:

MemCpy = ?__MemCpy



Delay(500)

#BufferSize = 904011
*Buffer1 = AllocateMemory(#BufferSize)
*Buffer2 = AllocateMemory(#BufferSize)
For i=1 To #BufferSize/4
    PokeL(*Buffer1+i-1,i*2)
Next
OpenConsole()
PrintN(Str(*Buffer1&15))
PrintN(Str(*Buffer2&15))
TestZeit.l  = ElapsedMilliseconds()
For i=1 To 1000
    Memcpy(*Buffer1,*Buffer2,#BufferSize)
Next
PrintN(Str(CompareMemory(*Buffer2,*Buffer1,#BufferSize)))
Zeit1 = ElapsedMilliseconds()-TestZeit


TestZeit.l  = ElapsedMilliseconds()
For i=1 To 1000
    CopyMemory(*Buffer1,*Buffer2,#BufferSize)
Next
Zeit3 = ElapsedMilliseconds()-TestZeit


Print("Es wurden je 1000 Aufrufe gestartet"+#crlf$+"Hellhound66 : "+Str(Zeit1)+" ms."+#crlf$+"PB brauchte : "+Str(Zeit3)+" ms."+#crlf$)
MessageRequester("Ende","Programm beendet",#PB_MessageRequester_Ok)

Verfasst: 07.10.2006 23:03
von Hellhound66
/update:
Da die Prozedur bei Speicherblöcken unter ~4KB sehr langsam wurde, hab ich sie dafür nochmal optimiert:

Code: Alles auswählen



Macro __cpya() ; __cpy#A1#()
    !MOVDQA [Edi+Eax]    ,xmm1
    !MOVDQA [Edi+Eax+16] ,xmm2
    !MOVDQA [Edi+Eax+32] ,xmm3
    !MOVDQA [Edi+Eax+48] ,xmm4
    !ADD Eax,64
EndMacro


Macro __cpyu()
    !MOVDQU [Edi+Eax]    ,xmm1
    !MOVDQU [Edi+Eax+16] ,xmm2
    !MOVDQU [Edi+Eax+32] ,xmm3
    !MOVDQU [Edi+Eax+48] ,xmm4
    !ADD Eax,64
EndMacro

Macro __cpys()
    !MOVNTDQ [Edi+Eax]    ,xmm1
    !MOVNTDQ [Edi+Eax+16] ,xmm2
    !MOVNTDQ [Edi+Eax+32] ,xmm3
    !MOVNTDQ [Edi+Eax+48] ,xmm4
    !ADD Eax,64
EndMacro

Macro __cpyblock(A1)
    !MOVDQ#A1# xmm1,[Esi+Eax]
    !MOVDQ#A1# xmm2,[Esi+Eax+16]
    !MOVDQ#A1# xmm3,[Esi+Eax+32]
    !MOVDQ#A1# xmm4,[Esi+Eax+48]
EndMacro

Prototype Memcpy(*Source,*Dest,Size.l)
Global MemCpy.MemCpy


Goto __JUMPOVER
__MemCpy:
!PUSH Esi
!PUSH Edi

!MOV Ecx,[Esp+20]
!MOV Esi,[Esp+12]
!MOV Edi,[Esp+16]
!XOR Eax,Eax
!MOV Ebx,Ecx
!SHR Ecx,6
!JZ @Parity

!CMP Ecx,62
!JL @alternative

!TEST Esi,15
!JZ @okay1
!TEST Edi,15
!JZ @version01
!JMP @version00

!@okay1:
!TEST Edi,15
!JZ @Version11
!TEST Esi,15
!JZ @version10
!JMP @version00


!@Version11:
!@inner_loop11:
__cpyblock(a)
__cpys()
!DEC Ecx
!JNZ @inner_loop11
!JMP @Parity

!@version01:
!@inner_loop01:
__cpyblock(u)
__cpya()
!DEC Ecx
!JNZ @inner_loop01
!JMP @Parity

!@version10:
;CallDebugger
!@inner_loop10:
__cpyblock(a)
__cpyu()
!DEC Ecx
!JNZ @inner_loop10
!JMP @Parity

!@version00:
!@inner_loop00:
__cpyblock(u)
__cpyu()
!DEC Ecx
!JNZ @inner_loop00
; !JMP @Parity


!@Parity:
!AND Ebx,15
!JZ @retxxx
!MOV Ecx,Ebx
!SHR Ecx,1
!JNC @JUMP1
!movsb
!@JUMP1:
!SHR Ecx,1
!JNC @jump2
!movsw
!@jump2:
!JZ @retxxx
!REP movsd
!@retxxx:
!POP Edi
!POP Esi
!RET 12

!@alternative:
!MOVQ mm0,[Esi+Eax]
!MOVQ mm1,[Esi+Eax+8]
!MOVQ mm2,[Esi+Eax+16]
!MOVQ mm3,[Esi+Eax+24]
!MOVQ mm4,[Esi+Eax+32]
!MOVQ mm5,[Esi+Eax+40]
!MOVQ mm6,[Esi+Eax+48]
!MOVQ mm7,[Esi+Eax+56]

!MOVQ [Edi+Eax]     ,mm0
!MOVQ [Edi+Eax+8]   ,mm1
!MOVQ [Edi+Eax+16]  ,mm2
!MOVQ [Edi+Eax+24]  ,mm3
!MOVQ [Edi+Eax+32]  ,mm4
!MOVQ [Edi+Eax+40]  ,mm5
!MOVQ [Edi+Eax+48]  ,mm6
!MOVQ [Edi+Eax+56]  ,mm7

!ADD Eax,64
!DEC Ecx
!JNZ @alternative

!JMP @Parity

__JUMPOVER:

MemCpy = ?__MemCpy



Delay(500)

#BufferSize = 300
*Buffer1 = AllocateMemory(#BufferSize)
*Buffer2 = AllocateMemory(#BufferSize)
For i=1 To #BufferSize/4
    PokeL(*Buffer1+i-1,i*2)
Next
OpenConsole()
PrintN(Str(*Buffer1&15))
PrintN(Str(*Buffer2&15))
TestZeit.l  = ElapsedMilliseconds()
For i=1 To 10000000
    Memcpy(*Buffer1,*Buffer2,#BufferSize)
Next
PrintN(Str(CompareMemory(*Buffer2,*Buffer1,#BufferSize)))
Zeit1 = ElapsedMilliseconds()-TestZeit


TestZeit.l  = ElapsedMilliseconds()
For i=1 To 10000000
    CopyMemory(*Buffer1,*Buffer2,#BufferSize)
Next
Zeit3 = ElapsedMilliseconds()-TestZeit


Print("Es wurden je 10000000 Aufrufe gestartet"+#crlf$+"Hellhound66 : "+Str(Zeit1)+" ms."+#crlf$+"PB brauchte : "+Str(Zeit3)+" ms."+#crlf$)
MessageRequester("Ende","Programm beendet",#PB_MessageRequester_Ok)

Verfasst: 07.10.2006 23:10
von SoS
Es wurden je 10000 Aufrufe gestartet
Hellhound66 : 593 ms.
PB brauchte : 1735 ms.
P4 2.6 ghz

Verfasst: 07.10.2006 23:54
von Lukaso
Es wurden je 10000 Aufrufe gestartet
Hellhound66 : 516 ms.
PB brauchte : 718 ms.
AMD64 3000+

Verfasst: 08.10.2006 00:02
von Fluid Byte
Es wurden je 10000000 Aufrufe gestartet
Hellhound66 : 469 ms.
PB brauchte : 1422 ms.

Verfasst: 08.10.2006 00:05
von mknjc
So mal meine Messungen

Hellhound66 PB
535 1675
550 1691
566 1675
503 1675
581 1707

547 1684,6

Unten ist der Durchschnittswert.

PB4

Rennt auf nem P4 HT 3,06

Verfasst: 08.10.2006 11:10
von Thorium
Bei mir nur gering schneller:

10000000 Aufrufe
Hellhount66: 1122
PureBasic: 1302

AMD Athlon 3200+ Barton

Verfasst: 08.10.2006 11:39
von Hellhound66
Im letzteren werden nur kleine Speicherblöcke kopiert. Mach den Speicherblock größer, dann wird der Unterschied ebenfalls größer ^^