float algorithm is slow

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Netocrat

    #16
    Re: float algorithm is slow

    On Sat, 09 Jul 2005 17:35:27 -0700, websnarf wrote:
    [color=blue]
    > Wenfei wrote:[color=green]
    >> float percentage;
    >> for (j = 0; j < 10000000; j++) {
    >> percentage = sinf(frequency * j * 2 * 3.14159 / sampleFreq );
    >> buffer[totalBytes] =ceilf(volume * percentage) + volume; totalBytes++;
    >> }
    >> }[/color]
    > sinf() appears to be a Microsoft VC++ extension that computes sin() but
    > uses only 32-bit floats. Interesting that the zealots in this newsgroup
    > didn't call you on that.
    >
    > Ok, anyhow remembering our trigonometry:
    >
    > sin(a + b) = sin(a)*cos(b) + sin(b)cos(a) cos(a + b) = cos(a)*cos(b) -
    > sin(b)sin(a)
    >
    > Now we can strength reduce the argument to sinf:
    >
    > arg += (freqency*2*3.1 4159/sampleFreq);
    >
    > But that value is a constant:
    >
    > arg += deltaAngle; /* deltaAngle is precomputed as:
    > freqency*2*3.14 159/sampleFreq */
    >
    > So we can simplify this to:
    >
    > s1 = percentage*cos( deltaAngle) + c*sin(deltaAngl e);
    > c = c*cos(deltaAngl e) + percentage*sin( deltaAngle);[/color]

    You meant to subtract there, not add, I believe.
    [color=blue]
    > percentage = s1;
    >
    > And of course we can replace the cos(deltaAngle) and sin(deltaAngle) with
    > some precomputed values, and we initialize c to 1, and percentage to 0.
    >
    > This removes all the trigonometric functions altogether.[/color]

    Good suggestion. That would seem to be the major contributor to the
    calculation time, although you'd have to compare the approaches to be
    sure. It's theoretically possible that on a specially optimised machine
    sin(j*deltaAngl e) could be faster than your approach, but I very much
    doubt that this is the case on the OP's cell phone...
    [color=blue]
    > The problem is that it will have "accumulati ng accuracy" problems. These
    > problems are not trivial, because you will lose the sin^2+cos^2=1
    > property, which will start scaling your results (either upward or
    > downward) globally, which could get bad.
    >
    > A simple way to mitigate this is to split the loop into groups of, say,
    > 100 or 1000 at a time, and reset the parameters with their true
    > mathematical value with the raw sin/cos functions:
    >
    > percentage = sinf (frequency * j * 2 * 3.14159 / sampleFreq); c
    > = cosf (frequency * j * 2 * 3.14159 / sampleFreq);[/color]

    Yes and you could tune the loop grouping number beforehand by looking at
    how many cycles it takes before the values grow too inaccurate for
    your needs.

    <snip>

    Comment

    • Christian Bau

      #17
      Re: float algorithm is slow

      In article <1120955727.048 760.89010@g14g2 000cwa.googlegr oups.com>,
      websnarf@gmail. com wrote:
      [color=blue]
      > Wenfei wrote:[color=green]
      > > float percentage;
      > > for (j = 0; j < 10000000; j++) {
      > > percentage = sinf(frequency * j * 2 * 3.14159 / sampleFreq );
      > > buffer[totalBytes] =ceilf(volume * percentage) + volume;
      > > totalBytes++;
      > > }[/color]
      >
      > sinf() appears to be a Microsoft VC++ extension that computes sin() but
      > uses only 32-bit floats. Interesting that the zealots in this
      > newsgroup didn't call you on that.[/color]

      That's no surprise because it is part of C99.

      Comment

      • P.J. Plauger

        #18
        Re: float algorithm is slow

        "Christian Bau" <christian.bau@ cbau.freeserve. co.uk> wrote in message
        news:christian. bau-6F50FE.19203910 072005@slb-newsm1.svr.pol. co.uk...
        [color=blue]
        > In article <1120955727.048 760.89010@g14g2 000cwa.googlegr oups.com>,
        > websnarf@gmail. com wrote:
        >[color=green]
        >> Wenfei wrote:[color=darkred]
        >> > float percentage;
        >> > for (j = 0; j < 10000000; j++) {
        >> > percentage = sinf(frequency * j * 2 * 3.14159 / sampleFreq );
        >> > buffer[totalBytes] =ceilf(volume * percentage) + volume;
        >> > totalBytes++;
        >> > }[/color]
        >>
        >> sinf() appears to be a Microsoft VC++ extension that computes sin() but
        >> uses only 32-bit floats. Interesting that the zealots in this
        >> newsgroup didn't call you on that.[/color]
        >
        > That's no surprise because it is part of C99.[/color]

        It's even defined, but optional, in C89.

        P.J. Plauger
        Dinkumware, Ltd.



        Comment

        • Wenfei

          #19
          Re: float algorithm is slow

          I am converting Notes format to PCM format to play sounds on the ceil
          phone. It is Linux os and it is not FPU, so it is slow.


          But finally, I used a sinf lookup table, and the sound can be played
          instantly.


          Thanks for all your guys idea.


          Wenfei


          Wenfei wrote:[color=blue]
          > float percentage;
          >
          > for (j = 0; j < 10000000; j++)
          > {
          > percentage = sinf(frequency * j * 2 * 3.14159 / sampleFreq );
          > buffer[totalBytes] =ceilf(volume * percentage) + volume;
          > totalBytes++;
          > }
          >
          > Because the float variable, the above loop take 2 seconds in c or c++
          > on Linux machine. Does anybody has a solution to reduce the time?
          >
          > Thanks,
          >
          > Wenfei[/color]

          Comment

          • Tydr Schnubbis

            #20
            Re: float algorithm is slow

            E. Robert Tisdale wrote:[color=blue]
            > Wenfei wrote:
            >[color=green]
            >> float percentage;
            >>
            >> for (j = 0; j < 10000000; j++) {
            >> percentage = sinf(frequency * j * 2 * 3.14159 / sampleFreq );
            >> buffer[totalBytes] =ceilf(volume * percentage) + volume;
            >> totalBytes++;
            >> }
            >>
            >> Because the float variable, the above loop take 2 seconds in c or c++
            >> on Linux machine. Does anybody has a solution to reduce the time?[/color]
            >[color=green]
            > > cat main.c[/color]
            > #include <stdlib.h>
            > #include <math.h>
            >
            > int main(int argc, char* argv[]) {
            >
            > const
            > size_t n = 10000000;
            > float buffer[n];
            > size_t totalBytes = 0;
            > const
            > float_t frequency = 1.0;
            > const
            > float_t sampleFreq = 1.0;
            > const
            > float_t pi = 3.1415926535897 9323846;
            > const
            > float_t volume = 1.0;
            >
            > for (size_t j = 0; j < n; ++j) {
            > float_t percentage = sinf(frequency* j*2*pi/sampleFreq);
            > buffer[totalBytes] =ceilf(volume*p ercentage) + volume;
            > totalBytes++;
            > }
            >
            > return 0;
            > }
            >[color=green]
            > > gcc -Wall -std=c99 -pedantic -O2 -o main main.c -lm
            > > time ./main[/color]
            > 3.694u 0.258s 0:03.92 100.5% 0+0k 0+0io 0pf+0w[/color]
            If you are posting a version of someone's example that looks different,
            but really does the exact same thing in the exact same way, it's best if
            you state that that's what you're doing. Don't make people read your
            code and compare to figure out you didn't change the logic, nor optimize
            it at all. But sure, you version is better style.

            -Tydr

            Comment

            Working...