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);
}

Reply via email to