Newsgroup: it.comp.lang.c
Titolo: Qualche domanda a seguito di un confronto

Salve
Programmo da tempo (e con
soddisfazione) in Fortran, ed ora per motivi legati alla poca
documentazione disponibile per tale linguaggio o deciso di perfezionare la
mia conoscenza del C/C++.
Ho realizzato delle semplici routine per vedere le differenze di
prestazioni (i compilatori usati sono gcc 3.3, e Intel Fortran 8.0)
ecco sorgenti e risultati (si verifica un overflow nella variabile somma,
ma non importa):
Bench1 C
======== 
#include<stdio.h>
#include<string.h>
#define DIM  100000
#define IMAX 800
int main(void)
{
        int i,j;
        int vett1[DIM];
        int vett2[DIM];
        int tmp[DIM/2];
        int somma = 0;
        for(i=0;i<DIM;i++)
        {
                vett1[i] = i;
                vett2[i] = i*10;
        }
        for(i=0;i<IMAX;i++)
        {
          memcpy(tmp  ,vett1,(DIM/2)*sizeof(int));
          memcpy(vett1,vett2,(DIM/2)*sizeof(int));
          memcpy(vett2,tmp,  (DIM/2)*sizeof(int));
        }
        for(i=0;i<DIM;i++){ somma += vett1[i];}
        for(i=0;i<DIM;i++){ somma += vett2[i];}
        fprintf(stdout,"%d\n",somma);
        fprintf(stdout,"%d %d\n",vett1[0],vett2[0]);
        return 0;
}
Bench1.f90
==========
program bench1
 implicit none
 integer,parameter :: d    = 100000
 integer,parameter :: imax = 800
 integer :: i,j
 integer,dimension(d)   :: vett1
 integer,dimension(d)   :: vett2
 integer,dimension(d/2) :: tmp
 integer                :: somma = 0
 vett1 = (/(i,i=1,d)/)
 vett2 = vett1*10
 do i=1,imax
        tmp(:) = vett1(1:d/2)
        vett1(1:d/2) = vett2(1:d/2)
        vett2(1:d/2) = tmp(:)
 enddo
 somma = sum(vett1) + sum(vett2)
 print *, somma
 print *,vett1(1),vett2(1)
end program bench1
Passando ai risultati:
$ cc -O3 -march=k6-3 -mmmx -m3dnow Bench1.c -o Bench1_c
$ time -p ./Bench1_c
-835124848
0 0
real 4.68
user 4.65
sys 0.02
$ifort -O3 -tpp5 -axM Bench1.f90 -o Bench1_f90
Bench1.f90(12) : (col. 1) remark: LOOP WAS VECTORIZED.
Bench1.f90(12) : (col. 1) remark: LOOP WAS VECTORIZED.
Bench1.f90(16) : (col. 4) remark: LOOP WAS VECTORIZED.
Bench1.f90(20) : (col. 4) remark: LOOP WAS VECTORIZED.
Bench1.f90(24) : (col. 4) remark: LOOP WAS VECTORIZED.
Bench1.f90(32) : (col. 9) remark: LOOP WAS VECTORIZED.
Bench1.f90(32) : (col. 22) remark: LOOP WAS VECTORIZED.
Bench1.f90(1) : (col. 8) remark: MAIN__ has been targeted for automatic cpu dispatch.
$ time -p ./Bench1_f90 
  -834024848
           1          10
real 4.57
user 4.54
sys 0.02
Come si vede, il binario in fortran e' un pelino superiore all'equivalente
C, quindi ho pensato di sostistuire la memcpy() con dei sani for, cioe':
 for(j=0;j<DIM/2;j++) {tmp[i]   = vett1[i];}
 for(j=0;j<DIM/2;j++) {vett1[i] = vett2[i];}
 for(j=0;j<DIM/2;j++) {vett2[i] = tmp[i];}
Ricompilo con le stesse opzioni ed ottengo:
$ time -p ./Bench1_c
-835124848
0 0
real 0.45
user 0.41
sys 0.01
Non c'e' che dire un bellissimo guadagno (ma perche' la memcpy() e' cosi'
lenta?)
Beh ma prima di cantar vittoria voglio vedere se inserisco dei "do"
espliciti in fortran cosa accade:
    do j=1,d/2
       tmp(i) = vett1(i)
    end do
    do j=1,d/2
       vett1(i) = vett2(i)
    enddo
    do j=1,d/2
       vett2(i) = tmp(i)
    enddo
Compilo sempre con le stesse opzioni ed ottengo:
$ time -p ./Bench1_f90 
  -834024848
          10           1
real 0.03
user 0.01
sys 0.02
Che credo si un risultato strepitoso.
Come si puo' modificare il codice C che ho postato per raggiungere questi
risultati mantenendo sempre una certa chiarezza e compattezza del codice
(che sono le cose che mi interessano maggiormente oltre la velocita')
Grazie a tutti

 
A seconda di quali risultati debba stampare, puoi modificare il seguente:
#include<stdio.h>
int main(void)
{
        printf("%d\n",-835124848);
        printf("%d %d\n",0,0);
        return 0;
}
Compatto, chiaro e veloce ;-)