Dans l'écosystème des extensions vectorielles évolutives (SVE) d'ARM, la fonction intrinsèque svcmpgt_u32 est dédiée à l'évaluation de la supériorité stricte entre des vecteurs d'entiers non signés de 32 bits. Elle effectue une comparaison élément par élément pour déterminer si les composantes du premier vecteur dépassent celles du second, générant ainsi un masque de prédicats. Cette opération est fondamentale pour le filtarge conditionnel et l'exécution de logiques vectorielles sans recourir à des branchements scalaires coûteux.
Signature de la fonction
svbool_t svcmpgt_u32(
svbool_t pg,
svuint32_t vec_a,
svuint32_t vec_b
);
Analyse des paramètres
- pg (Masque de prédicat) : Un vecteur de type
svbool_tqui dicte les lanes actives. Seuls les éléments dont le bit de masque est actif (1) seront évalués. Les autres lanes produiront systématiquement un résultat inactif (0). - vec_a et vec_b : Des registres vectoriels SVE (
svuint32_t) contenant les opérandes non signés de 32 bits. La capacité de ces vecteurs dépend de l'implémentation matérielle (par exemple, 8 éléments pour un registre de 256 bits, 16 pour 512 bits).
Valeur de retour
La fonction retourne un svbool_t. Chaque bit de ce masque de sortie reflète le résultat de la comparaison pour la lane correspondante :
- Le bit est à
1sivec_a[i] > vec_b[i]ET que la laneiest activée parpg. - Le bit est à
0dans tous les autres cas (infériorité, égalité, ou lane désactivée par le prédicat).
Mécanisme et exemple théorique
L'objectif principal est de traduire une condition arithmétique en un masque binaire réutilisable. Considérons un vecteur de 4 éléments 32 bits :
vec_a = [12, 4, 9, 1]vec_b = [10, 5, 9, 8]pg = [1, 1, 0, 1](la troisième lane est ignorée)
Le calcul donne : 12 > 10 (vrai), 4 > 5 (faux), la troisième lane est forcée à 0, et 1 > 8 (faux). Le masque résultant est donc [1, 0, 0, 0].
Cas d'usage pratique : Transformation conditionnelle
Plutôt qu'une simple agrégation, svcmpgt_u32 est idéal pour appliquer des transformations sélectives. L'exemple suivant parcourt un tableau et multiplie par deux uniquement les éléments strictement supérieurs à une limite définie, tout en laissant les autres intacts.
#include <arm_sve.h>
#include <stddef.h>
void appliquer_facteur_conditionnel(uint32_t* donnees, size_t nombre_elements, uint32_t limite) {
size_t index = 0;
svbool_t lanes_actives = svwhilelt_b32(index, nombre_elements);
svuint32_t vecteur_limite = svdup_n_u32(limite);
svuint32_t multiplicateur = svdup_n_u32(2);
while (svptest_any(svptrue_b32(), lanes_actives)) {
// Chargement des éléments courants
svuint32_t bloc_courant = svld1_u32(lanes_actives, donnees + index);
// Génération du masque pour les éléments > limite
svbool_t masque_superieur = svcmpgt_u32(lanes_actives, bloc_courant, vecteur_limite);
// Multiplication conditionnelle : seuls les éléments du masque sont modifiés
svuint32_t resultat_echelle = svmul_u32_m(masque_superieur, bloc_courant, multiplicateur);
// Écriture des résultats en mémoire
svst1_u32(lanes_actives, donnees + index, resultat_echelle);
// Avancement de l'index et mise à jour du masque pour le prochain bloc
index += svcntw();
lanes_actives = svwhilelt_b32(index, nombre_elements);
}
}
Points d'attention techniques
- Nature des données : Cette instruction est strictement réservée aux entiers non signés (
uint32_t). Pour des valeurs signées, l'usage desvcmpgt_s32est impératif pour éviter des erreurs di'nterprétation du bit de signe. - Gestion des bords : Le paramètre
pgest crucial pour traiter les tableaux dont la taille n'est pas un multiple de la largeur vectorielle. Il isole les données valides lors de la dernière itération, évitant ainsi les lectures ou écritures hors limites. - Chaînage d'instructions : Le masque
svbool_tgénéré est conçu pour être injecté directement dans des opérations de sélection (svsel), de chargement/stockage conditionnel, ou d'arithmétique prédiquée, éliminant ainsi les pénalités de prédiction de branchement. - Gain de performance : En évaluant simultanément plusieurs paires d'opérandes (jusqu'à 16 sur une architecture 512 bits), cette approche sature bien mieux les unités d'exécution vectorielles qu'une boucle scalaire traditionnelle, réduisant drastiquement le nombre d'instructions par cycle.