Question

Je travaille sur vectorisation automatique avec GCC. Je ne suis pas en mesure d'utiliser les attributs ou intrinsics en raison de besoins du client. (Je ne peux pas obtenir l'entrée d'utilisateur pour soutenir vectorisation)

Si l'information d'alignement de la matrice qui peut être vectorisé est inconnue, GCC invoque un laissez-passer pour « boucle versioning ». versioning Loop sera effectuée lorsque vectorisation en boucle se fait sur les arbres. Quand une boucle est identifiée comme vectorisable et la contrainte sur l'alignement ou la dépendance des données de données est l'entraver, (parce qu'ils ne peuvent pas être déterminées au moment de la compilation), puis deux versions de la boucle seront générés. Ce sont les versions vectorisées et non vectorisées de la boucle ainsi que des contrôles d'exécution pour l'alignement ou de la dépendance à contrôler quelle version est exécutée.

Ma question est de savoir comment nous devons faire respecter l'alignement? Si j'ai trouvé une boucle qui est vectorisable, je ne devrais pas générer deux versions de la boucle en raison d'informations d'alignement manquantes.

Par exemple. Considérons le code ci-dessous

short a[15]; short b[15]; short c[15];
int i;

void foo()
{
    for (i=0; i<15; i++)
    {
      a[i] = b[i] ;
    }
}

décharge d'arbres (options: -ftree-vectoriser -fdump-tree optimisé)

<SNIP>
     vector short int * vect_pa.49;
     vector short int * vect_pb.42;
     vector short int * vect_pa.35;
     vector short int * vect_pb.30;

    bb 2>:
     vect_pb.30 = (vector short int *) &b;
     vect_pa.35 = (vector short int *) &a;
     if (((signed char) vect_pa.35 | (signed char) vect_pb.30) & 3 == 0)    ;; <== (A)
       goto <bb 3>;
     else
       goto <bb 4>;

    bb 3>:
</SNIP>

Dans la version 'bb 3' code vectorisé est généré. A code « bb 4 » sans vectorisation est généré. Ceux-ci sont effectués en vérifiant l'alignement (déclaration « A »). Maintenant, sans utiliser intrinsics et d'autres attributs, comment dois-je obtenir que le code vectorisé (sans cette vérification d'alignement d'exécution.)

Était-ce utile?

La solution

Si les données en question sont allouées statiquement, vous pouvez utiliser l'attribut __align__ que GCC prend en charge de préciser qu'il devrait être aligné sur la frontière nécessaire. Si vous allouez dynamiquement ces tableaux, vous pouvez effectuer des surallocations par la valeur d'alignement, puis remonter le pointeur retourné jusqu'à l'alignement dont vous avez besoin.

Vous pouvez également utiliser la fonction posix_memalign() si vous êtes sur un système qui le soutient. Enfin, notez que malloc() toujours allouer de la mémoire alignée sur la taille du plus grand de type intégré, généralement 8 octets pour un double. Si vous n'avez pas besoin mieux que cela, alors malloc devrait suffire.

Modifier : Si vous modifiez votre code d'allocation pour forcer cette vérification pour être vrai (à savoir overallocate, comme suggéré ci-dessus), le compilateur devrait obliger de ne pas conditionalizing le code de la boucle. Si vous avez besoin d'alignement sur une limite de 8 octets, comme il semble, ce serait quelque chose comme a = (a + 7) & ~3;.

Autres conseils

Je reçois qu'une seule version de la boucle, en utilisant votre code exact avec ces options: gcc -march=core2 -c -O2 -fdump-tree-optimized -ftree-vectorize vec.c

Ma version de GCC est gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu8).

GCC est en train de faire quelque chose d'intelligent ici. Il force les tableaux a et b à être aligné de 16 octets. Il ne fait pas que c, probablement parce que c est jamais utilisé dans une boucle vectorisable.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top