Advertisement

x*1/y vs. x/y

Started by March 01, 2001 10:18 AM
14 comments, last by Promiscuous Robot 23 years, 11 months ago
Why is x*1.0/y supposedly faster than x/y? There''s a division in both, and in the first there is a division + multiplication. It seems that the first example should be slower than the second.
--------------------------I guess this is where most people put a famous quote..."Everything is funnier with monkey''s" - Unknown
if you were to add two constants, like this:
x = 4 + 4;

your compiler knows how to add two constants, and just resolves it to a single assignment:
x = 8;

i think it would be the same with multiplication:
x = 1 * y

would give you:
x = y;

of course, in your problem, you are using 1.0, which would CAST the type of variables involved to floats. so:
x = 1.0 * y;

would give you:
x = (float) y;

i think that is what is happening. (someone correct me if i''m wrong.) BUT, i doubt if floats being divided and multed are speedier than ints.

farmersckn
Advertisement
Some graphics cards and possibly CPUs are optimized to process floats. Sometimes that leads to ints being a bit slower. I have a Diamond Viper II card which runs 3d on my 700Duron no problem. But for 2d it goes slower than a PC with a 466Celeron and onboard video. That same PC can''t come close to the 3d ability my computer has.

Ben
http://therabbithole.redback.inficad.com

Multiplying by reciprocals is faster if you want to divide by a number more than once. So this:

x = x/z;
y = y/z;

is much slower than this:

r = 1/z;
x = x*r;
y = y*r;


~CGameProgrammer( );


~CGameProgrammer( ); Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.
Yup. I didn't believe it so I had to try it myself. Here's my test program:
(BTW, I completely cheezed this the first time, I've re-editted it)
    #include <iostream>#include <ctime>using std::cout;using std::endl;const int NUM_TESTS = 100000000;void f1 (double &x, double &y, double d){    x = x / d;    y = y / d;}void f2 (double &x, double &y, double d){    double r = 1.0/d;    x = x * r;    y = y * r;}int main (){    double x, y, d;    clock_t begin = clock ();    for (int i=0; i<NUM_TESTS; i++)    {        x = rand ();        y = rand ();        d = rand ();        f1 (x, y, d);    }    clock_t end = clock ();    cout << "Time for f1: " << end - begin << endl;    begin = clock ();    for (i=0; i<NUM_TESTS; i++)    {        x = rand ();        y = rand ();        d = rand ();        f2 (x, y, d);    }    end = clock ();    cout << "Time for f2: " << end - begin << endl;    return 0;}    


Here's the assembly listings for f1 and f2:
PUBLIC	?f1@@YAXAAN0N@Z					; f1EXTRN	__fltused:NEAR;	COMDAT ?f1@@YAXAAN0N@Z_TEXT	SEGMENT_x$ = 8_y$ = 12_d$ = 16?f1@@YAXAAN0N@Z PROC NEAR				; f1, COMDAT; 8    :     x = x / d; 	mov	eax, DWORD PTR _x$[esp-4]	fld	QWORD PTR [eax]	fdiv	QWORD PTR _d$[esp-4]	fstp	QWORD PTR [eax]; 9    : 	y = y / d;	mov	eax, DWORD PTR _y$[esp-4]	fld	QWORD PTR [eax]	fdiv	QWORD PTR _d$[esp-4]	fstp	QWORD PTR [eax]; 10   : }	ret	0?f1@@YAXAAN0N@Z ENDP					; f1_TEXT	ENDSPUBLIC	__real@8@3fff8000000000000000PUBLIC	?f2@@YAXAAN0N@Z					; f2;	COMDAT __real@8@3fff8000000000000000; File C:\Projects\test\test.cppCONST	SEGMENT__real@8@3fff8000000000000000 DQ 03ff0000000000000r ; 1CONST	ENDS;	COMDAT ?f2@@YAXAAN0N@Z_TEXT	SEGMENT_x$ = 8_y$ = 12_d$ = 16?f2@@YAXAAN0N@Z PROC NEAR				; f2, COMDAT; 13   : 	double r = 1.0/d;   	fld	QWORD PTR __real@8@3fff8000000000000000	fdiv	QWORD PTR _d$[esp-4]; 14   : 	x = x * r;  	mov	eax, DWORD PTR _x$[esp-4]	fld	ST(0)	fmul	QWORD PTR [eax]	fstp	QWORD PTR [eax]; 15   : 	y = y * r;	mov	eax, DWORD PTR _y$[esp-4]	fmul	QWORD PTR [eax]	fstp	QWORD PTR [eax]; 16   : }	ret	0?f2@@YAXAAN0N@Z ENDP					; f2_TEXT	ENDS 


9 instructions for f1, 10 for f2. How's the time now?

Time for f1: 12470Time for f2: 11200  


Only a slight gain, but still a gain.

If I comment-out one of the lines, so that only one computation is made, f2 is actually slightly (very slightly) slower.

So it looks like this is something to do only with 2+ divisions by the same value.

edit--to fix the stupid code mistake.

Edited by - Stoffel on March 1, 2001 10:33:59 PM
Just a small detail, but you might want to multiple by r instead of d in f2. It is generally better to compare two routines that do the same thing rather than two that do two entirely differant things.
Keys to success: Ability, ambition and opportunity.
Advertisement
If you look at the disassembly, the double r = 1.0/d; was removed completely because it wasn''t being used for anything. That could make up the difference in speed...
hey man, you forget something
probably blind...

look at your assembly, the divide in f2 is not there, why? because you dont use the variable r.

then the compiler removed that line, its why the function is much faster...

cheater!!!
cyberg- cyberg_coder@hotmail.com- http://members.xoom.com/cybergsoft
Doy. OK, I fixed it & re-editted my post. Nice catch. Guess I shouldn''t try to put out fires at work AND post here at the same time.
Make sure to test them with seperately, or the CPU can predict what the answer will be for the second calculation, and make it faster.

"Finger to spiritual emptiness underlying everything." -- How a C manual referred to a "pointer to void." --Things People Said
Resist Windows XP''s Invasive Production Activation Technology!
http://www.gdarchive.net/druidgames/

This topic is closed to new replies.

Advertisement