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 :

Optimisation programme C


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 41
    Par défaut Optimisation programme C
    Bonjour,

    je viens de créer un programme en C qui diminue la taille d'une bitmap par 2 et la resize. Le problème c'est que je dois l'optimiser afin qu'il soit plus rapide. Je pensais utiliser les pointeurs mais je ne vois pas vraiment comment faire. Voici mon code:
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    #include <stdio.h>
    #include <stdlib.h> // malloc
    #include <string.h> // memset
    #include <stdint.h> // uintxx_t types
     
    #include "time_measure.h"
    #include "image_utils.h"
     
    int basic_data_processing(process_data_t * process_data);
     
     
    int init_process_data(process_data_t * process_data, int argc, const char * argv[]) {
    	int status = 0, read_fd = -1;
    	uint32_t i = 0;
    	uint32_t width=0, height=0;
     
    	if( process_data != NULL ) {
    		memset(process_data, 0, sizeof(process_data_t));
    		// affect processing function
    		process_data->data_processing_function = basic_data_processing;
     
    		switch( argc ) {
    			case 2:
    				// read BMP file
    				read_fd = open(argv[1], O_RDONLY
    #ifdef WIN32
    											 | O_BINARY
    #endif // WIN32
    											 );
    				if( read_fd != -1 ) {
    					status = read_bmp_header(read_fd, &process_data->source_header);
    					if( status != -1 ) {
    						switch( process_data->source_header.bits_per_pixel ) {
    							case 8 :
    								status = read_bmp_file_8(read_fd, &process_data->source_header, &process_data->source_bitmap);
    								if( status != -1 ) {
                                                                            width=process_data->source_header.width;
                                                                             height= process_data->source_header.height;
                                                                               printf("%d\n", height);
                                                                              printf("%d\n", width);
    									status = 0; // status may be positive at this point
    									// allocate and initialize destination bitmap
    									process_data->destination_bitmap = (uint8_t *) malloc((process_data->source_header.width/2) * (process_data->source_header.height/2) * sizeof(uint8_t));
    									if( process_data->destination_bitmap ) {
    										process_data->output_file_path = suffixed_filename(argv[1], " (reduced).bmp");
    									} else status = -2; // bitmap allocation issue
    								} else printf("BMP content read failed\n");
    								break;
    							default:
    								printf("\"%s\" : has %d bits per pixels only 8 bpp is supported\n", argv[1], process_data->source_header.bits_per_pixel);
    								break;
    						} // switch header.bits_per_pixel
    					} else printf("BMP header read failed\n");
    				} else printf("open file failed\n");
    				break;
    			default:
    				printf("usage : %s <output BMP file path>\n", argv[0]);
    				status = -3;
    				break;
    		}
    	} else status = -1; // parameter issue
     
    	return status;
    }
     
    /***************************Méthode Initiale*************************************/
    int basic_data_processing(process_data_t * process_data) {
     
    	uint32_t x = 0;
        uint32_t y = 0;
        int32_t pixel, pixel_droit, pixel_bas, pixel_diag, moyenne;
    	int status = 0;
    	uint32_t width=process_data->source_header.width, height= process_data->source_header.height;
    	uint8_t * source_pointer = NULL;
    	uint8_t * destination_pointer = NULL;
    	uint32_t counter = 0;
     
     
    	if( (process_data != NULL) && (process_data->source_bitmap != NULL) && (process_data->destination_bitmap != NULL) ) {
     
    		source_pointer = process_data->source_bitmap;
    		destination_pointer = process_data->destination_bitmap;
     
           for(y=0; y<height; y++){
                    	for(x=0; x<width; x++){
     
                                 pixel=source_pointer[x+y*width];
                                 pixel_droit=source_pointer[x+1+y*width];
        	                     pixel_bas=source_pointer[x+(y+1)*width];
        	                     pixel_diag=source_pointer[(x+1)+(y+1)*width];
     
                                 moyenne=(pixel+pixel_droit+pixel_bas+pixel_diag)/4;
     
                      if( destination_pointer != NULL ) {
     
                         destination_pointer[(x/2)+(y/2)*(width/2)] = moyenne;
     
                       }
                        x++;
                  }
                  y++;
            }
    	} else status = -1; // parameter issue
     
    	return status;
    }
     
     
    int dispose_process_data(process_data_t * process_data) {
    	int status = 0;
    	uint32_t width=process_data->source_header.width, height=process_data->source_header.height;
     
    	if( (process_data != NULL) ) {
    		if( process_data->source_bitmap != NULL ) {
    			free(process_data->source_bitmap);
    			process_data->source_bitmap = NULL;
    		}
    		if( process_data->destination_bitmap != NULL ) {
    			if( process_data->output_file_path ) {
    				// save bitmap in BMP format
    				process_data->source_header.width = width/2;
                    process_data->source_header.height=height/2;
     
    				save_bitmap(process_data->output_file_path, &process_data->source_header, process_data->destination_bitmap);
    			}
    			free(process_data->destination_bitmap);
    			process_data->destination_bitmap = NULL;
    		}
    	} else status = -1; // parameter issue
     
    	return status;
    }
    Si quelqu'un à des idées je serais ravi.

    Merci

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    329
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2004
    Messages : 329
    Par défaut
    Les pointeurs ça "n'optimise" pas, c'est juste un moyen d'exprimer des constructions, "optimiser" c'est d'abord de l'algorithmie, et ensuite une réflexion sur l'architecture visée (hérarchie de cache, blocking des boucles, ...). En tenant compte du fait que tes boucles une fois traitée par le compilateur ne ressemble plus du tout à ce que tu avais en entrée.

    Déjà je m'étonne du x++ et y++ ? Est-ce que le code est correct ?

  3. #3
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    comme ça au feeling j'aurais tendance à regarder à partir de la ligne 84 les deux boucles imbriquées, j'imagine que l'essentiel du traitement passe dedans

    pour le moins tu peux sans doute éviter le recalcul à chaque ligne de choses comme "y*width", "(y+1)*width" à l'aide de variables intermédiaires/temporaires
    l'emploi du type "register" pour x et y peut-être aussi, et ramener les divisions par 2 et par 4 respectivement à des décalages de 1 et 2 bits vers la droite

    quelque chose comme ça :

    Code c : 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
     
        register uint32 x=0,y=0,yw1=0,yw2=0;
     
        for(y=0; y<height; y++){
            yw1 = y*width;
            yw2 = yw1 + width; /* plutot que de refaire la multiplication (y+1)*width */
            for(x=0; x<width; x++){
                pixel=source_pointer[x+yw1];
                pixel_droit=source_pointer[x+1+yw1];
                pixel_bas=source_pointer[x+yw2];
                pixel_diag=source_pointer[x+1+yw2];
                moyenne=(pixel+pixel_droit+pixel_bas+pixel_diag) >> 2;
                if( destination_pointer != NULL ) {
                    destination_pointer[(x>>1)+(y>>1)*(width>>1)] = moyenne;
                }
                x++;
            }
            y++;
        }

    mais c'est possiblement que des "bouts de ficelles", à voir si ça suffit à faire une différence significative

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 41
    Par défaut
    Bonjour,

    Joker-eph, mes x++ et y++ me permettent de passer de 2 lignes en 2 lignes et 2 colonnes en 2 colonnes pour faire ma moyenne.

    Merci BufferBob, tes modifications me permettent diminuer légèrement mon temps d'exécution.

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Bonjour à toi!
    Citation Envoyé par flavdu44 Voir le message
    Bonjour,
    Joker-eph, mes x++ et y++ me permettent de passer de 2 lignes en 2 lignes et 2 colonnes en 2 colonnes pour faire ma moyenne.
    Pour ca, il suffit de mettre x+=2 dans l'instruction d'incrémentation de la boucle

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 41
    Par défaut
    Merci, cela ma encore permis d'améliorer mes performances.

    Je compte maintenant m'orienter vers des pointeur pour cette partie du code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     for(y=0; y<height; y+=2){
            yw1 = y*width;
            yw2 = yw1 + width; 
            for(x=0; x<width; x+=2){
                pixel=source_pointer[x+yw1];
                pixel_droit=source_pointer[x+1+yw1];
                pixel_bas=source_pointer[x+yw2];
                pixel_diag=source_pointer[x+1+yw2];
                moyenne=(pixel+pixel_droit+pixel_bas+pixel_diag) >> 2;
                    destination_pointer[(x>>1)+(y>>1)*(width>>1)] = moyenne;
            }  
        }
    J'ai essayer plusieurs trucs mai je n'arrive jamais à tomber sur les pixels que je veut.

  7. #7
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Dérivé de la dernière version de ton code (et sauf erreur)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for(y=0; y<height; y+=2){
           uint8_t * p1 = source_pointer+y*width;
           uint8_t * p2 = p1+ width;
           uint8_t * pd = destination_pointer + (y>>1)*(width>>1);
           for(x=0; x<width; x+=2){
                    pd[(x>>1)] = (p1[x]+p1[x+1]+p2[x]+p2[x+1]) >> 2;
           }  
     }

Discussions similaires

  1. Optimisation programme en C
    Par senuol dans le forum C
    Réponses: 11
    Dernier message: 18/05/2011, 18h01
  2. [Débutant] tableau pour optimiser programme
    Par membreComplexe12 dans le forum MATLAB
    Réponses: 2
    Dernier message: 15/03/2010, 10h03
  3. Optimisation programmation Interface
    Par christophe_halgand dans le forum Interfaces Graphiques
    Réponses: 1
    Dernier message: 28/02/2008, 18h49
  4. Optimisation programme ::
    Par scolopendra dans le forum Langage
    Réponses: 5
    Dernier message: 16/04/2007, 17h53
  5. Optimiser programme (D7)
    Par mario9 dans le forum Delphi
    Réponses: 2
    Dernier message: 18/08/2006, 17h36

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