2016-12-19 1 views
-2

Je suis très nouveau dans l'assemblage et je veux trouver tous les triplets pythagoriciens dans une gamme de 1 à 100. Je suis en train de générer tous les nombres en C et tous les autres calculs devraient être faits dans l'assemblage SSE. J'essayais de le faire en utilisant la commande sqrt (j'ai essayé tous) mais je ne pouvais pas le faire fonctionner .. Quelqu'un peut-il me dire comment cela devrait être fait?Comment trouver des triplets pythagoriciens en utilisant les instructions de montage SSE?

C'est ce que j'ai jusqu'à présent:

int main(){ 
      for (int i = 1; i <= 100; i++) 
      { 
       a++; 
       if (a > 100) 
        a = 0; 
       for (int j = 1; j <= 100; j++) 
       { 
        b++; 
        if (b > 100) 
         b = a; 
        _asm //tricky part begins here: 
        { 
         movups xmm0, a 
         movups xmm1, b 
         pmuludq xmm0, xmm0 
         pmuludq xmm1, xmm1 
         //movups xmm2, 0 
         //paddd xmm2, xmm0 
         //paddd xmm2, xmm1 
         movups z, xmm0 
        } 
        printf("%d\n", z); 
       } 
      } 
    } 
+7

"Je veux faire cela en assemblage car je sais que c'est plus rapide que C." Comment sais-tu ça? Parce que ça ne sera probablement pas le cas. –

+6

Je ne suppose pas que votre asm écrit à la main sera plus rapide qu'une sortie du compilateur C. Les compilateurs sont intelligents, les processeurs modernes sont complexes. – Blorgbeard

+0

Notez votre algorithme en C ou en pseudocode en premier. – Jester

Répondre

2

Le problème fondamental avec votre approche est que vous devez être à la recherche à 4 b valeurs en parallèle, de sorte que vous ne pouvez pas charger à partir d'un C variable scalaire. Vous devez conserver des éléments dans les registres vectoriels à travers les itérations de boucle, car vous ne chargez pas seulement des vecteurs à partir de la mémoire ou de quelque chose. Vous devriez écrire toute la boucle dans asm car MSVC inline asm aspire à l'encapsulation de courtes séquences, en raison de la surcharge inévitable d'obtenir des résultats in/out.

Bien sûr, la meilleure façon de vectoriser cette boucle serait avec les intrinsèques C, pas avec inline asm. Ensuite, vous pouvez tenir le compilateur en main pour faire de meilleurs asm si nécessaire (et si possible) en vérifiant sa sortie asm pour les inefficacités. (Voir Why is this C++ code faster than my hand-written assembly for testing the Collatz conjecture?)


Bien sûr, si vous vouliez vraiment juste pour créer un code efficace pour générer des triplets pythagoriciens, votre algorithme est faux aussi:

L'article de Wikipedia a une section generating a triple qui décrit la formule d'Euclide . Itérer ce serait un problème différent de vérifier les hits dans une recherche brute de l'espace de recherche a=[1..100] b=[1..100], car vérifier si un nombre est un carré parfait est assez lent.

En outre, la détection des éléments vectoriels correspondant à une condition est maladroite. Une instruction packed-compare et ensuite PMOVMSKB (ou MOVMSKPS) vous donneront un bitmap, mais cela fonctionne mieux lorsque les hits sont rares, par ex. implémentant memchr où votre boucle s'arrête après le premier hit.

+0

Notez que la vérification de tout l'espace de recherche 'a = [1..100] b = [1..100]' prend moins de .005 secondes sur un ordinateur de bureau moyen, donc la prémisse entière de la question est absurde. – user3386109

+0

@ user3386109: C'est toujours un million ou deux cycles d'horloge, assez longs pour mesurer avec précision les compteurs de perf. Mais évidemment, le point s'applique plus aux plages de recherche plus grandes. Et appeler 'printf' au milieu de la recherche sur chaque hit est ridicule, plutôt que de les stocker dans un tableau ou quelque chose. –