Wozu Makros nicht alles gut sein können?

i_hasser

Grand Admiral Special
Mitglied seit
06.06.2002
Beiträge
18.964
Renomée
85
Standort
IO 0x60
Mal ein Auszug aus dem Memory Streaming Benchmark von AMBiX86 D:

Code:
// 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*

 
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.
 
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.
 
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.
 
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).
 
Guckt euch mal den C Code an, wie der MD5 Hashalgorithmus in Linux implementiert is. Da werden auch Kiloweise Makros mißbraucht.
 
Zurück
Oben Unten