SSE Speed test

BlitzMax Forums/BlitzMax Programming/SSE Speed test

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

I have been working on ways to improve performance of vector/matrix operations without having to resort to inline coding of the functions.

I have seen/written the various other libraries written in BMax but have been unhappy with the overall performance with pure max generated code.

Soo I started experimenting with implementing my own Objects in pure C code. It has also opened up the ability to utilize SSE extensions intrinsics exposed by GCC.

So I wrote a simple test BlitzMax Module in C that exposes the TVector3 object. This is a Max object but written in C. It uses some C compiler tricks to maximize performance. No StackFrames in particular when dealing with straight x87 FPU code. I pretty much lost this gain when I implmented the next part but the code is on par if not bit better than straight bmx code but not much.

The big gain comes from this..

There is also a global switch that when enabled the vector math is done via SSE extentions(havent figured out how I want to implement SSE detection).. On my Dual Core I am seeing speed up 30-33%. I am bit worried on inconsistent timing but is stable on my dual core machine.


(Win32 test)
http://smokenmirrors.com/Downloads/test.zip

BMX code so you can see whats going on. Just simple adds two vectors in loop and times them.

TVector which is coded in max with similar logic to a TVector3 which is coded in C.

Unlike many of the other libraries the approach of this library is that a Vector is not immutable. ie. Operations dont make new Vector Objects they Operate on the object. The reason for this approach vs. other is to avoid random invokation of garbage collection or memory allocations. It requires more thought and planing when using but it will create a much more consistent frame when dealing with large amounts of objects and extensive amounts of math since you need to be careful of allocations. This also applies for none GC languages when using heap based objects.

This sample is test for me to see some metrics on various machines before I spend much time coding out the more important usage of this which is to get SSE enabled Matrix functions as well as vector normalization.

This is coded currently to only work on PentiumIV(AMD?) or better due to switches and way I am currently building the module with but should eventually be able to be done so that it will automatically scale on X86 Processers as well as be cross compilable to PowerPC(does anyone use these)

Any test results/success or failure with machine specs would be appreciatd. Worst it should do is crash with illegal op code if SSE intructions are invoked on invalid platform.

Thanks
Doug



SuperStrict
Framework brl.StandardIO
Import dbs.vector

Extern "win32"
	Function QueryPerformanceFrequency(LARGE_INTEGER:Long Var)
	Function QueryPerformanceCounter(LARGE_INTEGER:Long Var)
EndExtern


Global freq : Long
Global startcount : Long 
Global stopcount : Long 
QueryPerformanceFrequency(freq)

Function StartTimer()
	QueryPerformanceCounter(startcount)
End Function
Function StopTimer:Double()
    QueryPerformanceCounter(stopcount)
    Return Double(stopcount-startcount)/(Double(freq)/1000)
End Function




Type TVector
	Field X:Float
	Field Y:Float
	Field Z:Float
	
	Method ToString:String()
		Return "x="+X+ " y="+Y+" z="+Z
	End Method	
	
	Method Add:TVector(v1:TVector, v2:TVector)
		X=V1.X+V2.X
		Y=V1.Y+V2.Y
		Z=V1.Z+V2.Z	
		Return Self			
	End Method
End Type

Const MAXLOOP:Int= 200000000

Function TestCObject(sse:Int)
	EnableSSE(sse)
	Print ""
	If sse 
		Print("C Vector SSE Enabled")
	Else
		Print("C Vector SSE Disabled")
	End If
		
	Local v1:TVector3 = New TVector3
	v1.X=1
	v1.Y=2
	v1.Z=3
	Local v2:TVector3 = New TVector3
	v2.X=4
	v2.Y=5
	v2.Z=6
	Local v3:TVector3 = New TVector3


	StartTimer()
	For Local i:Int=0 To MAXLOOP
		v3.Add(v1,v2)
	Next
	Local secs:Double = StopTimer()
	Print  "x="+v3.X+ " y="+v3.Y+" z="+v3.Z
	Print "C Code Time ="+secs +"ms"
	Print "Ops ="+(MaxLoop)/secs +" per ms"
	Print ""
End Function

Function TestBMaxObject()
    Print ""
    Print("BMX test Object")
	Local vv1:TVector = New TVector
	vv1.X=1
	vv1.Y=2
	vv1.Z=3
	Local vv2:TVector = New TVector
	vv2.X=4
	vv2.Y=5
	vv2.Z=6
	Local vv3:TVector = New TVector
    StartTimer()
	For Local i:Int=0 To MAXLOOP
		vv3.Add(vv1,vv2)
	Next
	Local secs:Double = StopTimer()
	Print  "x="+vv3.X+ " y="+vv3.Y+" z="+vv3.Z
	Print "BMX Time="+secs +"ms"
	Print "Ops ="+(MaxLoop)/secs +" per ms"
	Print ""
End Function

Print "Starting Tests"
TestCObject(False)
TestBMaxObject()
TestCObject(True)
Input("Press Enter to Exit")