2017-09-08 4 views
0

J'ai une structure de données qui contient 8 vecteurs bit, chacun 64 bits. Toutefois, les octets individuels pour ces tableaux sont entrelacés dans la structure de données au lieu d'être l'un après l'autre, chaque octet successif dans un bitvector donné étant de 8 octets après le précédent. Existe-t-il un moyen efficace (comme la charge parallèle et le stockage) pour déplacer des données entre ces tableaux imbriqués et un mot de 64 bits sur les processeurs x86-64 modernes? Le code C avec asm incorporé est correct bien que s'il existe une solution qui utilise les intrinsèques gcc, ce serait encore mieux.Comment lire ou écrire un tableau entrelacé?

+3

Il pourrait y avoir plusieurs techniques intéressantes pour cela, pourquoi ne postez-vous pas un exemple minimum viable de la structure, avec quelques exemples de données et peut-être même une version non optimisée du résultat que vous souhaitez obtenir pour que quelqu'un puisse vous aider. En l'état, c'est une question très vaste sans en connaître les détails. –

+1

Bien qu'il puisse y avoir des manières intelligentes de faire ceci (VPSHUFB vient à l'esprit), il semble peu probable que le temps et l'effort pour les écrire et les tester vous épargneraient beaucoup à moins que vous fassiez BEAUCOUP de charges de ces données. La solution de SBS peut ne pas être aussi sexy que quelque chose d'écrit en ASM en utilisant AVX2 ou AVX512BW, mais cela va être beaucoup plus portable et maintenable. À moins que ce ne soit un goulot d'étranglement dans votre code, je voterais pour un simple over sexy. –

Répondre

0

Je ne suis pas au courant des instructions du processeur x64 qui fonctionnent sur des données entrelacées comme ça. Cependant, étant donné que ces processeurs sont assez rapides sur le transfert et indexé E/S, j'utiliser l'approche suivante avec 8 inline déplacer/copier les opérations, et laisser le reste à l'optimiseur:

void Write (unsigned char*  bytes, 
      unsigned long long value, 
      int    offset) 
    { 
    bytes [offset  ] = (unsigned char) (value  ); 
    bytes [offset + 8] = (unsigned char) (value >> 8); 
    bytes [offset + 16] = (unsigned char) (value >> 16); 
    bytes [offset + 24] = (unsigned char) (value >> 24); 
    bytes [offset + 32] = (unsigned char) (value >> 32); 
    bytes [offset + 40] = (unsigned char) (value >> 40); 
    bytes [offset + 48] = (unsigned char) (value >> 48); 
    bytes [offset + 56] = (unsigned char) (value >> 56); 
    return; 
    } 

void Read (unsigned char*  bytes, 
      unsigned long long* value, 
      int     offset) 
    { 
    *value = ((unsigned long long) bytes [offset  ]  ) | 
      ((unsigned long long) bytes [offset + 8] << 8) | 
      ((unsigned long long) bytes [offset + 16] << 16) | 
      ((unsigned long long) bytes [offset + 24] << 24) | 
      ((unsigned long long) bytes [offset + 32] << 32) | 
      ((unsigned long long) bytes [offset + 40] << 40) | 
      ((unsigned long long) bytes [offset + 48] << 48) | 
      ((unsigned long long) bytes [offset + 56] << 56); 
    return; 
    } 

Ce magasins de code les valeurs de 64 bits dans l'ordre little-endian. Pour big-endian, il suffit de lire/écrire les octets dans l'ordre inverse.