Hallo,
[F'up nach suse-programming!]
On Mon, 18 Nov 2002, Jan Trippler wrote:
Slightly OT, aber wenns auch C sein darf - mal ein klein wenig
anderer Ansatz (könnte ein wenig schneller sein ;-):
==========================================================
/* ip.c: IP-Adressen ausgeben
Kompilieren: gcc -o ip ip.c */
#include
int main (int argc, char **argv) {
unsigned long ip = 0;
for (ip = 0; ip <= 0xffffffff; ip ++)
printf ("%d.%d.%d.%d\n", (ip >> 24) & 0xff,
(ip >> 16) & 0xff,
(ip >> 8) & 0xff,
ip & 0xff);
return (0);
}
==========================================================
Dauert aber immer noch zu lange... Naja, _etwas_ (wg. printf)
schneller geht's noch:
====
/* Fuer die eigene Anwendung den gewunschten Funktionsrumpf */
/* in ein main() einfuegen und den Rest weglassen */
#include
/* Privater header mit Makros fuer BENCHINIT/TIMEFUNC */
#include
#define MAX_PRINTF 0x007fffff
#define MAX_OPS 0x7fffffff
void ip_jan(void) {
unsigned long ip = 0;
unsigned long a,b,c,d;
for (ip = 0; ip <= MAX_PRINTF; ip++) {
a = (ip >> 24) & 0xff; b = (ip >> 16) & 0xff;
c = (ip >> 8) & 0xff; d = ip & 0xff;
printf ("%ld.%ld.%ld.%ld\n", a, b, c, d);
}
return;
}
void ip_jan_ops(void) {
unsigned long ip = 0;
unsigned long a,b,c,d;
for (ip = 0; ip <= MAX_OPS; ip++) {
a = (ip >> 24) & 0xff; b = (ip >> 16) & 0xff;
c = (ip >> 8) & 0xff; d = ip & 0xff;
}
return;
}
void ip_david(void) {
register unsigned long ip = 0;
register unsigned int a, b, c, d1, d2, d3, d4;
for (ip = 0; ip <= MAX_PRINTF; ip+=4) {
a = (ip >> 24) & 0xff;
b = (ip >> 16) & 0xff;
c = (ip >> 8) & 0xff;
d1 = ip & 0xff; d2 = d1 + 1; d3 = d1 + 2; d4 = d1 + 3;
printf("%d.%d.%d.%d\n%d.%d.%d.%d\n"
"%d.%d.%d.%d\n%d.%d.%d.%d\n",
a, b, c, d1, a, b, c, d2,
a, b, c, d3, a, b, c, d4
);
}
return;
}
void ip_david_ops(void) {
register unsigned long ip = 0;
register unsigned int a, b, c, d1, d2, d3, d4;
for (ip = 0; ip <= MAX_OPS; ip+=8) {
a = (ip >> 24) & 0xff;
b = (ip >> 16) & 0xff;
c = (ip >> 8) & 0xff;
d1 = ip & 0xff; d2 = d1 + 1; d3 = d1 + 2; d4 = d1 + 3;
}
return;
}
int main (int argc, char **argv) {
BENCHINIT;
TIMEFUNC(ip_david_ops,());
TIMEFUNC(ip_jan_ops,());
TIMEFUNC(ip_david,());
TIMEFUNC(ip_jan,());
return 0;
}
====
$ gcc -O2 -march=athlon -mcpu=athlon -malign-functions=4 \
-fschedule-insns2 -mwide-multiply -o ips ips.c
$ ./ips >/dev/null
ip_david_ops: 1.093644 sec
ip_jan_ops: 8.816783 sec
ip_david: 20.190973 sec
ip_jan: 24.128861 sec
$ gcc -O2 -march=athlon -mcpu=athlon -malign-functions=4 \
-fschedule-insns2 -mwide-multiply -funroll-loops -o ips ips.c
$ ./ips >/dev/null
ip_david_ops: 0.269966 sec
ip_jan_ops: 2.177346 sec
ip_david: 19.950344 sec
ip_jan: 24.064929 sec
Wie man sieht, geht ein Grossteil der Laufzeit auf's Konto von 'printf'
(und dabei sind das ja noch wesentlich weniger Schleifendurchlaeufe
(Faktor 256) -- hat mir einfach zu lange gedauert ;)...
Warum ist meine Variante so viel schneller? *hehe* Weil ich die Tage
mal in der AMD-Doku gestoebert habe, und dort gelesen habe, dass das
"vervierfachen" der "inneren" Ops und das verwenden von "temporaeren
(Register) Variablen" es ermoeglicht, die Rechenwerke der CPU parallel
zu verwenden... d.h. die Operationen im Schleifeninnern laufen
teilweise gleichzeitig, anstatt nacheinander ab. Bestes Beispiel:
for(i = 0; i < 10000; i++) {
sum += a[i];
}
ist _deutlich_ (ca. Faktor 4) langsamer als
for(i = 0; i < 10000; i+=4) {
s1 += a[i]; s2 += a[i+1];
s3 += a[i+2]; s4 += a[i+3];
}
sum = (s1 + s2) + (s3 + s4);
Auf Pentii > P2 muesste es aehnlich aussehen...
-dnh
--
126: Netzcomputer
Ein Netzcomputer ist ein Rechner, der vollständig vom Netz
abhängig ist. (ECONY 2/99)