Memcpy et zeromemory

Soyez le premier à donner votre avis sur cette source.

Vue 8 394 fois - Téléchargée 98 fois


Description

vu le nombre de sources se servant pour remplir ou copier un tableau d'une boucle for, j'ai pensé utile de demontré la performance des fonctions memcpy et ZeroMemory.
Je ne sait pas si ce sont les plus optimizées mais je les trouvent assez performantes (3 ou 4 fois superieur à la boucle for). Mais cela doit aussi dependre du compilateur et de l'optimisation.
Bon désolé c'est du C++ qui aurait du etre du C mais j'ai pas envie de transformer.

Source / Exemple :


#include <iostream>
#include <time.h>
#include <windows.h>

using namespace std;

#define LG 500000
#define DUREE 1

int main( void)
{
	cout<< "Programme de test de l'optimization des fonctions memcpy et ZeroMemory." <<endl;
	cout<< "Debut des tests. Veillez patienter.\n"  << endl;

	//tableau servant pour les essai.
	int *tab1,*tab2;

	try
	{
		tab1 = new int[ LG ];
		tab2 = new int[ LG ];
	}
	catch(...)
	{
		cout<< "Erreur survenu durant l'allocation." << endl;
		cout<< "Veillez diminuez la taille des tableaux" << endl;
		return 1;
	}

//*********************Remplissage de la memoire par des zeros************************
	cout<< "Debut du test de remplissage par des zeros sans fonction." << endl;
	time_t temps1 = time( NULL),temps2;
	int comp = 0;
	do
	{
		for( int i=0; i<LG; i++)
		{
			tab1[i] = 0;
		}
		comp++;
		temps2= time( NULL);
	}while( temps2-temps1 < DUREE );
	cout << "il a ete fait " << comp << " remplissages complets en "<< DUREE << " secondes\n" << endl;

//******Remplissage de la memoire par des zeros graace a la fonction ZeroMemory********
	cout<< "Debut du test de remplissage par des zeros avec ZeroMemory." << endl;
	temps1 = time( NULL);
	comp = 0;
	do
	{
		ZeroMemory( (void*)tab1, LG);
		comp++;
		temps2= time( NULL);
	}while( temps2-temps1 < DUREE );
	cout << "il a ete fait " << comp << " remplissages complets en "<< DUREE << " secondes\n" << endl;

//************************Remplissage de la memoire par copie************************
	cout<< "Debut du test de copie de tableau sans fonction." << endl;
	temps1 = time( NULL);
	comp = 0;
	do
	{
		for( int i=0; i<LG; i++)
		{
			tab2[i] = tab1[i];
		}
		comp++;
		temps2= time( NULL);
	}while( temps2-temps1 < DUREE );
	cout << "il a ete fait " << comp << " remplissages complets en "<< DUREE << " secondes\n" << endl;

//*******Remplissage de la memoire par copie gace a la fonction memcpy***************
	cout<< "Debut du test de copie de tableaus avec memcpy." << endl;
	temps1 = time( NULL);
	comp = 0;
	do
	{
		memcpy( (void *)tab2, (void *)tab1, LG);
		comp++;
		temps2= time( NULL);
	}while( temps2-temps1 < DUREE );
	cout << "il a ete fait " << comp << " remplissages complets en "<< DUREE << " secondes\n" << endl;

	delete [] tab1;
	delete [] tab2;

	return 0;
}

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

zeratul67
Messages postés
97
Date d'inscription
mardi 9 avril 2002
Statut
Membre
Dernière intervention
11 mai 2008
-
Voici le code assembleur généré par VS, à titre d'info, suru n cas bien simple :

for (int i = 0; i < 255; i++)
0040101E mov dword ptr [i],0
00401028 jmp WinMain+39h (401039h)
0040102A mov eax,dword ptr [i]
00401030 add eax,1
00401033 mov dword ptr [i],eax
00401039 cmp dword ptr [i],0FFh
00401043 jge WinMain+55h (401055h)
tab[i] = 0;
00401045 mov eax,dword ptr [i]
0040104B mov byte ptr tab[eax],0
00401053 jmp WinMain+2Ah (40102Ah)

ZeroMemory(tab, 255);
00401055 push 0FFh
0040105A push 0
0040105C lea eax,[tab]
00401062 push eax
00401063 call memset (4010B0h)
00401068 add esp,0Ch

Et voici le code de Memset

;***
;memset.asm - set a section of memory to all one byte
;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
;Purpose:
; contains the memset() routine
;
;*******************************************************************************

.xlist
include cruntime.inc
.list

page
;***
;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value"
;
;Purpose:
; Sets the first "count" bytes of the memory starting
; at "dst" to the character value "value".
;
; Algorithm:
; char *
; memset (dst, value, count)
; char *dst;
; char value;
; unsigned int count;
; {
; char *start = dst;
;
; while (count--)
; *dst++ = value;
; return(start);
; }
;
;Entry:
; char *dst - pointer to memory to fill with value
; char value - value to put in dst bytes
; int count - number of bytes of dst to fill
;
;Exit:
; returns dst, with filled bytes
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************

CODESEG

public memset
memset proc

.FPO ( 0, 3, 0, 0, 0, 0 )

mov edx,[esp + 0ch] ; edx = "count"
004010B0 mov edx,dword ptr [esp+0Ch]
mov ecx,[esp + 4] ; ecx points to "dst"
004010B4 mov ecx,dword ptr [esp+4]

test edx,edx ; 0?
004010B8 test edx,edx
jz short toend ; if so, nothing to do
004010BA je toend (40110Bh)

xor eax,eax
004010BC xor eax,eax
mov al,[esp + 8] ; the byte "value" to be stored
004010BE mov al,byte ptr [esp+8]


; Align address on dword boundary

push edi ; preserve edi
004010C2 push edi
mov edi,ecx ; edi = dest pointer
004010C3 mov edi,ecx

cmp edx,4 ; if it's less then 4 bytes
004010C5 cmp edx,4
jb tail ; tail needs edi and edx to be initialized
004010C8 jb tail (4010FBh)

neg ecx
004010CA neg ecx
and ecx,3 ; ecx = # bytes before dword boundary
004010CC and ecx,3
jz short dwords ; jump if address already aligned
004010CF je dwords (4010DDh)

sub edx,ecx ; edx = adjusted count (for later)
004010D1 sub edx,ecx
adjust_loop:
mov [edi],al
004010D3 mov byte ptr [edi],al
add edi,1
004010D5 add edi,1
sub ecx,1
004010D8 sub ecx,1
jnz adjust_loop
004010DB jne adjust_loop (4010D3h)

dwords:
; set all 4 bytes of eax to [value]
mov ecx,eax ; ecx=0/0/0/value
004010DD mov ecx,eax
shl eax,8 ; eax=0/0/value/0
004010DF shl eax,8

add eax,ecx ; eax=0/0val/val
004010E2 add eax,ecx

mov ecx,eax ; ecx=0/0/val/val
004010E4 mov ecx,eax

shl eax,10h ; eax=val/val/0/0
004010E6 shl eax,10h

add eax,ecx ; eax all 4 bytes [value]
004010E9 add eax,ecx

; Set dword-sized blocks
mov ecx,edx ; move original count to ecx
004010EB mov ecx,edx
and edx,3 ; prepare in edx byte count (for tail loop)
004010ED and edx,3
shr ecx,2 ; adjust ecx to be dword count
004010F0 shr ecx,2
jz tail ; jump if it was less then 4 bytes
004010F3 je tail (4010FBh)

rep stosd
004010F5 rep stos dword ptr [edi]
main_loop_tail:
test edx,edx ; if there is no tail bytes,
004010F7 test edx,edx
jz finish ; we finish, and it's time to leave
004010F9 je finish (401105h)
; Set remaining bytes

tail:
mov [edi],al ; set remaining bytes
004010FB mov byte ptr [edi],al
add edi,1
004010FD add edi,1

sub edx,1 ; if there is some more bytes
00401100 sub edx,1
jnz tail ; continue to fill them
00401103 jne tail (4010FBh)

; Done
finish:
mov eax,[esp + 8] ; return dest pointer
00401105 mov eax,dword ptr [esp+8]
pop edi ; restore edi
00401109 pop edi

ret
0040110A ret
omi
Messages postés
11
Date d'inscription
samedi 12 janvier 2002
Statut
Membre
Dernière intervention
22 juillet 2003
-
Ben oui mais ces fonctions seront toujours plus rapide, a longueur égales, que avec une boucle for programmez a la main quelque soit la longeur de la chaine.
Qui d'ailleur dans le programme peut etre reglé en modifiant la constante LG.
JackosKing
Messages postés
168
Date d'inscription
mardi 31 décembre 2002
Statut
Membre
Dernière intervention
21 avril 2005
-
la vitesse est fonction de la longueur du buffer a effacer...

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.