Question

J'ai actuellement le code suivant:

float a[4] = { 10, 20, 30, 40 };
float b[4] = { 0.1, 0.1, 0.1, 0.1 };
asm volatile("movups (%0), %%xmm0\n\t"
             "mulps (%1), %%xmm0\n\t"             
             "movups %%xmm0, (%1)"             
             :: "r" (a), "r" (b));

J'ai tout d'abord quelques questions:

(1) Si je voulais aligner les tableaux sur des limites de 16 octets, cela fonctionnerait-il? Puisque les tableaux sont alloués sur la pile, est-il vrai qu’il est presque impossible de les aligner?

voir la réponse sélectionnée pour ce message: Les variables de pile sont-elles alignées par le GCC __attribute __ ((aligné (x)) )?

(2) Le code pourrait-il être remanié pour le rendre plus efficace? Que se passe-t-il si je mets les deux tableaux flottants dans des registres plutôt qu’un seul?

Merci

Était-ce utile?

La solution

  

si je voulais aligner les tableaux sur des limites de 16 octets, cela fonctionnerait-il? Puisque les tableaux sont alloués sur la pile, est-il vrai qu’il est presque impossible de les aligner?

Il est nécessaire que l’alignement sur la pile fonctionne. Sinon, les éléments intrinsèques ne fonctionneraient pas. Je suppose que le message que vous avez cité concerne la valeur exorbitante qu'il a sélectionnée pour la valeur d'alignement.

à 2:

Non, il ne devrait pas y avoir de différence de performance. Consultez ce site pour connaître le minutage des instructions de plusieurs processeurs.

Fonctionnement de l'alignement des variables de pile:

push    ebp
mov ebp, esp
and esp, -16                ; fffffff0H
sub esp, 200                ; 000000c8H

Les et alignent le début de la pile sur 16 octets.

Autres conseils

Ecrivez-le en C, utilisez

gcc -S -mssse3

si vous avez une version assez récente de gcc.

  

(1) si je voulais aligner les tableaux sur des limites de 16 octets, cela fonctionnerait-il même? Puisque les tableaux sont alloués sur la pile, est-il vrai qu’il est presque impossible de les aligner?

Non, il est assez simple d'aligner le pointeur de pile en utilisant et :

and esp, 0xFFFFFFF0 ; aligned on a 16-byte boundary

Toutefois, vous devez utiliser les ressources fournies par GCC, telles qu'un type 16 octets ou un __ attribut __ pour personnaliser l'alignement.

GCC prend-il en charge le type de données __ m128 ? Si tel est le cas, c'est votre meilleur plan pour garantir un type de données aligné sur 16 octets. Néanmoins, __ attribut __ ((aligné (16))) permet d’aligner des éléments. Définissez vos tableaux comme suit

float a[4] __attribute__((aligned(16))) = { 10, 20, 30, 40 };
float b[4] __attribute__((aligned(16))) = { 0.1, 0.1, 0.1, 0.1 };

puis utilisez movaps à la place:)

L'utilisation intrinsèque est beaucoup plus rapide, en particulier avec l'optimisation. J'ai écrit un test simple et comparer les deux versions (asm et intrinsèque)

unsigned long long time1;
__m128 a1,b1;


a1=_mm_set_ps(10, 20,30,40);
b1=_mm_set_ps(0.1, 0.1, 0.1, 0.1);
float a[4] = { 10, 20, 30, 40 };
float b[4] = { 0.1, 0.1, 0.1, 0.1 };

time1=__rdtsc();
a1=_mm_mul_ps(a1,b1);
time1=__rdtsc() - time1 ;
printf("Time: %llu\n",time1);


time1=__rdtsc();
asm volatile("movups (%0), %%xmm0\n\t"
                 "mulps (%1), %%xmm0\n\t"
                 "movups %%xmm0, (%1)"
                 :: "r" (a), "r" (b));
time1=__rdtsc() - time1 ;
printf("Time: %llu\n",time1);

Horodatages de processeur version 50-60 intrinsèques Asm Version ~ 1000 timestamps proc

Vous pouvez le tester sur votre ordinateur

À propos du refactoring. Vous pouvez utiliser intrinsèque. Exemple:

#include <emmintrin.h>

int main(void)
{
    __m128 a1,b1;

    a1=_mm_set_ps(10, 20,30,40);
    b1=_mm_set_ps(0.1, 0.1, 0.1, 0.1);

    a1=_mm_mul_ps(a1,b1);

    return 0;
}

Avec l'optimisation gcc ( -O2 , -O3 ), il est possible que le travail soit plus rapide que l'ASM.

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