est memset plus efficace que pour la boucle. donc si j'ai
char x[500];
memset(x,0,sizeof(x));
ou
char x[500];
for(int i = 0 ; i < 500 ; i ++) x[i] = 0;
lequel est le plus efficace et pourquoi? existe-t-il une instruction spéciale dans le matériel pour effectuer l'initialisation au niveau du bloc.
Très certainement, memset
sera beaucoup plus rapide que cette boucle. Notez comment vous traitez un caractère à la fois, mais ces fonctions sont tellement optimisées qu'elles définissent plusieurs octets à la fois, même en utilisant, lorsqu'elles sont disponibles, MMX et SSE instructions.
Je pense que l'exemple paradigmatique de ces optimisations, qui passent généralement inaperçues, est la fonction GNU C library strlen
. On pourrait penser qu'elle a au moins O(n) performances, mais il a en fait O(n/4) ou O(n/8) selon l'architecture (oui , Je sais, en gros O() sera le même, mais vous obtenez en fait un huitième du temps Comment? Tricky, mais joliment: strlen .
Eh bien, pourquoi ne pas jeter un coup d'œil au code d'assemblage généré, optimisation complète sous VS 2010.
char x[500];
char y[500];
int i;
memset(x, 0, sizeof(x) );
003A1014 Push 1F4h
003A1019 lea eax,[ebp-1F8h]
003A101F Push 0
003A1021 Push eax
003A1022 call memset (3A1844h)
Et votre boucle ...
char x[500];
char y[500];
int i;
for( i = 0; i < 500; ++i )
{
x[i] = 0;
00E81014 Push 1F4h
00E81019 lea eax,[ebp-1F8h]
00E8101F Push 0
00E81021 Push eax
00E81022 call memset (0E81844h)
/* note that this is *replacing* the loop,
not being called once for each iteration. */
}
Donc, sous ce compilateur, le code généré est exactement le même. memset
est rapide, et le compilateur est suffisamment intelligent pour savoir que vous faites la même chose que d'appeler memset
une fois de toute façon, donc il le fait pour vous.
Si le compilateur a effectivement laissé la boucle telle quelle, cela serait probablement plus lent car vous pouvez définir plus d'un bloc de taille d'octet à la fois (c'est-à-dire que vous pouvez dérouler votre boucle un peu au minimum. Vous pouvez supposer que memset
sera au moins aussi rapide qu'une implémentation naïve telle que la boucle. Essayez-la sous une version de débogage et vous remarquerez que la boucle n'est pas remplacée.
Cela dit, cela dépend de ce que le compilateur fait pour vous. Regarder le démontage est toujours un bon moyen de savoir exactement ce qui se passe.
Cela dépend vraiment du compilateur et de la bibliothèque. Pour les compilateurs plus anciens ou les compilateurs simples, memset peut être implémenté dans une bibliothèque et ne fonctionnerait pas mieux qu'une boucle personnalisée.
Pour presque tous les compilateurs qui valent la peine d'être utilisés, memset est une fonction intrinsèque et le compilateur va générer du code en ligne optimisé pour cela.
D'autres ont suggéré de profiler et de comparer, mais je ne me dérangerais pas. Utilisez simplement memset. Le code est simple et facile à comprendre. Ne vous inquiétez pas jusqu'à ce que vos tests de référence vous indiquent que cette partie du code est un point chaud de performance.
La réponse est "cela dépend". memset
PEUT être plus efficace, ou il peut utiliser en interne une boucle for. Je ne peux pas penser à un cas où memset
sera moins efficace. Dans ce cas, cela peut devenir une boucle for plus efficace: votre boucle itère 500 fois en définissant une valeur de 0 octets du tableau à chaque fois. Sur une machine 64 bits, vous pouvez effectuer une boucle, en définissant 8 octets (un long long) à la fois, ce qui serait presque 8 fois plus rapide, et en traitant simplement les 4 octets restants (500% 8) à la fin.
ÉDITER:
en fait, c'est ce que memset
fait dans la glibc:
http://repo.or.cz/w/glibc.git/blob/HEAD:/string/memset.c
Comme Michael l'a souligné, dans certains cas (où la longueur du tableau est connue au moment de la compilation), le compilateur C peut inline memset
, en supprimant la surcharge de l'appel de fonction. Glibc dispose également de versions optimisées pour l'assemblage de memset
pour la plupart des plates-formes majeures, comme AMD64:
http://repo.or.cz/w/glibc.git/blob/HEAD:/sysdeps/x86_64/memset.S
Les bons compilateurs reconnaîtront la boucle for et la remplaceront par une séquence en ligne optimale ou un appel à memset. Ils remplaceront également le memset par une séquence en ligne optimale lorsque la taille du tampon est petite.
En pratique, avec un compilateur d'optimisation, le code généré (et donc les performances) sera identique.
D'accord avec ci-dessus. Ça dépend. Mais, à coup sûr, le memset est plus rapide ou égal à la boucle for. Si vous n'êtes pas sûr de votre environnement ou que vous êtes trop paresseux pour tester, prenez la route sûre et optez pour le memset.