PDA

Visualizza la versione completa : [C/C++] Esecuzione dello stesso codice Linux VS Windows


pippoplutoasd
18-05-2012, 17:21
Ciao a tutti!!
Mi sono imbattuto in quello che per me un "mistero"...vi spiego: ho scritto un programma in C/C++ che legge un'immagine in un file bitmap e la riscrive in un altro file bitmap. Ho compilato questo programma sia in windows ( Xp professional ) con Visual Studio C++ Express sia in linux ( Ubuntu 12.04 ) con Geany 0.21. La macchina su cui viene eseguito il codice la stessa.Vi posto il codice che viene compilato con Geany 0.21 ( quello che viene compilato con Visual Studio leggermente diverso, quello che cambia il modo di gestire il timer del computer per vedere il tempo di esecuzione del programma; per windows ho usato la funzione clock() ).

[CODE]//Programma che legge l'immagine da un file scelto dall'utente e la ricopia in un file chiamato 'copia.bmp'
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <sys/time.h>

using namespace std;

#pragma pack(1)
struct PIXEL
{
unsigned int b;
unsigned int g;
unsigned int r;
PIXEL *succ;
};
#pragma pack()

typedef PIXEL* rgb;

int main()
{
timeval start,stop; //dichiaro le variabili di tempo
double trascorsi;

rgb inizio=NULL;
rgb nuovo=NULL;
rgb ultimo=NULL;
rgb bin=NULL; //puntatore per eliminazione elemento di lista
FILE *imm = NULL;
FILE *ris = NULL;
long int i=0;
long int z=0;
long int j=0;
long int x=0;
int trash;
long int height;
long int width;
long int image_size=0;
char nome_file[30];
char padding;
cout<<"Inserisci il nome dell'immagine: ";
cin.getline(nome_file,30);
imm = fopen(nome_file, "rt");
ris = fopen("copia.bmp", "wb");
cout<<"Dimmi la larghezza dell'immagine:";
cin>>width;
cout<<endl<<"Dimmi l'altezza dell'immagine:";
cin>>height;
image_size=width*height*3 + ((width%4)*height) +54;
if(imm==NULL)
{
cout<<"Errore nell'apertura del file immagine."<<endl;
}
else if(ris==NULL)
{
cout<<"Errore nell'apertura del file immagine."<<endl;
}
else
{
cout<<"Apertura del file immagine avvenuta."<<endl;
cout<<"La grandezza effettiva dell'immagine e' "<<image_size<<endl;
cout<<"Ma la matrice di interesse e' "<<width*height*3<< "pixels"<<endl;
i=0;
cout<<"Inizio acquisizione header... ";
while(i<54) //Elimina i primi 54 bytes dal file relativi all'header
{
trash=fgetc(imm);
fwrite (&trash, sizeof(char), 1, ris);
i++;
}
cout<<"Fatto!"<<endl;
cout<<"L'header e' stato scritto nel nuovo file."<<endl;
ultimo=inizio;
cout<<"Inizio acquisizione del corpo dell'immagine... ";
while(z<height)
{
j=0;
while(j<width)
{

nuovo=new PIXEL;
nuovo->r=fgetc(imm);
nuovo->g=fgetc(imm);
nuovo->b=fgetc(imm);

nuovo->succ=NULL;
if(ultimo==NULL)
{
inizio=nuovo;
}
else
{
ultimo->succ=nuovo;
}
ultimo=nuovo;
j++;
nuovo=NULL;
}
for(i=0;i<(width%4);i++)
{
trash=fgetc(imm); //Elimina i bytes di padding per ogni riga
}
z++;
}
cout<<"Fatto!"<<endl;

nuovo=inizio;

cout<<"Inizio scrittura della nuova immagine sul file 'copia.bmp'... ";
gettimeofday(&start,NULL); //acquisisco il tempo
while(nuovo!=NULL) //scrittura nuova immagine
{


fwrite(&(nuovo->r),sizeof(char),1,ris); //stampiamo i 3 bytes relativi al pixel
fwrite(&(nuovo->g),sizeof(char),1,ris);
fwrite(&(nuovo->b),sizeof(char),1,ris);

if(((width%4)!=0)&&(x==(width-1)))
{
for(j=0;j<(width%4);j++)
{
fwrite(&padding,sizeof(char),1,ris); //scrivo il pixel di padding width%4 volte
}
x=0;
}
else
{
x++;
}
bin=nuovo;
nuovo=nuovo->succ; //sposto il puntatore al successivo pixel
delete bin;

i++;
}
cout<<"Fatto!"<<endl;

cout<<"i: "<<i<<endl;
cout<<"x: "<<x<<endl;
}

fclose(imm); //chiudo i 2 file
fclose(ris);

gettimeofday(&stop,NULL);
trascorsi = (stop.tv_sec - start.tv_sec) * 1000000; //secondi to micro
trascorsi += abs((stop.tv_usec - start.tv_usec)); //microsecondi
printf("Tempo di esecuzione totale: %f secondi.",(trascorsi/1000000));

return 0;
}

Il problema questo: in linux il tempo di esecuzione di questo programma ( come tempo di esecuzione in questo caso intendo solo la parte di scrittura dell'immagine nel nuovo file 'copia.bmp' ) di 0.17-0.18 secondi. In windows, invece, il tempo di esecuzione 17-18 secondi. Da cosa dipende questo? Dal sistema operativo o dal compilatore?

Scara95
18-05-2012, 17:31
Geany non un compilatore (come d'altra parte non lo visual c++), in ogni caso che linux sia pi performante di windows non un mistero, tuttavia non dipende solo dall'os ma anche dal compilatore e probabilmente anche dal fatto che (quasi con certezza) il tuo programma in windows stato compilato in codice CLI e non in codice macchina, rendendo il programma meno performante...

oregon
18-05-2012, 17:40
Non penso proprio che ci possa essere una differenza di questa portata (0.17 e 17 secondi).

Prima di parlare di differenze di prestazioni tra OS e compilatori, si dovrebbe capire come misuri il tempo con Windows (ovvero vedere effettivamente il codice che hai usato con Windows).

Bisognerebbe anche capire quali ottimizzazioni hai usato per l'uno e l'altro (hai compilato in Debug o Release con VC++?) e solo dopo tirare le somme.

Anche se hai compilato con VC.NET le differenze dei tempi mi sembrano eccessive.

Scara95
18-05-2012, 18:17
Originariamente inviato da oregon
Non penso proprio che ci possa essere una differenza di questa portata (0.17 e 17 secondi).

Prima di parlare di differenze di prestazioni tra OS e compilatori, si dovrebbe capire come misuri il tempo con Windows (ovvero vedere effettivamente il codice che hai usato con Windows).

Bisognerebbe anche capire quali ottimizzazioni hai usato per l'uno e l'altro (hai compilato in Debug o Release con VC++?) e solo dopo tirare le somme.

Anche se hai compilato con VC.NET le differenze dei tempi mi sembrano eccessive.

Ha ragione, infatti la mia era una risposta sommaria.

ESSE-EFFE
18-05-2012, 18:26
Originariamente inviato da pippoplutoasd
per windows ho usato la funzione clock() ).

Hai diviso il risultato finale per CLK_TCK (CLOCKS_PER_SEC), vero?

pippoplutoasd
18-05-2012, 18:32
Scusate la mia ignoranza sulla terminologia grazie della correzione. Tra l'altro ho anche scritto male il codice...ho fatto l'anteprima per vedere come si vedeva ma penso che, sbadatamente, ho cliccato su invia. Un'altra cosa che mi sono dimenticato prima che l'immagine su cui ho fatto la prova 1113x1118 pixels.


//Programma windows sistema operativo XP Professional IDE visual studio C++ 2010 Express
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
struct PIXEL
{
unsigned int b;
unsigned int g;
unsigned int r;
PIXEL *succ;
};
typedef PIXEL* rgb;
int _tmain(int argc, _TCHAR* argv[])
{
clock_t start,end;
double diff;
rgb inizio=NULL;
rgb nuovo=NULL;
rgb ultimo=NULL;
rgb bin=NULL;
FILE *imm = NULL;
FILE *ris = NULL;
long int i=0;
long int z=0;
long int j=0;
long int x=0;
int trash;
long int height;
long int width;
long int image_size=0;
char nome_file[30];
char r,g,b;
char padding;
cout<<"Inserisci il nome dell'immagine:";
cin.getline(nome_file,30);
imm = fopen(nome_file, "rt");
ris = fopen("copia.bmp", "wb");
cout<<"Dimmi la larghezza dell'immagine:";
cin>>width;
cout<<"Dimmi l'altezza dell'immagine:";
cin>>height;
image_size=width*height*3 + ((width%4)*height) +54;
if(imm==NULL)
{
cout<<"Errore nell'apertura del file immagine."<<endl;
}
else if(ris==NULL)
{
cout<<"Errore nell'apertura del file immagine."<<endl;
}
else
{
cout<<"Apertura del file immagine avvenuta."<<endl;
cout<<"La grandezza effettiva dell'immagine e' "<<image_size<<endl;
cout<<"Ma la matrice di interesse e' "<<width*height*3<< "pixels"<<endl;
i=0;
cout<<"Inizio acquisizione header... ";
while(i<54) //Elimina i primi 54 bytes dal file relativi all'header
{
trash=fgetc(imm);
fwrite (&trash, sizeof(char), 1, ris);
i++;
}
cout<<"Fatto!"<<endl;
cout<<"L'header e' stato scritto nel nuovo file."<<endl;
ultimo=inizio;
cout<<"Inizio acquisizione del corpo dell'immagine... ";
while(z<height)
{
j=0;
while(j<width)
{
nuovo=new PIXEL;
nuovo->r=fgetc(imm);
nuovo->g=fgetc(imm);
nuovo->b=fgetc(imm);
nuovo->succ=NULL;
if(ultimo==NULL)
{
inizio=nuovo;
}
else
{
ultimo->succ=nuovo;
}
ultimo=nuovo;
j++;
nuovo=NULL;
}
for(i=0;i<(width%4);i++)
{
trash=fgetc(imm); //Elimina i bytes di padding per ogni riga
}
z++;
}
cout<<"Fatto!"<<endl;
nuovo=inizio;
//x parte da zero
cout<<"Inizio scrittura della nuova immagine sul file 'copia.bmp'... ";
start=clock(); //da qui prendo inzia il conteggio
while(nuovo!=NULL) //scrittura nuova immagine
{
fwrite(&(nuovo->r),sizeof(char),1,ris); //stampiamo i 3 bytes relativi al pixel
fwrite(&(nuovo->g),sizeof(char),1,ris);
fwrite(&(nuovo->b),sizeof(char),1,ris);

if(((width%4)!=0)&&(x==(width-1)))
{
for(j=0;j<(width%4);j++)
{
fwrite(&padding,sizeof(char),1,ris); //scrivo il pixel di padding width%4 volte
}
x=0;
}
else
{
x++;
}
bin=nuovo;
nuovo=nuovo->succ; //sposto il puntatore al successivo pixel
delete bin;
i++;
}
cout<<"Fatto!"<<endl;
end=clock(); //qui finisce il conteggio
diff=((double)(end-start))/CLOCKS_PER_SEC;
cout<<"Tempo di esecuzione per la scrittura dell'immagine "<<diff<<" secondi"<<endl;
cout<<"i: "<<i<<endl;
cout<<"x: "<<x<<endl;
}
fclose(imm); //chiudo i 2 file
fclose(ris);
system("PAUSE");
return 0;
}

Compilando in Release e il tempo di esecuzione 17.812 secondi, mentre compilando in Debug il tempo di esecuzione 18.39

ESSE-EFFE
18-05-2012, 18:44
Originariamente inviato da pippoplutoasd
Compilando in Release e il tempo di esecuzione 17.812 secondi, mentre compilando in Debug il tempo di esecuzione 18.39
Cio scusa hai gli stessi tempi di prima anche se ora dividi per CLOCKS_PER_SEC? O lo facevi gi prima?

Scara95
18-05-2012, 18:51
Per me colpa della macchina virtuale v.v
Oltre ad eventuali flag di ottimizzazione diverse...

pippoplutoasd
18-05-2012, 18:55
Scusate se non l'ho scritto ma avevo fatto anche prima quella divisione. Secondo me non un problema di precisione del risultato finale. Ho notato che ,anche cronometrando il tempo grossolanamente da spettatore, su Ubuntu ci mette un attimo a scrivere l'immagine ( appena premo invio mi da subito i risultati ) mentre su Windows devo aspettare quei 17-18 secondi.

shodan
18-05-2012, 18:57
Immagine 1280 * 1024 (3841KB) processata in 0.61 secondi. Modalit release. Windows 7 nativo.
Tra l'altro c' una imprecisione:


imm = fopen(nome_file, "rt"); /* rb, non rt */

Loading