2009-09-23 6 views
4

En essayant de comprendre si la boucle interne de mon code atteint une barrière de conception matérielle ou un manque de compréhension de ma part. Il y a un peu plus à lui, mais la plus simple question que je peux trouver pour répondre est la suivante:Quelle est l'accélération théorique maximale due à SSE pour une soustraction binaire simple?

Si je le code suivant:

float px[32768],py[32768],pz[32768]; 
float xref, yref, zref, deltax, deltay, deltaz; 

initialize_with_random(px); 
initialize_with_random(py); 
initialize_with_random(pz); 

for(i=0;i<32768-1;i++) { 
    xref=px[i]; 
    yref=py[i]; 
    zref=pz[i]; 
    for(j=0;j<32768-1;j++ { 
    deltx=xref-px[j]; 
    delty=yref-py[j]; 
    deltz=zref-pz[j]; 
    } } 

Quel type de vitesse théorique maximale en serais-je capable de voir en allant aux instructions SSE dans une situation où j'ai un contrôle complet sur le code (assemblage, intrinsèques, etc.) mais pas de contrôle sur l'environnement d'exécution autre que l'architecture (c'est un environnement multi-utilisateur donc je ne peux rien faire comment le noyau OS affecte le temps à mon processus particulier).

En ce moment, je vois une accélération de 3x avec mon code, quand j'aurais pensé que l'utilisation de SSE me donnerait beaucoup plus de profondeur vectorielle que la vitesse 3x indique (probablement l'accélération de 3x me dit que j'ai un débit théorique maximum de 4x). (J'ai essayé des choses comme laisser deltx/delty/deltz être des tableaux dans le cas où le compilateur n'était pas assez intelligent pour les auto-promouvoir, mais je ne vois encore que 3x accélérer.) J'utilise le compilateur intel C avec les drapeaux de compilateur appropriés pour la vectorisation, mais pas intrinsèquement évidemment.

+0

question stupide, mais supprime le '-1' de la pour les conditions changent quelque chose? (votre boucle va de 0 à 32766 au lieu de 32767) – Hasturkun

+0

Non, c'est un nombre arbitraire.Dans le code de production actuel, ce nombre serait variable de toute façon. (Ce qui veut dire que je devrai à la fin dérouler la boucle en morceaux de taille de registre je crois et manipuler le boîtier terminal avec une logique supplémentaire.) –

Répondre

4

Cela dépend de la CPU. Mais le maximum théorique ne dépassera pas 4x. Je ne connais pas de CPU qui puisse exécuter plus d'une instruction SSE par cycle d'horloge, ce qui signifie qu'il peut au maximum calculer 4 valeurs par cycle.

La plupart des processeurs peuvent faire au moins une instruction scalaire à virgule flottante par cycle, donc dans ce cas vous verrez un maximum théorique d'une accélération 4x.

Mais vous devrez rechercher le débit d'instructions spécifique pour le processeur que vous utilisez.

Une accélération pratique de 3x est plutôt bonne.

+0

Les extensions pratiques supérieures à 4x sont possibles, au moins dans certaines situations, et sur certains modèles . Une fois, le processeur d'un grand fabricant a surpassé facilement le nouveau modèle de 2 générations du concurrent sur un code qui faisait beaucoup de calculs vectoriels et scalaires (avec une pression de mémoire modeste). Il s'est avéré que sur le processeur «plus ancien et plus lent», le code non-SSE s'est déroulé entièrement hors service et «gratuitement» pendant que le code SSE fonctionnait. Bien que ce soit un cas vraiment spécial, je suppose qu'un compilateur d'optimisation pourrait atteindre similaire sur une petite échelle. – Damon

2

Je pense que vous devrez probablement entrelacer la boucle interne en quelque sorte. Le vecteur à trois composants se fait à la fois, mais ce n'est que trois opérations à la fois. Pour arriver à 4, vous feriez 3 composants à partir du premier vecteur, et 1 à partir du suivant, puis 2 et 2, et ainsi de suite. Si vous avez créé un type de file d'attente qui charge et traite les données 4 composants à la fois, séparez-le ensuite, cela peut fonctionner. Editer: Vous pouvez dérouler la boucle interne pour faire 4 vecteurs par itération (en supposant que la taille du tableau est toujours un multiple de 4). Cela accomplirait ce que j'ai dit plus haut.

1

Considérez: Quelle est la largeur d'un flotteur? Quelle est la largeur de l'instruction SSEx? Le ratio devrait vous donner une sorte de limite supérieure raisonnable.

Il est également intéressant de noter que les tuyaux hors d'usage jouent havok avec de bonnes estimations de l'accélération.

0

Vous devriez considérer loop tiling - la façon dont vous accédez aux valeurs dans la boucle interne cause probablement beaucoup de thrashing dans le cache de données L1. Ce n'est pas si mal, car tout reste dans la L2 à 384 Ko, mais il y a facilement une différence d'ordre de grandeur entre un cache L1 et un cache L2, ce qui peut faire une grande différence pour vous.

Questions connexes