Extremely poor performance crunching random numbers under PIV-FC5
BankHacker
bankhacker at gmail.com
Fri May 19 09:17:37 UTC 2006
> Here is my guess at the meaning of it all that appears to work:
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <fcntl.h>
>
> int nRandom;
> struct random_data randomdataState;
> char szBufferState[1024];
>
>
> int main(int argc, char ** argv) {
> int n;
>
> int fd=open("/dev/urandom", O_RDONLY);
> if(fd<1) { perror("unable to open /dev/urandom"); return 1; }
>
> read(fd, szBufferState, sizeof(szBufferState));
> close(fd);
>
> initstate_r(*((int *)szBufferState),
> (szBufferState+sizeof(int)), sizeof(szBufferState)-sizeof(int),
> &randomdataState);
>
> for(n=0;n<2048;n++) {
> random_r(&randomdataState, &nRandom);
> printf("%d\n", nRandom);
> }
>
> return (0);
> }
Ok. I tested it and worked. Thanks a lot. You seems to be a "C guru"
or similar. GUAU!
I have implemented your way random_r() function insime my cpu-test
code. Here it is the full source code:
### test-cpu-2.c ##################################################
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include <fcntl.h>
#ifdef linux
inline void randomize(struct random_data *randomdataState) {
#else
inline void randomize() {
#endif
time_t seconds;
#ifdef linux
char szBufferState[1024];
extern int read();
extern int close();
int fd;
#else
#endif
time(&seconds);
srand((unsigned int) seconds);
#ifdef linux
/* Se inicializa el generador especial de numeros aleatorios */
srand48((unsigned int) seconds);
fd=open("/dev/urandom", O_RDONLY);
if(fd<1) { perror("unable to open /dev/urandom"); /*return 1;*/ }
read(fd, szBufferState, sizeof(szBufferState));
close(fd);
initstate_r(*((int *)szBufferState), (szBufferState+sizeof(int)),
sizeof(szBufferState)-sizeof(int), randomdataState);
#else
#endif
}
/* int main(int argc, char ** argv) { */
int main() {
int i, r, numero_ciclos, numero_ciclosM;
clock_t start, end;
char* buf;
struct random_data randomdataState;
/* Se inicializa el generador de numeros aleatorios */
#ifdef linux
randomize(&randomdataState);
#else
randomize();
#endif
start = clock();
/* Se reserva 0.1 Gb de memoria */
buf=malloc(100*1024*1024);
end = clock();
printf("Reservado 0.1 Gb de memoria en %.3f s.\n", (double)(end -
start)/CLOCKS_PER_SEC);
start = clock();
/* Se escribe en 0.1 Gb de memoria */
for(i=0; i<100*1024*1024; i++) {
buf[i]='0';
}
end = clock();
printf("Escritura sobre 0.1 Gb de memoria en %.3f s.\n",
(double)(end - start)/CLOCKS_PER_SEC);
numero_ciclos = 10000000; numero_ciclosM = numero_ciclos / 1E6;
start = clock();
for(i=0; i<numero_ciclos; i++) {
r = rand();
}
end = clock();
printf("%d M de rand() en %.3f s. (ejemplo.: %d)\n",
numero_ciclosM, (double)(end - start)/CLOCKS_PER_SEC, r);
start = clock();
for(i=0; i<numero_ciclos; i++) {
r = sqrt(i);
}
end = clock();
printf("%d M de sqrt(i) en %.3f s. (ejemplo.: %d)\n",
numero_ciclosM, (double)(end - start)/CLOCKS_PER_SEC, r);
start = clock();
for(i=0; i<numero_ciclos; i++) {
r = log(i);
}
end = clock();
printf("%d M de log(i) en %.3f s. (ejemplo.: %d)\n",
numero_ciclosM, (double)(end - start)/CLOCKS_PER_SEC, r);
start = clock();
for(i=0; i<numero_ciclos; i++) {
r = log10(i);
}
end = clock();
printf("%d M de log10(i) en %.3f s. (ejemplo.: %d)\n",
numero_ciclosM, (double)(end - start)/CLOCKS_PER_SEC, r);
#ifdef linux
start = clock();
for(i=0; i<numero_ciclos; i++) {
r = random();
}
end = clock();
printf("LINUX: %d M de random() en %.3f s. (ejemplo.: %d)\n",
numero_ciclosM, (double)(end - start)/CLOCKS_PER_SEC, r);
start = clock();
for(i=0; i<numero_ciclos; i++) {
random_r(&randomdataState, &r);
}
end = clock();
printf("LINUX: %d M de random_r() en %.3f s. (ejemplo.: %d)\n",
numero_ciclosM, (double)(end - start)/CLOCKS_PER_SEC, r);
start = clock();
for(i=0; i<numero_ciclos; i++) {
r = lrand48();
}
end = clock();
printf("LINUX: %d M de lrand48() en %.3f s. (ejemplo.: %d)\n",
numero_ciclosM, (double)(end - start)/CLOCKS_PER_SEC, r);
#else
#endif
return (0);
}
### test-cpu-2.c (the end) ########################################
I have compiled it this way:
gcc test-cpu-2.c -o randr-test-cpu-2 -lm -W -Wall -pedantic -O0
I explain later why "-O0".
The result is this:
# ./randr-test-cpu-2
Reservado 0.1 Gb de memoria en 0.010 s.
Escritura sobre 0.1 Gb de memoria en 0.610 s.
10 M de rand() en 46.950 s. (ejemplo.: 1551429474)
10 M de sqrt(i) en 0.240 s. (ejemplo.: 3162)
10 M de log(i) en 0.820 s. (ejemplo.: 16)
10 M de log10(i) en 0.810 s. (ejemplo.: 6)
LINUX: 10 M de random() en 38.720 s. (ejemplo.: 146139182)
LINUX: 10 M de random_r() en 19.370 s. (ejemplo.: 495480852)
LINUX: 10 M de lrand48() en 31.600 s. (ejemplo.: 451810414)
19 seconds is not a good result! I have compiled the same code on an
Opteron 64 bits:
# gcc test-cpu-2.c -o randr-test-cpu-2 -lm -W -Wall -pedantic -O0 -static
# file randr-test-cpu-2
randr-test-cpu-2: ELF 64-bit LSB executable, AMD x86-64, version 1
(SYSV), for GNU/Linux 2.4.0, statically linked, not stripped
# ./randr-test-cpu-2
Reservado 0.1 Gb de memoria en 0.000 s.
Escritura sobre 0.1 Gb de memoria en 0.720 s.
10 M de rand() en 0.140 s. (ejemplo.: 2146669435)
10 M de sqrt(i) en 0.200 s. (ejemplo.: 3162)
10 M de log(i) en 1.090 s. (ejemplo.: 16)
10 M de log10(i) en 1.230 s. (ejemplo.: 6)
LINUX: 10 M de random() en 0.130 s. (ejemplo.: 1324087262)
LINUX: 10 M de random_r() en 0.070 s. (ejemplo.: 539283702)
LINUX: 10 M de lrand48() en 0.150 s. (ejemplo.: 1823489204)
0.070 seconds is a good result. I have also compiled ir on an Intel
Pentium 4 @ 2.40GHz:
# gcc test-cpu-2.c -o randr-test-cpu-2 -lm -W -Wall -pedantic -O0
# file randr-test-cpu-2
randr-test-cpu-2: ELF 32-bit LSB executable, Intel 80386, version 1
(SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs),
not stripped
# ./randr-test-cpu-2
Reservado 0.1 Gb de memoria en 0.000 s.
Escritura sobre 0.1 Gb de memoria en 0.600 s.
10 M de rand() en 0.420 s. (ejemplo.: 422740983)
10 M de sqrt(i) en 0.660 s. (ejemplo.: 3162)
10 M de log(i) en 1.300 s. (ejemplo.: 16)
10 M de log10(i) en 1.200 s. (ejemplo.: 6)
LINUX: 10 M de random() en 0.330 s. (ejemplo.: 870228159)
LINUX: 10 M de random_r() en 0.190 s. (ejemplo.: 2081863344)
LINUX: 10 M de lrand48() en 0.600 s. (ejemplo.: 119398373)
0.190 seconds is also a good result. In last system, when compiling
statically, results become a bit better:
# gcc test-cpu-2.c -o randr-test-cpu-2 -lm -W -Wall -pedantic -O0 -static
# file randr-test-cpu-2
randr-test-cpu-2: ELF 32-bit LSB executable, Intel 80386, version 1
(SYSV), for GNU/Linux 2.2.5, statically linked, not stripped
# ./randr-test-cpu-2
Reservado 0.1 Gb de memoria en 0.000 s.
Escritura sobre 0.1 Gb de memoria en 0.590 s.
10 M de rand() en 0.270 s. (ejemplo.: 2033397145)
10 M de sqrt(i) en 0.800 s. (ejemplo.: 3162)
10 M de log(i) en 1.540 s. (ejemplo.: 16)
10 M de log10(i) en 1.470 s. (ejemplo.: 6)
LINUX: 10 M de random() en 0.260 s. (ejemplo.: 819752714)
LINUX: 10 M de random_r() en 0.170 s. (ejemplo.: 28223623)
LINUX: 10 M de lrand48() en 0.640 s. (ejemplo.: 1765781247)
Conclusion: random_r() function seems to suffer the same bug/problem
than rand() standard function. Right?
Oddity: initstate_r() function seems to throgh very easily a
"Segmentation Fault" error when not compiling with "-O0" flag on
certain systems. My opteron and my PIV @ 3Ghz are affected, while my
PIV at 2.4Ghz not. I will appreciate any comments/similar experiencies.
Any idea to continue testings?
Thanks sincerely!
More information about the fedora-list
mailing list