[comp.graphics] TSRX Performance Problems

fish@puffer.cis.ohio-state.edu (Keith Fish) (09/25/88)

> Subject: Slow graphics on Turbo SRX ???
> Date: 20 Sep 88 13:14:16 GMT

General observation: this benchmark will run instantaneously on even yesterdays
machines, so fast that the accuracy of any measurement could easily be
questioned.  Hence, I don't think this is a very good benchmark.

> The source for the silicon graphics machine follows:
> 

Notice, this program does integer, not floating point, move/draw -- not very
representative for an application that wants to run on different size displays.
Also notice, the angles are specified via an integer -- this indicates that a
look-up table is being used for the sin/cos values.
Finally, the viewing transforms are set up to exactly match the size of
the device.  IRIS libraries may be smart enough to take advantage of this.

> $include /usr/include/fgl.h
>                 call ginit
>                 call viewpo(0,1023,0,767)
>                 call ortho2(0.,1023.,0.,767.)
>                 call cursof
>                 call color(0)
>                 call clear
>                 call linewi(1)
>                 call color(7)
>                 call transl(511.,384.,0.)
>                 do 10 i=1,3600
>                         call rotate(1,'z')
>                         call move2i(0,0)
>                         call draw2i(128,0)
>           10    continue
>                 call gexit
>                 end
> 

Notice, this program does floating point move/draws -- probably more expensive
than integer operation.
Also notice, the angles are specified in floating point radians -- no look-up
table here.
Finally, the viewing transforms must really do something.

>   include '/usr/include/starbase.f1.h'
>   program b1
>   include '/usr/include/starbase.f2.h'
>   integer *4 fildes
>   integer *4 cill
>   integer *4 arg1(64),arg2(64)
>   fildes=gopen('/dev/crt'//char(0), OUTDEV, 'hp98731'//char(0), INIT)
>   arg1(1)= FALSE
>   call gescape(fildes,SWITCH_SEMAPHORE,arg1,arg2)
>   call vdc_extent(fildes,0.,0.,0.,1279.,1023.,0.)

>   call view_port(fildes,0.,0.,1023.,767.)
>   call translate2d(fildes,384.,511.)
Comment: remove the viewport() call and change the values in the translate()
call to be <639,512> (the center pixel of the HP/TSRX screen).  This will give
a 1->1 mapping between VDCs and DCs just as with the SGI benchmark.

>   PI=3.14152
>   angle=(2. * PI)/3600.
>   do 10 i=i,3600
>     call rotate2d(fildes,angle,3)
>     call move2d(fildes,0.,0.)
>     call draw2d(fildes,128.,0.)
Comment: you might try change the SGI benchmark to use floating point numbers
so that you'll be comparing oranges against oranges, not bananas.

>     call make_picture_current(fildes)
Comment: remove make_picture_current() call.  This is not needed as lines
will be drawn when the buffer fills up.  The gclose() statement will flush
anything left in the buffer.  At the least, put this call OUTSIDE of the loop.

> 10  continue
>   cill=gclose(fildes)
> end
> 
> subroutine identity2d(M)
>   real M(2,3)
>   M(1,1)=1.
>   M(1,2)=0.
>   M(1,3)=0.
>   M(2,1)=0.
>   M(2,2)=1.
>   M(2,3)=0.
> end
Comment: If Fortran has a mechanism to copy arrays quickly, then it might be
better to allocate a static Identity matrix and copy it into M whenever
identity2d() is called.

> 
> subroutine translate2d(fildes,x,y)
>   integer *4 fildes
>   real M(2,3)
>   real x
>   real y
>   call identity2d(M)
>   M(1,3)=x
>   M(2,3) = y
>   call view_matrix2d(fildes,M,PRE_CONCAT_VW)
Comment: the concat_transformation2d() call might be a better choice than the
view_matrix2d() call (ie. I'm not sure on this one).

> end
> 
> subroutine rotate2d(fildes,angle,axis)
>   integer *4 fildes
>   integer *4 axis
>   real angle
>   real M(2,3)
>   call identity2d(M)
>   M(1,1) = cos(angle)
>   M(2,1) = -sin(angle)
>   M(1,2) = -M(2,1)
>   M(2,2) = M(1,1)
>   call view_matrix2d(fildes,M,PRE_CONCAT_VW)
> end
Comment: Leverage the following C-program code to emulate a sin/cos look-up
table routine.  It is most likely faster to have a static lookup table
around (already initialized Fortran REAL array) and pull 3600*2 numbers out
of it (twice per call to rotate()) than it is to call math library routines
to calculate these intrinsics 3600*2 times.

> Greetings,
> 
> Marco Lesmeister, AE, HP Holland

I tried to send Marco mail and my comments are from the knowledge I think I've
gotten while working with TSRXs.

Keith Fish


/*
 * angle.c: Program to print out sin/cos values for angles specified in
 *          integer values of tenths-of-a-degree.
 * Compile: cc -o angle angle.c -lm
 * Usage:   angle 500 -4508 36003
 *          will give the sin/cos values for the angles 50.0, 314.92, and 0.3
 *          respectively.
 */
#include <stdio.h>
#include <math.h>
#define PI 3.1415927
static double sines[901];     /* Fortran REAL is OK, double not necessary */

main(argc,argv)
int argc; char *argv[];
{
    int i, quad, cosneg, sinneg, cosindx, sinindx, inangle, argindex=0;
    double a,c,s;

    if (argc < 2) exit(1);    /* Need at least one value to calculate */
    for (i = 0; i < 901; i++) {
        a = ((float)i * PI) / 1800.0;     sines[i] = sin(a);
    }

    while (argc > 1) {
        argc--; argindex++;         inangle = atoi(argv[argindex]);

        printf("Input= %-5d, ",inangle);
        /* Mod the angle to 0->3599 */
        i = inangle / 3600;     inangle -= (i * 3600);
        if (inangle < 0) inangle += 3600;
        /* Get which quadrant we're in and get angle to 0->900 range */
        quad = inangle / 900;
        if (quad) {    /* quad ranges from 0->3, ie. quadrants I->IV */
            i = quad * 900;
            /* If at start of quadrant II or IV, make it at end of I or III */
            if ((quad & 1) && (inangle == i)) { sinindx = 900; quad--; }
            else sinindx = inangle - i;        /* Find the modulo */
        } else sinindx = inangle;            /* Already in range */
        cosindx = 900 - sinindx;            /* Cos(a) is sin(90-a) */
        /* If in quadrants II or III, cosine is negative */
        cosneg = sinneg  = 0;
        if (quad && (quad < 3)) cosneg = 1;
        /* If in quadrants III or IV, sine is negative */
        if (quad > 1) sinneg = 1;
        /* If in quadrants II or IV, reverse sine<->cosine values */
        if (quad & 1) { i = cosindx;    cosindx = sinindx;    sinindx = i; }
        /* Look up the values in the table; make them negative if necessary. */
        c = sines[cosindx];    if (cosneg && cosindx) c *= -1;
        s = sines[sinindx];    if (sinneg && sinindx) s *= -1;
    
        printf("sin= %1.3f, cos= %1.3f\n",s,c);
    }
}
/*
 ************* END OF SAMPLE PROGRAM ****
 */