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

Langage Java Discussion :

Conversion d'un byte[] vers un int[]


Sujet :

Langage Java

  1. #1
    Membre habitué Avatar de ludosoft
    Homme Profil pro
    Chef de projet technique
    Inscrit en
    Juillet 2002
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2002
    Messages : 99
    Points : 136
    Points
    136
    Par défaut Conversion d'un byte[] vers un int[]
    Bonjour,
    J'ai un affreux problème pour lequel l'ami Google n'a pas de solution...

    Voilà, j'ai un tableau de "byte" dont le nombre de cases est toujours un multiple de 4. Je voudrais transformer ce tableau en tableau de "int" (d'où l'histoire du multiple de 4). En gros l'idée est de regrouper les octets 4 à 4 pour former des "int".

    Voici un code, très naïf, qui fait à peu près ce que je veux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    byte a[]={1,2,3,4,5,6,7,8};
    int b[]=new int[2];
    for(int i=0;i<a.length;i+=4)
     b[i/4]=(a[i]<<24)+(a[i+1]<<16)+(a[i+2]<<8)+a[i+3];
    Par contre question performance, c'est vraiment pas ça du tout. Je suis donc à la recherche d'une solution plus propre sans passer par du C natif.

    Auriez-vous une idée ? Merci beaucoup d'avance !

    PS : pour info j'aurais codé ça comme ça en C :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char a[]={1,2,3,4,5,6,7,8};
    int b[2];
    memcpy(b,a,sizeof(a));

  2. #2
    Membre chevronné
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    1 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 348
    Points : 1 787
    Points
    1 787
    Par défaut
    Humm ... Pas simple là. C'est vraiment si mauvais que ça en perfos ?
    La seule petite optim que je vois et encore serait de faire des ou binaires au lieu de tes +, ça doit aller plus vite je pense. Mais je doute que tu gagnes vraiment beaucoup.

    Question bête : comment tu mesures ta perfo là dessus ?

  3. #3
    Membre habitué Avatar de ludosoft
    Homme Profil pro
    Chef de projet technique
    Inscrit en
    Juillet 2002
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2002
    Messages : 99
    Points : 136
    Points
    136
    Par défaut
    Merci pour ta réponse !

    La mesure est en fait très rudimentaire. Ce bout de code doit être intégré dans un processus de traitement du type :

    - Lire un tableau de n*4 byte
    - Instancier un tableau de n int
    - "Copier" le byte[] dans le int[]
    - Exploiter le int[]

    Dans mon appli, ce petit algo est itéré 175 fois avec n=1920. En mettant en commentaire la ligne "Copier le byte[] dans le int[]", le temps d'exécution perceptible se trouve grandement modifié (en gros un facteur de 10). Le temps d'exécution étant de l'ordre de quelques secondes.

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,
    Citation Envoyé par ludosoft
    La mesure est en fait très rudimentaire.
    Il est long ton code ? Parce que ce serait bien que tu nous le donne pour déterminer l'origine du problème...

    a++

  5. #5
    Membre chevronné
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    1 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 348
    Points : 1 787
    Points
    1 787
    Par défaut
    Assez d'accord. Si le code est petit, ça serait pas mal que tu le mettes ici, parce que j'avoue être étonné que ce soit si lent ...

  6. #6
    Membre habitué Avatar de ludosoft
    Homme Profil pro
    Chef de projet technique
    Inscrit en
    Juillet 2002
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2002
    Messages : 99
    Points : 136
    Points
    136
    Par défaut
    Voici le code. Il s'agit là de traiter un flux d'images à la volée.

    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
     
    BufferedInputStream reader=new BufferedInputStream(fluxDecodeur.in);
    BufferedOutputStream writer=new BufferedOutputStream(fluxEncodeur.out);
     
    byte[] buffer=new byte[160*120*4];
    int[] rgbaData=new int[160*120];
     
    try{
    	while(true){
    		int taille=reader.read(buffer);
    		if(taille<=0)break;
     
    		////////////////////////////////////////////////
    		//La fameuse conversion du byte[] en int[]
    		int j;
    		int nombreDeInt=taille>>2;
    		for(int i=0;i<nombreDeInt;i++){
    			j=i<<2;
    			rgbaData[i]=(buffer[j]<<24)|(buffer[j+1]<<16)|(buffer[j+2]<<8)|buffer[j+3];
    		}
    		////////////////////////////////////////////////
     
     
    		////////////////////////////////////////////////
    		//Traitement de l'image (le corps de cette fonction est vide pour le moment)
    		////////////////////////////////////////////////
    		bricolerImage(160,120,rgbaData);
     
     
    		////////////////////////////////////////////////
    		//Opération inverse pas encore implémentée (rgbaData[] vers buffer[])
    		////////////////////////////////////////////////
     
     
    		writer.write(buffer,0,taille);
    	}
    }finally{
    	reader.close();
    	writer.flush();
    	writer.close();
    }
    Il est clair que j'aurais pu utiliser la fonction "readInt" de la classe "DataInputStream" mais il est impossible ici aussi de se passer d'un "for".
    Reste que la globalité du traitement reste moins performante qu'avec un bon vieux "memcpy".

    Notez aussi que j'ai modifié la portion de code en fonction des remarques de chtig ce qui a permis d'améliorer les performances.

  7. #7
    Membre habitué Avatar de ludosoft
    Homme Profil pro
    Chef de projet technique
    Inscrit en
    Juillet 2002
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2002
    Messages : 99
    Points : 136
    Points
    136
    Par défaut
    Voici une variante du même code, utilisant DataInputStream et DataOutputStream. On remarque le que code est bien plus élégant mais question performance c'est très mauvais : 12s de temps d'exécution contre 1s avec le code que j'ai posté juste avant...
    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
     
    int[] rgbaData=new int[160*120];
    DataInputStream reader=new DataInputStream(fluxDecodeur.in);
    DataOutputStream writer=new DataOutputStream(fluxEncodeur.out);
     
    try{
    	int taille;
    	while(true){
     
    		for(int i=0;i<rgbaData.length;i++)
    			rgbaData[i]=reader.readInt();
     
    		bricolerImage(160,120,rgbaData);
     
    		for(int i=0;i<rgbaData.length;i++)
    			writer.writeInt(rgbaData[i]);
    	}
    }finally{
    	reader.close();
    	writer.flush();
    	writer.close();
    }

  8. #8
    Membre habitué Avatar de ludosoft
    Homme Profil pro
    Chef de projet technique
    Inscrit en
    Juillet 2002
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2002
    Messages : 99
    Points : 136
    Points
    136
    Par défaut
    Encore une remarque.

    Vous aurez sans doute remarqué le "while(true)". A cause de ça j'ai effectué tous mes tests en mode debug. Or, en mode d'exécution "normal", tout va infiniment plus vite !
    J'ai fait plusieurs tests, c'est bien le mode debug qui me ralanti tout. Pour infos, je suis sur Netbeans 5.5 / java6.

    Ce qui est marrant c'est que l'implémentation "à la main" du "readInt" ne génère pas cette lenteur...

    Enfin pour recentrer le débat, la question initiale était aussi de savoir si java avait un équivalent de "memcpy". En fait ce serait un genre de super "System.arraycopy" qui accepterait en paramètre 2 tableaux de type différents mais de taille mémoire égale.

    J'admets qu'en java s'est une grosse ânerie de vouloir copier "binairment" un tableau de classe x[] dans un tableau de classe y[] mais j'avais un espoir concernant les tableaux de types primitifs...

  9. #9
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ludosoft
    J'admets qu'en java s'est une grosse ânerie de vouloir copier "binairment" un tableau de classe x[] dans un tableau de classe y[] mais j'avais un espoir concernant les tableaux de types primitifs...
    Il me semble, mais je n'en suis pas sûr à 100%, que les types primitifs peuvent être représenté de différentes manières selon la JVM et/ou le système d'exploitation hôte... du coup une tel méthode pourrait poser beaucoup de problème...

    a++

  10. #10
    Membre chevronné
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    1 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 348
    Points : 1 787
    Points
    1 787
    Par défaut
    J'ai aussi le même souvenir, même si je serais malheureusement incapable de pointer un article traitant de cela.
    En tout cas, je n'ai pas connaissance d'une quelconque API permettant de faire ce genre de copie mémoire en Java...
    Donc finalement, sans le mode debug tu arrives à une perfo correcte ?

  11. #11
    Membre habitué Avatar de ludosoft
    Homme Profil pro
    Chef de projet technique
    Inscrit en
    Juillet 2002
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chef de projet technique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2002
    Messages : 99
    Points : 136
    Points
    136
    Par défaut
    Oui c'est impec comme ça ! Le code retenu est donc le dernier que j'ai posté, faisant appel un maximum à l'outillage standard de Java. A utiliser en mode "non debug" (du moins NetBeans) pour ne pas souffrir de lenteur.

    En tout cas pour votre aide !

    a+

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

Discussions similaires

  1. Byte[4] vers un int, et vice-versa
    Par anubis_1001 dans le forum Langage
    Réponses: 2
    Dernier message: 14/05/2010, 11h04
  2. Conversion 4 bytes vers float
    Par morgan_2956 dans le forum C#
    Réponses: 3
    Dernier message: 10/03/2010, 09h33
  3. conversion de byte vers string
    Par dalilnet dans le forum Langage
    Réponses: 5
    Dernier message: 18/07/2008, 15h05
  4. Conversion byte vers réel en Delphi7
    Par delphino7 dans le forum Langage
    Réponses: 3
    Dernier message: 03/05/2008, 15h25
  5. conversion Byte[] vers int
    Par skud dans le forum C#
    Réponses: 5
    Dernier message: 17/05/2007, 12h14

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