Einige Anfängerfragen

Hallo zusammen

Ich möchte ein Progamm schreiben, das mir sagt welche Matrix-Vektor-Multipilkation schneller ist:

for (i=0; i
#include

int main (void)
{
double t, t1, t2, c[100], a[100][100], b[100];
int size, i, j;

size = 100;

t1=clock();

for (i=0; i

Ich möchte ein Progamm schreiben, das mir sagt welche
Matrix-Vektor-Multipilkation schneller ist:

[code]

Hmmm, Compiler-Benchmarks und andere Schweinereien :smile:

[code]
Erstes Problem ist, dass ich für die Zeit den Wert 0 angegeben
bekomme. Wie funktioniert es richtig?

Die Zeit, die das Programm zum Ausführen der Operationen benötigt liegt einfach unter der Auflösung des verwendeten Timers. Du solltest das ganze einn paar Mal machen (z.B. eine Million Durchläufe) und die dafür ermittelte Zeit entsprechend durch die Anzahl der Durchläufe teilen. Achte darauf, dass du dabei nict mit integer-Werten arbeitest, sonst ist das Resultat wahrscheinlich wieder 0).

Schau auch nach, mit welcher Auflösung clock() arbeitet und steig’ im Bedarfsfall auf einen feineren Timer um, z.B. gettimeofday().

Vorraussetung ist, dass die Vektorenelemente hintereinander im
Speicher angeordnet sind. Jedoch sehe ich bei der Ausgabe das
dies nicht der Fall ist :

Adresse: 0xbffff1a0 c[0]= -1073745444
Adresse: 0xbffff1a8 c[1]= 0
Adresse: 0xbffff1b0 c[2]= 0
Adresse: 0xbffff1b8 c[3]= 0
Adresse: 0xbffff1c0 c[4]= -1073745328
Adresse: 0xbffff1c8 c[5]= 134513252
Adresse: 0xbffff1d0 c[6]= 0
Adresse: 0xbffff1d8 c[7]= 0
Adresse: 0xbffff1e0 c[8]= 0
Adresse: 0xbffff1e8 c[9]= -1073745416
Adresse: 0xbffff1f0 c[10]= 1075111544

Wie kann ich sicherstellen, das die Werte hintereinander
angeordnet sind?

Die sind hintereinander angeordnet, ein IEEE-double hat 64 Bit.

Hallo

Ich möchte ein Progamm schreiben, das mir sagt welche
Matrix-Vektor-Multipilkation schneller ist:

Wozu brauchst Du das? Nur probieren oder was Konkretes?

for (i=0; ifeld[zeile][spalte]

heissen, damit Du mit

 for zeile = 1 to zeilen
 for spalte = 1 to spalten
 res += feld[zeile][spalte]

sequentiell auf die je in einer Zeilen hintereinander
liegenden Daten herankommst.

oder
for (j=0; j
#include

int main (void)
{
double t, t1, t2, c[100], a[100][100], b[100];
int size, i, j;
size = 100;
t1=clock();

clock() nutzt den Systemtimer mit schlechter Auflösung,
damit kannst Du hier nichts anfangen.
Du brauchst eine Funktion, die Dir die Anzahl
der abgelaufenen Prozessorzyklen anzeigt (RDTSC).

for (i=0; i QWORD tsc_ticks()

{
#ifdef _MSC_VER
// disable „no return value“ warning
#pragma warning( disable : 4035 )
_asm xor eax, eax
_asm xor edx, edx
_asm rdtsc // _asm _emit 0x0f // _asm _emit 0x31
#else
__asm__ (
„xorl %eax, %eax\n“
„xorl %edx, %edx\n“
„rdtsc“);
#endif
}Dann musst Du noch darauf achten, einen 64-bit int-typ
QWORD zu definieren, z.B.

 #ifdef \_MSC\_VER
 // --- Win32 Microsoft C++ defines INT64 data item ---
 typedef \_\_int64 QWORD;
 // #elseif Dann sollte es gehen.
Bei gcc/x64 reicht es, wenn Du "long" oder "int" nimmst, 
ist dann 64 bit.



> Vorraussetung ist, dass die Vektorenelemente hintereinander im  
> Speicher angeordnet sind. Jedoch sehe ich bei der Ausgabe das  
> dies nicht der Fall ist :


Das ist schon der Fall. Um Dein Feld auszugeben,
machst Du einfach:


     
     for (i=0; i**size; i++) // und <u>nicht</u>   
     printf("Adresse: %p c[%i]= %f\n",&c[i], i, c[i]);**   




> Wie kann ich sicherstellen, das die Werte hintereinander  
> angeordnet sind?


Schreibe 1 bis 100 in das Feld c und gib es wieder aus.

Grüße

CMБ

Hallo Andreas,

So weit bin ich für den ersten Fall:

> #include   
> #include   
>   
> int main (void)  
> {

#define SIZE 100;


> double t, t1, t2, c[SIZE], a[SIZE][SIZE], b[SIZE];

 double \*ptr\_a, \*ptr\_b, \*ptr\_c;


> double t, t1, t2, c[100], a[100][100], b[100];  
> int size, i, j;  
>   
> size = 100;  
>   
> t1=clock();

 \*ptr\_a = &a[0][0];


> for (i=0; ic[i] += a[i][j] \* b[j];

 \*ptr\_c++ += \*ptr\_a++ \* \*ptr\_b++;
 }


> return 0;  
> }


Teste mal wie schnell das ist .....

Das Problem ist, dass der Ausdruck:
"c[i] += a[i][j] \* b[j];"
folgendermassen aufgelöst werden muss:
(\*(c+i\*sizeof(double))) += (\*(a+i\*j\*sizeof(double))) \* (\*(b+j\*sizeof(double)));

Rein zur Adressberechnung benötigst du dabei 4 Multiplikationen und 3 Additionen .....

Für:
"\*ptr\_c++ += \*ptr\_a++ \* \*ptr\_b++;"
benötigst du zur Adressberechnung nur 3 Additionen. Dabei ist noch zu bedenken, dass eine Addition weniger CPU-Takte benötigt als eine Addition.

MfG Peter(TOO)

Dabei ist
noch zu bedenken, dass eine Addition weniger CPU-Takte
benötigt als eine Addition.

Ich glaube kaum.

('tschuldigung)
vbt

Hallo vbt,

Ich glaube kaum.

Mit einem Barrelshifter hast du für Multiplikationen mit 2er Potenzen recht. Ansonsten sollte dir ja der mathematische unterschied zwischen einer binären Addition und eine Multiplikation bekannt sein.

ftp://download.intel.com/design/Pentium4/manuals/248…
Aanhanc C

MfG Peter(TOO)

Hallo Peter !

Ich glaube kaum.

Ansonsten sollte dir ja der mathematische unterschied zwischen einer binären Addition und eine Multiplikation bekannt sein.

Es ist völlig egal, ob einem der mathematische Unterschied zwischen einer binären Addition und einer Multiplikation bekannt ist, vbt hat auf jeden Fall Recht!
Deine Aussage:

Dabei ist noch zu bedenken, dass eine Addition weniger CPU-Takte benötigt als eine Addition.

ist nunmal nicht richtig!

Schöne Grüsse
Christof

P.S.: Im Zweifelsfalle lies deine Aussage nochmal genau nach :wink:

Hallo Christof,

Es ist völlig egal, ob einem der mathematische Unterschied
zwischen einer binären Addition und einer Multiplikation
bekannt ist, vbt hat auf jeden Fall Recht!
Deine Aussage:

Dabei ist noch zu bedenken, dass eine Addition weniger
CPU-Takte benötigt als eine Addition.

Der Artikel von PeterTOO strotzte vor Fehlern und
Widersprüchen, daher wird er wohl einen schlechten
Tag gehabt haben. Das passiert doch jedem von uns
mal. Nächste Woche ist alles wieder gut und er
schreibt wieder verständliche Artikel …
Nun lasst ihn doch schon in Ruhe :wink:

Grüße

CMБ