Hi folks,after the float vs double debate, I decided to benchmark at least conversion between the two datatypes. The code is attached to the end of the mail ( compile with: gcc -O2 -o floatspeed floatspeed.c -lm ) basically I am testing: (loops of the instructions below unrolled in sequences of 4 to minimize the overhead of the for loop) float to float buffer passing: *outbuf32ptr++ = *inbuf32ptr++; *outbuf32ptr++ = *inbuf32ptr++; *outbuf32ptr++ = *inbuf32ptr++; *outbuf32ptr++ = *inbuf32ptr++; double to double: *outbuf64ptr++ = *inbuf64ptr++; *outbuf64ptr++ = *inbuf64ptr++; *outbuf64ptr++ = *inbuf64ptr++; *outbuf64ptr++ = *inbuf64ptr++; float to double: *outbuf64ptr++ = (double) *inbuf32ptr++; *outbuf64ptr++ = (double) *inbuf32ptr++; *outbuf64ptr++ = (double) *inbuf32ptr++; *outbuf64ptr++ = (double) *inbuf32ptr++; double to float: *outbuf32ptr++ = (float) *inbuf64ptr++; *outbuf32ptr++ = (float) *inbuf64ptr++; *outbuf32ptr++ = (float) *inbuf64ptr++; *outbuf32ptr++ = (float) *inbuf64ptr++; Test system intel Celeron 366: RESULTS: float to float buffers time delta=15.906434 million operations/sec=128.753 double to double buffers time delta=15.969527 million operations/sec=128.244 float to double buffers time delta=17.425132 million operations/sec=117.531 double to float buffers time delta=22.873382 million operations/sec=89.536 SUMMARY: as you can see double to double and float to float assignments deliver almost the same speed. float 2 double cost is a few % , while double 2 float cost about 30% of performance loss. (vs float2float or double2double) This again proved that my multidatatype design is superiour to a design limited to float. Consider the fact that many VST plugins are now internally (except for inputs and outputs) working with double to get full 24bit precision. (synths, and other HQ stuff, since you can't pretend to deliver full 24bit precision while only doing 24bit internal computations) That means at least a double to float and float to double conversion between many plugins, which can eat a part of your CPU to do useless work. With my design you can for example keep plugins using the "double" datatype in a sequential chain without any useless datatype ( float to double at every input and double to float at every output) conversions. (flexible plugins should provide float and double, so that the host can choose what to use (for precision or speed reasons)) comments ? Benno.
/* floatspeed.c (c) by Benno Senoner ( [EMAIL PROTECTED] ) hack to benchmark, the passing of buffers between floats and doubles compile with cc -O2 -o floatspeed floatspeed.c -lm run with ./floatspeed */ #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <unistd.h> #define NUMLOOPS 2000000 #define MYSIZE 1024 #define MYSIZEDIV4 256 double my_gettime(void); main() { float *inbuf32ptr; double *inbuf64ptr; float *outbuf32ptr; double *outbuf64ptr; float inbuf32[MYSIZE]; double inbuf64[MYSIZE]; float outbuf32[MYSIZE]; double outbuf64[MYSIZE]; int i,u; double time1,time2,delta; for(i=0; i<MYSIZE; i++) { inbuf32[i]=drand48() * pow(10.0,100*( drand48()-0.5)); inbuf64[i]=(double) inbuf32[i]; } time1=my_gettime(); for(u=0 ; u<NUMLOOPS ; u++) { inbuf32ptr=inbuf32; outbuf32ptr=outbuf32; for(i=0; i<MYSIZEDIV4; i++) { *outbuf32ptr++ = *inbuf32ptr++; *outbuf32ptr++ = *inbuf32ptr++; *outbuf32ptr++ = *inbuf32ptr++; *outbuf32ptr++ = *inbuf32ptr++; } } time2=my_gettime(); delta=time2-time1; printf("\nfloat to float buffers\n"); printf("time delta=%f\n",delta); printf("million operations/sec=%.3f\n",NUMLOOPS*MYSIZE/delta/1000000.0); time1=my_gettime(); for(u=0 ; u<NUMLOOPS ; u++) { inbuf64ptr=inbuf64; outbuf64ptr=outbuf64; for(i=0; i<MYSIZEDIV4; i++) { *outbuf64ptr++ = *inbuf64ptr++; *outbuf64ptr++ = *inbuf64ptr++; *outbuf64ptr++ = *inbuf64ptr++; *outbuf64ptr++ = *inbuf64ptr++; } } time2=my_gettime(); delta=time2-time1; printf("\ndouble to double buffers\n"); printf("time delta=%f\n",delta); printf("million operations/sec=%.3f\n",NUMLOOPS*MYSIZE/delta/1000000.0); time1=my_gettime(); for(u=0 ; u<NUMLOOPS ; u++) { inbuf32ptr=inbuf32; outbuf64ptr=outbuf64; for(i=0; i<MYSIZEDIV4; i++) { *outbuf64ptr++ = (double) *inbuf32ptr++; *outbuf64ptr++ = (double) *inbuf32ptr++; *outbuf64ptr++ = (double) *inbuf32ptr++; *outbuf64ptr++ = (double) *inbuf32ptr++; } } time2=my_gettime(); delta=time2-time1; printf("\nfloat to double buffers\n"); printf("time delta=%f\n",delta); printf("million operations/sec=%.3f\n",NUMLOOPS*MYSIZE/delta/1000000.0); time1=my_gettime(); for(u=0 ; u<NUMLOOPS ; u++) { inbuf64ptr=inbuf64; outbuf32ptr=outbuf32; for(i=0; i<MYSIZEDIV4; i++) { *outbuf32ptr++ = (float) *inbuf64ptr++; *outbuf32ptr++ = (float) *inbuf64ptr++; *outbuf32ptr++ = (float) *inbuf64ptr++; *outbuf32ptr++ = (float) *inbuf64ptr++; } } time2=my_gettime(); delta=time2-time1; printf("\ndouble to float buffers\n"); printf("time delta=%f\n",delta); printf("million operations/sec=%.3f\n",NUMLOOPS*MYSIZE/delta/1000000.0); } double my_gettime(void) { double res; struct timeval mytv; gettimeofday(&mytv,NULL); res=mytv.tv_sec+mytv.tv_usec/1000000.0; return(res); }