IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Multiplication registres SSE


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2009
    Messages : 52
    Points : 33
    Points
    33
    Par défaut Multiplication registres SSE
    Bonjour,

    Je suis en train de tester plusieurs instructions sse2, je me base sur la documentation MSDN (http://msdn.microsoft.com/en-us/libr...(v=vs.80).aspx).

    J'utilise VS2008 et mon programme est une application win32.

    J'essaie de multiplié un vecteur d'octet par un scalaire (un tableau de char par un int), j'ai dû faire d'autre manip auparavant (unpacke et package) dans le but de transformé mes octets(char) en short qui va me permettre de faire la multiplication (en fait je dois faire une addition avec un double que je transforme en short en le multipliant par 64).

    Bref, tout compile parfaitement et tout s'éxècute sans bug, le problème est que lorsque j'essaie d'afficher les valeurs du tableau une fois le traitement fait et bien rien ne s'affiche (que du vide).

    J'ai testé sans la multiplication et les valeurs du tableau s'affiche, il y a donc un problème au niveau de ma multiplication.

    Voici mon code (je pense que cela sera beaucoup plus clair avec):

    le source:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    #include "test_sse.h"
     
    int main()
    {
    	int wait=0;
    	char test[16]={24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54};
     
    	for(int i=0;i<16;i++)
    	{
    		cout << test[i] << endl;
    	}
    	cout << "==========================" << endl;
     
    	CalculSSE(test,1,1.2);
     
     
    	for(int j=0;j<16;j++)
    	{
    		cout << test[j] << endl;
    	}
    	cin >> wait;
    	return 0;
    }
     
     
    char* CalculSSE(char* test,int brillance,double contraste)
    {
    		//cast de l'image et load
    		__m128i* pImg=(__m128i*)test;
    		__m128i PxH;
    		__m128i PxL;
    		PxH= _mm_loadu_si128(pImg);
    		PxL= _mm_loadu_si128(pImg);
     
    		//Initialisation constante
    		__m128i ZeroReg= _mm_setzero_si128();
    		__m128i BrillanceReg= _mm_set1_epi16((short)brillance);
    		__m128i ContrasteReg= _mm_set1_epi16((short)(contraste*64));
     
    		//UNPACK
    		PxH=_mm_unpackhi_epi8(PxH,ZeroReg);
    		PxL=_mm_unpacklo_epi8(PxL,ZeroReg);
    		//Multiplication brillance
    		PxH=_mm_mulhi_epu16(PxH,BrillanceReg);
    		PxL=_mm_mulhi_epu16(PxL,BrillanceReg);
     
    		PxH=_mm_packus_epi16(PxL,PxH);
     
     
    		_mm_storeu_si128(pImg,PxH);
     
    		test=(char*)pImg;
    		return test;
    }
    Le headeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <iostream>
    #include <opencv\cv.h>
    #include <opencv\highgui.h>
    #include <xmmintrin.h>
     
    using namespace cv;
    using namespace std;
     
    char* CalculSSE(char* test,int brillance,double contraste);
    en espérant que vous puissiez m'aider,

    P.S: Vous remarquerez que le but final et de faire un traitement d'image en passant par les registres SSE (qui est normalement censé être plus rapide que le traitement standard).

    Cordialement,

    sushis

  2. #2
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    cout << char affiche le caractere non la valeur

    cout << (int)(test[i]) << endl;

    me parait mieux.

    Ensuite si tu veux des perfs, mieux vaut aligner ta memoire et utiliser load/store plutot que loadu/storeu.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2009
    Messages : 52
    Points : 33
    Points
    33
    Par défaut
    Merci bien j'ai pas du tout pensé au cast...

    Bref, ça m'affiche que des zéros, pourtant sans la multiplication les valeurs du tableau reste inchangé et dans l'ordre une fois la manip faite (unpack/pack).

    EDIT: l'utilisation de load et store fait planté le programme!

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2009
    Messages : 52
    Points : 33
    Points
    33
    Par défaut
    up!

    Je me suis en me relisant je me suis peut-être mal expliqué.

    La valeur de la variable brillance vaut 1 dans mon test, normalement le tableau lors de son deuxième affichage (donc après avoir effectué les multiplication) est censé affiché la même chose or ça n'est pas le cas il n'affiche que des zéro...

  5. #5
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par sushis Voir le message
    Bref, ça m'affiche que des zéros, pourtant sans la multiplication les valeurs du tableau reste inchangé et dans l'ordre une fois la manip faite (unpack/pack).
    tes unpack sont faux alors ?

    Citation Envoyé par sushis Voir le message
    l'utilisation de load et store fait planté le programme!
    oui, j'ai dis qu'il fallait aligner la memoire

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2009
    Messages : 52
    Points : 33
    Points
    33
    Par défaut
    Et bien je ne sais pas si met unpack sont faux.

    Tout fonctionne quand je n'utilise pas les instructions de multiplication.

    Je pensais que ma mémoire était aligné "automatiquement" en utilisant cette
    fonction, je devrais faire ça dés la déclaration de mon tableau?

    Je ne comprend pas très bien...

    Enfin bref, on m'a dit d'utiliser les autre fonctions, le plus important pour moi et de faire fonctionner correctement la multiplication.

    Alors il aurait un problème au niveau des unpack?

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par sushis Voir le message
    Je pensais que ma mémoire était aligné "automatiquement" en utilisant cette
    fonction, je devrais faire ça dés la déclaration de mon tableau?
    Non - il faut utiliser des types spéciaux alignés (__m128, __m128i, __m128d, comme tu le fais) ou aligner de manière explicite un type utilisateur (avec __declspec(align(16)) : cf http://msdn.microsoft.com/en-us/library/83ythb65.aspx), ou allouer une zone mémoire alignée.

    Pour ce dernier point, il existe plusieurs techniques :
    • utiliser _aligned_malloc() (http://msdn.microsoft.com/en-us/library/8z34s9c6.aspx). malloc() et l'opérateur new ne sont pas suffisant.
    • Utiliser p = new char[](taille + 16) (ou malloc), et incrémenter p de manière à ce que (p % 16) == 0 avant de l'utiliser. Ne pas oublier de garder quelque part l'adresse originale afin de pouvoir faire le delete correspondant.

    Un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    class aligned_buffer
    {
      char* m_buffer;
      char* m_aligned_buffer;
    public:
      aligned_buffer(std::size_t size)
        : m_buffer(new char[](size + 16)
      {
        m_aligned_buffer = m_buffer;
        m_aligned_buffer += (16 - (m_aligned_buffer % 16));
      }
      ~aligned_buffer()
      { delete m_buffer; }
      const char *ptr() const { return m_aligned_buffer; }
    };
    (Attention : ce n'est qu'on code d'exemple ; il n'est pas vraiment apte à passer dans votre code à vous, sauf si vous aimez les problèmes).

    Un pointeur sur une variable du type __m128i ne référence pas systématiquement une zone mémoire alignée (le fait d'affecter une valeur à un pointeur ne va pas aligner la mémoire de manière magique : il faut que tu aligne la mémoire toi-même, où que tu procèdes par loadu/storeu comme tu le fais à l'heure actuelle).

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2009
    Messages : 52
    Points : 33
    Points
    33
    Par défaut
    Je procéderai par loadu/storeu dans un premier temps. Si on me demande d'aligner la mémoire je le ferais.

    En ce qui concerne la multiplication de mes valeurs le problème viendrait-il vraiment du unpack?

    Pourtant tout fonctionne bien (si j'enlève les multiplication).

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2009
    Messages : 52
    Points : 33
    Points
    33
    Par défaut
    En fait, la fonction retourne les valeurs haute sur 32 bits de la multiplication donc forcément que des zéros puisque j'utilise du 16 bits.

    J'ai donc utilisé l'autre fonction: _mm_mullo_epi16 qui garde les valeurs basse et la multiplication fonctionne.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Ecriture registres multiples Modbus TCP
    Par Ashkandie dans le forum Réseau
    Réponses: 2
    Dernier message: 01/08/2012, 12h50
  2. Réponses: 0
    Dernier message: 19/10/2011, 15h05
  3. [SSE] Meilleur code pour "mirroir" (flip) d'un registre XMM
    Par BB_17 dans le forum x86 32-bits / 64-bits
    Réponses: 3
    Dernier message: 28/05/2009, 13h19
  4. [Windows]accès base de registre windows
    Par Greg01 dans le forum API standards et tierces
    Réponses: 27
    Dernier message: 05/06/2007, 16h14
  5. Réponses: 6
    Dernier message: 25/03/2002, 22h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo