En supposant quelque chose comme: Je peux aller plus vite sur une machine d'accès non alignée (par exemple x86) en écrivant quelque chose comme: p> Cependant, il doit construire sur plusieurs architectures, donc je voudrais faire quelque chose comme: p> mais je ne trouve aucune bonne information sur les macros définies du compilateur (comme mon hypothétique __ aligné4 __ code> ci-dessus) qui spécifient l'alignement ou toute façon intelligente d'utiliser le pré-processeur pour déterminer l'alignement de l'architecture cible. Je pourrais simplement tester
défini (__svr4) && défini (__sun) code>, mais je préférerais quelque chose qui va simplement fonctionner tm sup> sup> sur d'autres architectures nécessitant des accès à la mémoire alignée. P> p>
3 Réponses :
Alors que X86 fixe silencieusement les accès non alignés, cela n'est guère optimal pour la performance. Il est généralement préférable d'assumer un certain alignement et de réaliser des réalisations vous-même:
unsigned int const alignment = 8; /* or 16, or sizeof(long) */ void memcpy(char *dst, char const *src, unsigned int size) { if((((intptr_t)dst) % alignment) != (((intptr_t)src) % alignment)) { /* no common alignment, copy as bytes or shift around */ } else { if(((intptr_t)dst) % alignment) { /* copy bytes at the beginning */ } /* copy words in the middle */ if(((intptr_t)dst + size) % alignment) { /* copy bytes at the end */ } } }
Sur la base de la définition OP i code> en dehors du
code> boucle, je suis inquiet qu'il n'a pas C99 ou
intptr_t code>.
Même sans C99, chaque système de type UNIX que j'ai vu a eu intptr_t code> dans
intttypes.h code> pour les âges ... Je ne pense pas que ce soit un problème.
Et +1 à Simon pour résoudre le problème de manière optimale même sur les arcs qui "permettent" d'un accès non aligné. Mais c'est probablement une mauvaise idée de faire une alignement code> une variable et non une constante.
+1, mais j'utiliserais uintptr_t code>, modulo de valeurs signées est suspect
et pour les instructions de SIMD, un bon compilateur doit comprendre que par lui-même, par exemple si vous donniez -march = natif code> à GCC, je le ferais, je pense, dès que vous lui donnez grand assez de types entiers à traiter.
Je crains que la copie des deux tampons de source dans des tampons alignés, la création d'un tampon de bande aligné, faisant le masque de manière alignée, puis en déplaçant la mémoire tampon de bande alignée dans le tampon Dest non aligné que l'utilisateur transmettra de manière significative plus que juste Payer le coût du masque de ByTewise non aligné en premier lieu.
J'utilisais memcpy code> principalement à titre d'exemple, car il est facile de comprendre.
L'approche standard serait d'avoir un script code> configurer code> qui exécute un programme pour tester les problèmes d'alignement. Si le programme de test ne se bloque pas, le script de configuration définit une macro dans une en-tête de configuration générée qui permet une implémentation plus rapide. La mise en œuvre plus sûre est la valeur par défaut.
void mask_bytes(unsigned char* dest, unsigned char* src, unsigned char* mask, unsigned int len) { unsigned int i; unsigned int wordlen = len >> 2; #if defined(UNALIGNED) // go fast for(i=0; i<wordlen; i++) { // the following line will raise SIGBUS on SPARC and other archs that require aligned access. ((uint32_t*)dest)[i] = ((uint32_t*)src)[i] & ((uint32_t*)mask)[i]; } for(i=wordlen<<2; i<len; i++){ dest[i] = src[i] & mask[i]; } #else // go slow for(i=0; i<len; i++) { dest[i] = src[i] & mask[i]; } #endif }
(Je trouve qu'il est étrange que vous avez Une autre option consiste à utiliser différentes fonctions qui tirent parti des types dans C. Par exemple: P> src code> et
masque code> quand vraiment ces commutes. J'ai renommé
mask_bytes > à
memand code>. Mais de toute façon ...)
void memand_bytes(char *dest, char *src1, char *src2, size_t len)
{
unsigned int i;
for (i = 0; i < len; i++)
dest[i] = src1[i] & src2[i];
}
void memand_ints(int *dest, int *src1, int *src2, size_t len)
{
unsigned int i;
for (i = 0; i < len; i++)
dest[i] = src1[i] & src2[i];
}
La CPU fait les cycles supplémentaires pour obtenir les données non alignées et le transférer au bon endroit. Normalement, cela serait significatif plus lent puis aligné obtenir. Vous devriez toujours essayer de lire aligné ...
Tout comme dire que j'ai toujours travaillé sur des systèmes qui ne peuvent pas faire des copies transversales, de sorte que je viens de venir assumer l'existence de copies normales et "rapides" comme normale.
Malheureusement, cela se trouve dans une bibliothèque et je ne peux pas contrôler comment les utilisateurs de cette bibliothèque alignent les tampons qu'ils m'envoient.