Fast conversions? 
Author Message
 Fast conversions?

Question:  Is "sprintf" the fastest way to convert numerical data to ascii?

We need to output ASCII postscript files of line graphics, which are
tracings of acoustic waveforms.

Using the gcc compiler (2.7.0), and gprof, we're finding that the
bottleneck here is the calls to sprintf, which is called by the "lineto"
routine, which in turn calls the "output" routine.

const int bufsize = 8192 ;
static char firsttime, buffer[8192], *bp, *eob, DATA[128] ;
static FILE *OUTFILE ;

#define output(f, newdata, len, lasttime) { \
 \
    if ( firsttime == 0 ) { \
        bp = buffer ; \
        eob = buffer + bufsize ; \
        firsttime = 1 ; \
    } \
 \
    if ( bp + len >= eob ) { \
        fwrite(buffer bp - buffer, sizeof(char), f); \
        bp = buffer ; \
    } \
 \
    memcpy(bp, newdata, len); \
    bp += len ; \
 \
    if ( lasttime )  \
        fwrite(buffer, bp buffer, sizeof(char), f); \

Quote:
}

#define lineto(x, y) { \
        int c = sprintf(DATA, "%g %g L\n", x, y); \
        output(OUTFILE, DATA, c, 0); \

Quote:
}

The above macros were originally written as functions, then converted in
Thanks in advance.

--
        Arun Chandra



Sat, 24 Oct 1998 03:00:00 GMT  
 Fast conversions?


Quote:

>Question:  Is "sprintf" the fastest way to convert numerical data to ascii?

>We need to output ASCII PostScript files of line graphics, which are
>tracings of acoustic waveforms.

>#define lineto(x, y) { \
>    int c = sprintf(DATA, "%g %g L\n", x, y); \
>    output(OUTFILE, DATA, c, 0); \
>}

Considering what you're trying to output, are you sure that floating point
is the way to go ?

Suitably scaled integer coordinates might be sufficient for your plot,
in which case sprintf("%d") will be magnitudes faster than "%g".

If you have loads of points in a small range, using a lookup table instead
of sprintf() might even be faster.

Does your PostScript file need to be humanly readable ?
Don't forget that PostScript is a computer language in its own right.
You might even coerce it to read the output of an fwrite() properly
(granted, it won't be very portable, unless you happen to be sure your
C compiler uses an IEEE representation).

It is feasible under PostScript level 1, and even easier with
level 2 filters.
--
[nosave]<http://www.eleves.ens.fr:8080/home/espie/index.html>
microsoft network is EXPLICITLY forbidden to redistribute this message.
`Moon purismu powa, make up.... Tsuki ni kawatte, oshiokiyo !'



Sat, 24 Oct 1998 03:00:00 GMT  
 Fast conversions?


[How does one optimize the following code]
const int bufsize = 8192 ;
static char firsttime, buffer[8192], *bp, *eob, DATA[128];
static FILE *OUTFILE;

void
output(FILE * f, char * newdata, int len, int lasttime) {

    if ( firsttime == 0 ) {
        bp = buffer;
        eob = buffer + bufsize;
        firsttime = 1;
    }

    if ( bp + len >= eob ) {
        fwrite(buffer, bp - buffer, sizeof(char), f);
        bp = buffer;
    }

    memcpy(bp, newdata, len);
    bp += len;

    if ( lasttime )
        fwrite(buffer, bp - buffer, sizeof(char), f);

Quote:
}

void
lineto(double x, double y) {
        int c = sprintf(DATA, "%g %g L\n", x, y);
        output(OUTFILE, DATA, c, 0);

Quote:
}

Optimization 1:
        interprocedural constant propagation: lasttime is always
        0, so why bother doing the test.

Possible Optimization 2:
        can you identify the first time lineto is called? If so,
        you can initialize bp & eob using a different function.

Possible Optimization 3:
        How many digits of precision do you _REALLY_ need?
        If I remember my postscript correctly, you can change the coordinate
        system inside postscript itself. So, if you really need 4 digits
        of precision scale up your coordinate system so that by 1000.
        Then use "%d" instead of "%g", so
                int c = sprintf(DATA, "%d %d L\n", (int)x, (int)y);

Possible Optimization 4:
        Can postscript accept hexadecimal (base 16) numbers? (Wish
        I had my manual with me). If so, use "%x" instead of "%d".
        So
                int c = sprintf(DATA, "0x%x 0x%x L\n", (int)x, (int)y);

Possible Optimization 5:
        Roll your own version of sprintf(...0x%x...). Its pretty simple to
        write, if you ignore portability

              void
              lineto(double x, double y) {
                const char *   cvt = "0123456789abcdef";
                static char *  templ = "0xdddddddd 0xdddddddd L\n";
                char *         end0 = templ[9];
                char *         end1 = templ[20];
                unsigned       ux = (unsigned)x;
                unsigned       uy = (unsigned)y;
                int            i;

                for( i = 0; i < 8; i ++ ) {
                  *end0 = cvt[ux&0xf];
                  *end1 = cvt[uy&0xf];
                  end0--;
                  ux >>= 4;
                  uy >>= 4;
                }
                output(OUTFILE, templ, 24, 0);
              }

Possible Optimization 6:
        and of course now you can constant propagate the 24....
        giving an output that looks like
              void
              output_ip(FILE * f, const char * newdata )
              {
                if ( bp + 24 >= eob ) {
                  fwrite(buffer, bp - buffer, sizeof(char), f);
                  bp = buffer;
                }
                memcpy(bp, newdata, 24);
                bp += 24;
              }

Possible Optimization 7:
        You're trying to do file buffer management yourself.
        On many operating systems, that is best left to the OS.
        Why not just use fputs()?
        Some compilers will inline that call, so you may not even see
        the function call overhead.
        Alternatively, use fputc() (if, and ONLY IF the compiler
        inlines that call, though)
--
------------------------------------------------------------------------------
| Mayan Moudgill                  | These are _MY_ opinions. Any resemblance |

------------------------------------------------------------------------------



Mon, 26 Oct 1998 03:00:00 GMT  
 Fast conversions?

[floating-point conversion speed problems incorrectly handled by double buffering]

You completely misunderstand the workings of the standard i/o library.
Its prime purpose is to provide user-level (vs kernel) buffering of i/o.
You will get better performance with the following:

# define        lineto(X, Y)    fprintf (OUTFILE, "%e %e L\n", X, Y)

%e format might be implemented quicker than %g format.
If you like, you might try using a larger buffer for OUTFILE by calling setvbuf(),
but I don't think this will have much effect.

Correct floating-point conversion is a difficult problem; I would
not attempt to do it off-hand.

If integral coordinates are sufficient, a further speedup is possible with

# define        lineto(X, Y)    fprintf (OUTFILE, "%d %d L\n", (int) X, (int) Y)

Konrad Schwarz



Mon, 26 Oct 1998 03:00:00 GMT  
 Fast conversions?

Quote:

> Question:  Is "sprintf" the fastest way to convert numerical data to ascii?

> We need to output ASCII PostScript files of line graphics, which are
> tracings of acoustic waveforms.

> Using the gcc compiler (2.7.0), and gprof, we're finding that the
> bottleneck here is the calls to sprintf, which is called by the "lineto"
> routine, which in turn calls the "output" routine.

Are you certain that sprintf() is slower than fwrite()?  Typically disk
access is much slower then almost anything else.  

There is no portable way to speed up the sprintf() calls.  Many compilers
support functions such as ftoa() or fcvt().  These are often faster than
sprintf() (when they are available), but you may buy yourself portability
problems in the future.

--
#####################################################################

Emmenjay Consulting                 http://www.hutch.com.au/~emmenjay
#####################################################################



Sat, 31 Oct 1998 03:00:00 GMT  
 Fast conversions?

Quote:


>Are you certain that sprintf() is slower than fwrite()?  Typically disk
>access is much slower then almost anything else.  

>There is no portable way to speed up the sprintf() calls.  Many compilers
>support functions such as ftoa() or fcvt().  These are often faster than
>sprintf() (when they are available), but you may buy yourself portability
>problems in the future.

Indeed.  Or they may be slower than sprintf.  An implementor that has
spent a long time tweeking printf does not want to maintain another
floating point formatter.  If he is asked to supply these routines for
compatibility reasons he will just code them as call to sprintf().
For any implemention there is almost some technique faster than
sprintf(), but you need some solid evidence before resorting to it
because it will certainly have to be rewritten repeatedly.  


Tue, 03 Nov 1998 03:00:00 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. Fastest Conversion Method?

2. Fast conversion between time_t and struct tm?

3. fast conversion of integers to strings

4. Fast conversion of array from (unsigned char) to (int) ?

5. How to do type conversion in a fast way

6. Fastest rounding with conversion

7. Fast Binary to ASCII (Decimal) Conversion

8. faster strcat (and/or faster string append in C++)

9. faster,faster

10. Faster faster

11. C to Pascal Conversion (Was: Pascal to C Conversion)

12. String conversion and double-to-string conversion

 

 
Powered by phpBB® Forum Software