Weird Performance Improvement
Moderator: InsideQC Admins
21 posts
• Page 1 of 2 • 1, 2
Weird Performance Improvement
This is an odd one. Not certain if it belongs as a tutorial or a general Quake engine programming topic, as it's more of a discussion point at the moment.
By default Quake's timers use floating point, and keep frametimes as the difference between two floating point numbers (which are accumulated onto other floating point numbers throughout the engine).
The trouble with floating point numbers is that they're subject to precision loss. So I've been switching to using integers all the way through, and only converting to floating point at the last possible moment. So far so good.
But the odd thing is that I got a significant performance improvement out of it too. How significant? Framerates about doubled from just switching to integers up as far as Host_FilterTime. I've confirmed this to be the case in both DirectQ and RMQ, and have also double-checked before and after with FRAPS, so it seems as though it's not moonshine, even though common sense would say that it should be.
You'll need to use a timing function that returns time as milliseconds for this - something like timeGetTime will do - and use it instead of Sys_FloatTime, with no conversion of the milliseconds to floating point until you absolutely need to.
The critical point seems to be up as far as Host_FilterTime, so here's DirectQ's current version for reference:
Host_Frame needs to be modded to take a DWORD (or unsigned int or whatever), and you need to pass it the difference between two timeGetTime calls (instead of two Sys_FloatTime calls).
By default Quake's timers use floating point, and keep frametimes as the difference between two floating point numbers (which are accumulated onto other floating point numbers throughout the engine).
The trouble with floating point numbers is that they're subject to precision loss. So I've been switching to using integers all the way through, and only converting to floating point at the last possible moment. So far so good.
But the odd thing is that I got a significant performance improvement out of it too. How significant? Framerates about doubled from just switching to integers up as far as Host_FilterTime. I've confirmed this to be the case in both DirectQ and RMQ, and have also double-checked before and after with FRAPS, so it seems as though it's not moonshine, even though common sense would say that it should be.
You'll need to use a timing function that returns time as milliseconds for this - something like timeGetTime will do - and use it instead of Sys_FloatTime, with no conversion of the milliseconds to floating point until you absolutely need to.
The critical point seems to be up as far as Host_FilterTime, so here's DirectQ's current version for reference:
- Code: Select all
bool Host_FilterTime (DWORD time)
{
float checktime;
static DWORD dwRealTime = 0;
static DWORD dwOldRealTime = 0;
// rather than adding floats with consequent precision loss we'll instead add DWORDs
// with no precision loss, then convert the precise time to float.
dwRealTime += time;
realtime = (float) dwRealTime * 0.001f;
checktime = (float) (dwRealTime - dwOldRealTime) * 0.001f;
// prevent division by zero
if (host_maxfps.value < 1) Cvar_Set (&host_maxfps, 1);
if (!cls.timedemo && (checktime < (1.0f / host_maxfps.value)))
return false;
host_frametime = checktime;
dwOldRealTime = dwRealTime;
if (host_framerate.value > 0)
host_frametime = host_framerate.value;
else if (host_frametime > 0.1f) host_frametime = 0.1f;
return true;
}
Host_Frame needs to be modded to take a DWORD (or unsigned int or whatever), and you need to pass it the difference between two timeGetTime calls (instead of two Sys_FloatTime calls).
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
It's been a loooong time since my college days... I seem to remember that when using floating points, time is lost in shifting (floating) the decimal place in math operations.
Looking at other comments on the internet... they also mention that integers can provide a speed boost 2 to 3 times more than floats.
Makes one wonder if there are any other speed boosts to be found by switching from floats to integers... what about the rendering?
Looking at other comments on the internet... they also mention that integers can provide a speed boost 2 to 3 times more than floats.
Makes one wonder if there are any other speed boosts to be found by switching from floats to integers... what about the rendering?
Good God! You shot my leg off!
-

Junrall - Posts: 191
- Joined: Mon Sep 21, 2009 12:27 am
- Location: North West Oregon, USA
Junrall wrote:It's been a loooong time since my college days... I seem to remember that when using floating points, time is lost in shifting (floating) the decimal place in math operations.
Looking at other comments on the internet... they also mention that integers can provide a speed boost 2 to 3 times more than floats.
Makes one wonder if there are any other speed boosts to be found by switching from floats to integers... what about the rendering?
Your thoughts are the same as mine. I am going through and changing as much as I can.
Something as constant as time should definetly be an integer and not a float.
-

Mexicouger - Posts: 514
- Joined: Sat May 01, 2010 10:12 pm
andrewj wrote:I remain extremely skeptical that changing a few floats to ints can double your framerate.
Something else is going on.
Time is constantly being accounted for, So change the float to an int, and you have a speed increase, as the game isn't trying to account for those extra decimals.
But I don't think a near double of the frame rate would come out of that.
-

Mexicouger - Posts: 514
- Joined: Sat May 01, 2010 10:12 pm
Mexicouger wrote:andrewj wrote:But I don't think a near double of the frame rate would come out of that.
Maybe on a CPU restricted system.
http://red.planetarena.org - Alien Arena and the CRX engine
- Irritant
- Posts: 250
- Joined: Mon May 19, 2008 2:54 pm
- Location: Maryland
Junrall wrote:Makes one wonder if there are any other speed boosts to be found by switching from floats to integers... what about the rendering?
This I wonder as well especially on computers that are a bit floating point deficient... (read: 486 class, Cyrix 6x86, K5, Nintendo DS)
In software, the rendering has to be floating point for the BSP vertex precision IIRC. You don't want them to be int.
i should not be here
- leileilol
- Posts: 2783
- Joined: Fri Oct 15, 2004 3:23 am
Mexicouger wrote:Can you write a tutorial on this? That would be great!
It's not really something I'd be comfortable tutorializing, for a number of reasons. The main one is that Quake's timers are really something you shouldn't be messing with unless you've got a reasonable idea what you're doing, otherwise you could very quickly find yourself in deep shit with no idea of how to back out of it. A second one is that for a fully comprehensive solution you need to go through everywhere else in the engine that has a timer or a time count and modify that too. That's a lot of places. A third reason is that the svc_time message really needs to be changed as well, and that's a protocol change.
There's enough sample code and info above to enable you to figure out the basics for yourself. As it stands with that, you'll occasionally lose 1ms of time only to gain it back again in the next frame. Fixing that needs svc_time to be modified.
Junrall wrote:It's been a loooong time since my college days... I seem to remember that when using floating points, time is lost in shifting (floating) the decimal place in math operations.
Looking at other comments on the internet... they also mention that integers can provide a speed boost 2 to 3 times more than floats.
Makes one wonder if there are any other speed boosts to be found by switching from floats to integers... what about the rendering?
There's perfectly valid reasons for using either type (integers don't handle division well, for example) and on modern CPUs the FPU is pretty damn fast - potentially even faster than using integers.
This kind of thing would be very dubious for renderer speed gains unless we're talking about a software engine. You'd be far better off investing your time and effort in doing things like switching textures to formats that are actually supported in hardware and batching geometry up in vertex arrays or VBOs, and you'll get orders of magnitude more speed than you would by replacing a few poxy floats here with a few poxy integers there.
andrewj wrote:I remain extremely skeptical that changing a few floats to ints can double your framerate.
Something else is going on.
That pretty much nails it. It still smells largely like voodoo bullshit to me too. Yet I even went and double-checked it with FRAPS and there it was. The best explanation I can offer is that at higher framerates the time per frame becomes so low that FP accuracy is a factor, and Host_FilterTime is returning false more often than it should be.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
mh wrote:You'll need to use a timing function that returns time as milliseconds for this - something like timeGetTime will do - and use it instead of Sys_FloatTime, with no conversion of the milliseconds to floating point until you absolutely need to.
Maybe that's the whole point: the problem here is not handling time as floats, but the called function to retrieve the time. Would you mind to run a profiling into Visual Studio to compare the call times, mh ?
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC
(LordHavoc)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
Isn't int, at least in C, the size of a word?
Ken Thompson wrote:One of my most productive days was throwing away 1000 lines of code.
Get off my lawn!
-

dreadlorde - Posts: 268
- Joined: Tue Nov 24, 2009 2:20 am
dreadlorde wrote:Isn't int, at least in C, the size of a word?
Usually, yes. But there's no formal rule.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC
(LordHavoc)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
frag.machine wrote:dreadlorde wrote:Isn't int, at least in C, the size of a word?
Usually, yes. But there's no formal rule.
And it depends on what size a word is.
frag.machine wrote:Maybe that's the whole point: the problem here is not handling time as floats, but the called function to retrieve the time. Would you mind to run a profiling into Visual Studio to compare the call times, mh ?
I seriously doubt if this is it as timeGetTime is known to be the slowest of the available timing functions in Windows and despite that it fairly frequently returns in 0 milliseconds.
Even so, keeping it as floats all the way through and modding Sys_FloatTime to return ((float) timeGetTime () / 1000.0f) (or ((float) timeGetTime () * 0.001f)) doesn't get the improvement. The improvement is specifically when you switch Host_FilterTime and everything that calls it to milliseconds, irrecpective of the timing function.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
Really weird. I vaguely remember Carmack mentioning at some point they toyed with the idea of using fixed point integer instead floats but quickly ditched that and just jumped to FPU supported floats. Maybe back in 1995 it was a wise move, and since them everyone accepted that as true without revalidating things.
EDIT: OR, we are facing a severe performance issue with the current versions of MSVC math libs. Are you testing this with debug or release builds ?
I guess I'll do some tests myself later.
EDIT: OR, we are facing a severe performance issue with the current versions of MSVC math libs. Are you testing this with debug or release builds ?
I guess I'll do some tests myself later.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC
(LordHavoc)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
Quake2 keeps its time in miliseconds.
The main advantage of miliseconds is that your precision is the same at the start as it is at the end.
Progressively incrementing a timer like dwRealTime (if it were a float) would result in precision errors with higher framerates. The higher your framerate is, the worse it gets. When the frame rate reaches 2k/3k, your precision really starts to suffer.
Some timing bugs only appear when you set r_norefresh 1 (other than timerefresh reporting #inf fps, lol).
The main advantage of miliseconds is that your precision is the same at the start as it is at the end.
Progressively incrementing a timer like dwRealTime (if it were a float) would result in precision errors with higher framerates. The higher your framerate is, the worse it gets. When the frame rate reaches 2k/3k, your precision really starts to suffer.
Some timing bugs only appear when you set r_norefresh 1 (other than timerefresh reporting #inf fps, lol).
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
21 posts
• Page 1 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 1 guest