[Closed] intersectRay speed – 10x times slower in new Max?
Hello, I’m writing a tool which uses the intersectRay method very often. I was using Max 2014 and 2015 for testing, but now I’m kinda shocked after running it in Max 2017 and 2018. Looks like v2017 is like 5 times slower than 2014 and 2015, but Max 2018 is like 10+ times slower… I don’t have the opportunity to test it on Max 2019.
Could you tell me what is going on here? I’ve prepared a small benchmark, please test it and paste your results.
(
rollout inRaySpeedTest "test"(edittext etext)
fn getMaxVersion = return (2000+(((maxVersion())[1]/1000)-2))
with undo off
(
max create mode
local tests = 10
local avgTime = 0.0
for t in 1 to tests do
(
delete objects
gc()
local gs=GeoSphere pos:[-15,-2.5,0] isSelected:on radius:25 segs:200
addModifier gs (Noisemodifier strength:[8,8,8] scale:15 seed:t)
converttomesh gs
r = ray [0,0,100] [0,0,-1]
aTime = timestamp()
local iray = intersectray gs r
bTime = timestamp()
point pos:(iray.pos)
print (t as string+" : "+((bTime-aTime) as string + " ms"))
avgTime += (bTime-aTime)
completeRedraw()
)
avgTime = (avgTime as float) / (tests as float)
createdialog inRaySpeedTest width:260
inRaySpeedTest.etext.text = "3ds Max "+(getMaxVersion() as string)+(", averageTime = "+avgTime as string+" ms")
)
)
My results:
3ds Max 2014, averageTime = 7.4 ms
3ds Max 2015, averageTime = 7.6 ms
3ds Max 2016, averageTime = 7.8 ms
3ds Max 2017, averageTime = 64.8 ms
3ds Max 2018, averageTime = 127.2 ms
I confirm the issue. on my machine your test is about 10 times slower with version 2018 vs 2016.
So, the ray intersects slower but better. Not with greater accuracy, but just better
it’s like many new features… UI for example. Not faster, not less flickering, not adjustable well for 2K/4K monitors, not clearer, not easier bind to controllers/events/callbacks… just better
Confirmed. Might be part of the MXS improvements that started with Max 2017.
3ds Max 2014, averageTime = 5.9 ms
3ds Max 2015, averageTime = 5.2 ms
3ds Max 2016, averageTime = 5.6 ms
3ds Max 2017, averageTime = 44.6 ms
3ds Max 2018, averageTime = 102.3 ms
3ds Max 2019, averageTime = 109.1 ms
Looks like with that release a boycott against MXS was started.
But don’t say it too loud because you’ll be asked to show a “real case” where this affects the performance as they have profiled the code improvements and have found nothing where this applies. Sad.
This is ridiculous. Actually I’m struggling with this issue using 3ds Max SDK.
This particular function
int Mesh::IntersectRay (Ray &ray, float &at, Point3 &norm)
runs 4x slower compiled to Max 2017 than 2014. Looks like I need to write my own intersectRay function.
BTW, I briefly discussed this with Larry Minton and he points out that with 2017, a kD tree like acceleration structure was introduced, which takes time to set up. The test script above is a worst-case scenario, since it creates an object, intersects one ray and then discards everything.
If you do the same for 200 rays per loop, you start to see the speedup.
i have similar methods which might pre-collect some data for quicker calculations after that.
but i always give a choice to the user – cache this data or calculate on-the-fly.
for example, i don’t need to make a kdtree if i need to find closest point for ten points.
Ok, any acceleration structure takes time to build. But shouldn’t we see a huge performance improvement right after the first iteration?
Okay, it looks like it really speed things up in the next iterations, but the first raycast is terribly slow, that’s why it is useless for me, because I need to shot just a few rays onto big number of different meshes.
(
rollout inRaySpeedTest "test"(edittext etext)
fn getMaxVersion = return (2000+(((maxVersion())[1]/1000)-2))
with undo off
(
max create mode
local tests = 5
local avgTime = 0.0
for t in 1 to tests do
(
delete objects
gc()
local gs=GeoSphere pos:[0,0,0] isSelected:on radius:30 segs:200 wirecolor:blue
addModifier gs (Noisemodifier strength:[0,10,10] scale:15 seed:t)
converttomesh gs
local loopTime = 0
for cast in 1 to 100 do
(
r = ray [-25.0 + (cast / 100.0)*50.0,0,100] [0,(random -0.05 0.05),-1]
aTime = timestamp()
local iray = intersectray gs r
bTime = timestamp()
if iray != undefined then
point pos:(iray.pos) size:3 wirecolor:yellow
loopTime += (bTime-aTime)
print (cast as string+" : "+(bTime - aTime) as string+" ms")
)
loopTime /= 100
avgTime += loopTime
completeRedraw()
)
avgTime = (avgTime as float) / (tests as float)
createdialog inRaySpeedTest width:260
inRaySpeedTest.etext.text = "3ds Max "+(getMaxVersion() as string)+(", averageTime = "+avgTime as string+" ms")
)
)
I’ve also noticed that when I change the ray position, but the direction remains the same (so basically delete the (random -0.05 0.05) and replace with 0 ) the performance gain disappears.
And in 2018 a second KDTree was implemented as a backup, that’s why it is 2X/3X slower compared with 2017.