PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wozu Makros nicht alles gut sein können?



i_hasser
17.10.2004, 13:16
Mal ein Auszug aus dem Memory Streaming Benchmark von AMBiX86 D:


// Full Benchmark Function Macro
// * x and y are function name and var type, b1 to b4 are function names for approp. ADD, COPY, SCALE and TRIAD Benchmark
#define MEMORY_BENCH(x,y,b1,b2,b3,b4) \
Bench_Memory1::PartResult Bench_Memory1::x(TimerF* timer_device, double runtime, int megs) \
{ \
int i,j; \
\
TIMERF_T t1,t2,t3,t4,t5; \
\
y* test_range1=new y[ ((1<<20)*megs) / sizeof(y) ]; \
y* test_range2=new y[ ((1<<20)*megs) / sizeof(y) ]; \
y* test_range3=new y[ ((1<<20)*megs) / sizeof(y) ]; \
\
int loops; \
\
for(loops=1;;loops*=2) \
{ \
t1=timer_device->getticks(); \
\
b1(test_range1, test_range2, test_range3, ((1<<20)*megs) / sizeof(y), loops); \
\
t2=timer_device->getticks(); \
if (timer_device->getseconds(t1,t2)>=(runtime/5.0)) break; \
} \
\
PartResult ret; \
\
t1=timer_device->getticks(); \
b1(test_range1, test_range2, test_range3, ((1<<20)*megs) / sizeof(y), loops); \
\
t2=timer_device->getticks(); \
b2(test_range1, test_range2, ((1<<20)*megs) / sizeof(y), loops); \
\
t3=timer_device->getticks(); \
b3(test_range1, test_range2, ((1<<20)*megs) / sizeof(y), loops); \
\
t4=timer_device->getticks(); \
b4(test_range1, test_range2, test_range3, ((1<<20)*megs) / sizeof(y), loops); \
\
t5=timer_device->getticks(); \
\
ret.ADD= ((1<<20)*megs*loops*3) / timer_device->getseconds(t1,t2); \
ret.COPY= ((1<<20)*megs*loops*2) / timer_device->getseconds(t2,t3); \
ret.SCALE=((1<<20)*megs*loops*2) / timer_device->getseconds(t3,t4); \
ret.TRIAD=((1<<20)*megs*loops*3) / timer_device->getseconds(t4,t5); \
\
delete test_range1, test_range2, test_range3; \
\
return ret; \
}


// ADD Function Macro
// * A dirty hack to save code lines ;)
// * NOTE: ubound must be a power of 2 (!)
#define MEMORY_BENCH_ADD(x,y) \
void Bench_Memory1::x (y* src1, y* src2, y* src3, int ubound, int loops) { \
int i,j; \
for(j=0;j<loops;j++) { \
for(i=0;i<ubound;i+=32) { \
src1[i+0] =src2[i+0] +src3[i+0]; src1[i+1]= src2[i+1] +src3[i+1]; \
src1[i+2] =src2[i+2] +src3[i+2]; src1[i+3]= src2[i+3] +src3[i+3]; \
src1[i+4] =src2[i+4] +src3[i+4]; src1[i+5]= src2[i+5] +src3[i+5]; \
src1[i+6] =src2[i+6] +src3[i+6]; src1[i+7]= src2[i+7] +src3[i+7]; \
src1[i+8] =src2[i+8] +src3[i+8]; src1[i+9]= src2[i+9] +src3[i+9]; \
src1[i+10] =src2[i+10] +src3[i+10]; src1[i+11]= src2[i+11] +src3[i+11]; \
src1[i+12] =src2[i+12] +src3[i+12]; src1[i+13]= src2[i+13] +src3[i+13]; \
src1[i+14] =src2[i+14] +src3[i+14]; src1[i+15]= src2[i+15] +src3[i+15]; \
src1[i+16] =src2[i+16] +src3[i+16]; src1[i+17]= src2[i+17] +src3[i+17]; \
src1[i+18] =src2[i+18] +src3[i+18]; src1[i+19]= src2[i+19] +src3[i+19]; \
src1[i+20] =src2[i+20] +src3[i+20]; src1[i+21]= src2[i+21] +src3[i+21]; \
src1[i+22] =src2[i+22] +src3[i+22]; src1[i+23]= src2[i+23] +src3[i+23]; \
src1[i+24] =src2[i+24] +src3[i+24]; src1[i+25]= src2[i+25] +src3[i+25]; \
src1[i+26] =src2[i+26] +src3[i+26]; src1[i+27]= src2[i+27] +src3[i+27]; \
src1[i+28] =src2[i+28] +src3[i+28]; src1[i+29]= src2[i+29] +src3[i+29]; \
src1[i+30] =src2[i+30] +src3[i+30]; src1[i+31]= src2[i+31] +src3[i+31]; \
} \
} \
}

// COPY Function Macro
// * A dirty hack to save code lines ;)
// * NOTE: ubound must be a power of 2 (!)
#define MEMORY_BENCH_COPY(x,y) \
void Bench_Memory1::x ( y* src1, y* src2, int ubound, int loops) { \
int i,j; \
for(j=0;j<loops;j++) { \
for(i=0;i<ubound;i+=32) { \
src1[i+0] =src2[i+0]; src1[i+1]= src2[i+1]; \
src1[i+2] =src2[i+2]; src1[i+3]= src2[i+3]; \
src1[i+4] =src2[i+4]; src1[i+5]= src2[i+5]; \
src1[i+6] =src2[i+6]; src1[i+7]= src2[i+7]; \
src1[i+8] =src2[i+8]; src1[i+9]= src2[i+9]; \
src1[i+10] =src2[i+10]; src1[i+11]= src2[i+11]; \
src1[i+12] =src2[i+12]; src1[i+13]= src2[i+13]; \
src1[i+14] =src2[i+14]; src1[i+15]= src2[i+15]; \
src1[i+16] =src2[i+16]; src1[i+17]= src2[i+17]; \
src1[i+18] =src2[i+18]; src1[i+19]= src2[i+19]; \
src1[i+20] =src2[i+20]; src1[i+21]= src2[i+21]; \
src1[i+22] =src2[i+22]; src1[i+23]= src2[i+23]; \
src1[i+24] =src2[i+24]; src1[i+25]= src2[i+25]; \
src1[i+26] =src2[i+26]; src1[i+27]= src2[i+27]; \
src1[i+28] =src2[i+28]; src1[i+29]= src2[i+29]; \
src1[i+30] =src2[i+30]; src1[i+31]= src2[i+31]; \
} \
} \
}

// SCALE Function Macro
// * A dirty hack to save code lines ;)
// * NOTE: ubound must be a power of 2 (!)
#define MEMORY_BENCH_SCALE(x,y) \
void Bench_Memory1::x ( y* src1, y* src2, int ubound, int loops) { \
int i,j; \
y a=3; \
for(j=0;j<loops;j++) { \
for(i=0;i<ubound;i+=32) { \
src1[i+0] =a*src2[i+0]; src1[i+1]= a*src2[i+1]; \
src1[i+2] =a*src2[i+2]; src1[i+3]= a*src2[i+3]; \
src1[i+4] =a*src2[i+4]; src1[i+5]= a*src2[i+5]; \
src1[i+6] =a*src2[i+6]; src1[i+7]= a*src2[i+7]; \
src1[i+8] =a*src2[i+8]; src1[i+9]= a*src2[i+9]; \
src1[i+10] =a*src2[i+10]; src1[i+11]= a*src2[i+11]; \
src1[i+12] =a*src2[i+12]; src1[i+13]= a*src2[i+13]; \
src1[i+14] =a*src2[i+14]; src1[i+15]= a*src2[i+15]; \
src1[i+16] =a*src2[i+16]; src1[i+17]= a*src2[i+17]; \
src1[i+18] =a*src2[i+18]; src1[i+19]= a*src2[i+19]; \
src1[i+20] =a*src2[i+20]; src1[i+21]= a*src2[i+21]; \
src1[i+22] =a*src2[i+22]; src1[i+23]= a*src2[i+23]; \
src1[i+24] =a*src2[i+24]; src1[i+25]= a*src2[i+25]; \
src1[i+26] =a*src2[i+26]; src1[i+27]= a*src2[i+27]; \
src1[i+28] =a*src2[i+28]; src1[i+29]= a*src2[i+29]; \
src1[i+30] =a*src2[i+30]; src1[i+31]= a*src2[i+31]; \
} \
} \
}

// TRIAD Function Macro
// * A dirty hack to save code lines ;)
// * NOTE: ubound must be a power of 2 (!)
#define MEMORY_BENCH_TRIAD(x,y) \
void Bench_Memory1::x (y* src1, y* src2, y* src3, int ubound, int loops) { \
int i,j; \
y a=3; \
for(j=0;j<loops;j++) { \
for(i=0;i<ubound;i+=32) { \
src1[i+0] =a*src2[i+0] +src3[i+0]; src1[i+1]= a*src2[i+1] +src3[i+1]; \
src1[i+2] =a*src2[i+2] +src3[i+2]; src1[i+3]= a*src2[i+3] +src3[i+3]; \
src1[i+4] =a*src2[i+4] +src3[i+4]; src1[i+5]= a*src2[i+5] +src3[i+5]; \
src1[i+6] =a*src2[i+6] +src3[i+6]; src1[i+7]= a*src2[i+7] +src3[i+7]; \
src1[i+8] =a*src2[i+8] +src3[i+8]; src1[i+9]= a*src2[i+9] +src3[i+9]; \
src1[i+10] =a*src2[i+10] +src3[i+10]; src1[i+11]= a*src2[i+11] +src3[i+11]; \
src1[i+12] =a*src2[i+12] +src3[i+12]; src1[i+13]= a*src2[i+13] +src3[i+13]; \
src1[i+14] =a*src2[i+14] +src3[i+14]; src1[i+15]= a*src2[i+15] +src3[i+15]; \
src1[i+16] =a*src2[i+16] +src3[i+16]; src1[i+17]= a*src2[i+17] +src3[i+17]; \
src1[i+18] =a*src2[i+18] +src3[i+18]; src1[i+19]= a*src2[i+19] +src3[i+19]; \
src1[i+20] =a*src2[i+20] +src3[i+20]; src1[i+21]= a*src2[i+21] +src3[i+21]; \
src1[i+22] =a*src2[i+22] +src3[i+22]; src1[i+23]= a*src2[i+23] +src3[i+23]; \
src1[i+24] =a*src2[i+24] +src3[i+24]; src1[i+25]= a*src2[i+25] +src3[i+25]; \
src1[i+26] =a*src2[i+26] +src3[i+26]; src1[i+27]= a*src2[i+27] +src3[i+27]; \
src1[i+28] =a*src2[i+28] +src3[i+28]; src1[i+29]= a*src2[i+29] +src3[i+29]; \
src1[i+30] =a*src2[i+30] +src3[i+30]; src1[i+31]= a*src2[i+31] +src3[i+31]; \
} \
} \
}

// Main Benchmark Functions

MEMORY_BENCH(bench_int8, int8, bench_int8_add, bench_int8_copy, bench_int8_scale, bench_int8_triad);
MEMORY_BENCH(bench_int16, int16, bench_int16_add, bench_int16_copy, bench_int16_scale, bench_int16_triad);
MEMORY_BENCH(bench_int32, int32, bench_int32_add, bench_int32_copy, bench_int32_scale, bench_int32_triad);
MEMORY_BENCH(bench_int64, int64, bench_int64_add, bench_int64_copy, bench_int64_scale, bench_int64_triad);


// Auxilary Benchmark functions

MEMORY_BENCH_ADD(bench_int8_add, int8);
MEMORY_BENCH_ADD(bench_int16_add, int16);
MEMORY_BENCH_ADD(bench_int32_add, int32);
MEMORY_BENCH_ADD(bench_int64_add, int64);

MEMORY_BENCH_COPY(bench_int8_copy, int8);
MEMORY_BENCH_COPY(bench_int16_copy, int16);
MEMORY_BENCH_COPY(bench_int32_copy, int32);
MEMORY_BENCH_COPY(bench_int64_copy, int64);

MEMORY_BENCH_SCALE(bench_int8_scale, int8);
MEMORY_BENCH_SCALE(bench_int16_scale, int16);
MEMORY_BENCH_SCALE(bench_int32_scale, int32);
MEMORY_BENCH_SCALE(bench_int64_scale, int64);

MEMORY_BENCH_TRIAD(bench_int8_triad, int8);
MEMORY_BENCH_TRIAD(bench_int16_triad, int16);
MEMORY_BENCH_TRIAD(bench_int32_triad, int32);
MEMORY_BENCH_TRIAD(bench_int64_triad, int64);




Gibts eigentlich auch sowas wie FOR-Schleifen für Makros? *chatt*

PuckPoltergeist
17.10.2004, 13:26
Original geschrieben von i_hasser
Gibts eigentlich auch sowas wie FOR-Schleifen für Makros? *chatt*

Nein, direkt Schleifenkonstrukte gibt es beim CPP nicht. Man kann Ausdrücke zu Schleifen expandieren lassen, aber selber mit Schleifen in CPP programmieren geht nicht. Das hat auch seinen Grund, denn in CPP zu programmieren ist verdammt gefährlich.

i_hasser
17.10.2004, 13:30
Schade eigentlich, dachte an sowas wie 'for $a in int8 int16 int32 int64' bei BASH.

Naja, geht ja auch so *chatt*

Templates wären für einen Speicherbenchmark dummerweise nur zu langsam, sonst hätt ich es damit gemacht.

PuckPoltergeist
17.10.2004, 13:39
Original geschrieben von i_hasser
Templates wären für einen Speicherbenchmark dummerweise nur zu langsam, sonst hätt ich es damit gemacht.

Wozu bitteschön Templates? Das geht auch per Hand ausprogrammiert, und bedeutet mit Sicherheit nicht den Aufwand.

i_hasser
17.10.2004, 13:47
Oh doch, ich müsste die Funktion 6mal machen (es fehlt noch float32 und float64, wobei das nicht das Problem sein dürfte).

Und abgesehen davon kommt noch ein 2. Streaming Benchmark sowie ein Blockbenchmark, die nehmen alle 3 6 verschiedene Datentypen und bilden aus dem Ergebnis den Mittelwert (bei CPUs ohne Write Gathering sackt die Datenrate normalerweise in den Keller sowie man nicht 32bit Integer nimmt).

Ich denke der Random Access Benchmark wird auch alle Datentypen durchtesten. Auf Dauer spart man sich damit dann doch ellenweise Code, vor allem wenn man dann doch mal eine Kleinigkeit ändern muss.


Und rein logisch betrachtet ist die Lösung oben viel sauberer, weil nur wenig Sachen doppelt vorkommen (es also auf das wesentliche reduziert ist).

Marnem
17.10.2004, 17:20
Guckt euch mal den C Code an, wie der MD5 Hashalgorithmus in Linux implementiert is. Da werden auch Kiloweise Makros mißbraucht.