CGTalk > Software > Autodesk 3ds max > 3dsMax SDK and MaxScript
Login register
Thread Closed share thread « Previous Thread | Next Thread »
 
Thread Tools Search this Thread Display Modes
Old 05-26-2008, 11:10 AM   #1
noontz
Older Member
 
noontz's Avatar
portfolio
Steffen Dyhr-Nielsen
noontz
Roedkaersbro, Denmark
 
Join Date: Dec 2007
Posts: 23
Question Optimization ideas needed

Code:
undo off ( with redraw off for i = 1 to total do ( l = copy ny l.transform = pos[i] attach olleaves l ) )

Hi.. This loop is from a kind of scatter thing where "pos" is an array of matrix3 & "ny" is the object Im scattering ( attaching to "olleaves" )

This works, but is extremely slow.. Any clues on how to speed it up? ( The help file dried out quiet quickly on optimization, and this forum houses braincapacity beyond my imagination )

Thx in advance.. Steffen..
 
Old 05-26-2008, 12:20 PM   #2
davestewart
Repeat-customer
 
davestewart's Avatar
Dave Stewart
Animator / scripter
United Kingdom
 
Join Date: Sep 2004
Posts: 488
I did a quick test with spheres, and replaced your loop code:

Code:
ny.transform = pos[i] meshop.attach olleaves ny deleteSourceNode:false


Taking out the copy made it 3 times quicker on average
__________________
Portfolio | Keyframes and Code

Last edited by davestewart : 05-26-2008 at 12:22 PM.
 
Old 05-26-2008, 12:28 PM   #3
noontz
Older Member
 
noontz's Avatar
portfolio
Steffen Dyhr-Nielsen
noontz
Roedkaersbro, Denmark
 
Join Date: Dec 2007
Posts: 23
Thumbs up

Hi Dave..

Your answer is just as fast as your solution Thanks so much!!!
I thought I would be out in some kind of facearray stuff to avoid loading "ny" all the time..

This one is going public so Im not the only one thankfull
 
Old 05-26-2008, 12:41 PM   #4
davestewart
Repeat-customer
 
davestewart's Avatar
Dave Stewart
Animator / scripter
United Kingdom
 
Join Date: Sep 2004
Posts: 488
Great stuf
__________________
Portfolio | Keyframes and Code
 
Old 05-26-2008, 01:32 PM   #5
noontz
Older Member
 
noontz's Avatar
portfolio
Steffen Dyhr-Nielsen
noontz
Roedkaersbro, Denmark
 
Join Date: Dec 2007
Posts: 23
Unhappy

Hi Dave...

For what ever crazy reason im afraid your loop doesnt do the job, when implemented in the rest of my code.. On a test I actually get a slowdown from 8 minutes to 10 minutes, but this could be due to something else, donno ??? ( 7.500 iterations ) Anyway these runtimes are crazy compared to the realtime feedback in for instance the scatter utility, so there must be something hidden under the hood..
 
Old 05-26-2008, 02:10 PM   #6
davestewart
Repeat-customer
 
davestewart's Avatar
Dave Stewart
Animator / scripter
United Kingdom
 
Join Date: Sep 2004
Posts: 488
OK, 7500 sounds like a lot!

Well I don't have much experience with large datasets, but I would suspect that the problem might lie in the fact that as an object's size increases, it becomes increasingly expensive to perform operations on it.

Why don't you try doing, say, 10 iterations of 750 (creating 10 new objects) then a further 10 iterations to attach these 10 new objects together.

It may be that the square root of 7500 might be the best iteration to go for (ie, 86 loops, then, 86 more to attach)

You could store a timestamp after each process in the loop to prove (or disprove) the point

Dave
__________________
Portfolio | Keyframes and Code
 
Old 05-26-2008, 02:52 PM   #7
Bobo
Krakatoa Guy
 
Bobo's Avatar
Borislav Petrov
Product Specialist
Thinkbox Software
Vancouver, Canada
 
Join Date: Mar 2002
Posts: 5,327
The trouble with attachments is that the Undo buffer gets filled up really fast - each attach operations accumulates the previous version of the mesh, so it grows exponentially.

Thus, if you do not intend to perform an undo after that, you should better add with undo off () around the code. See "How to Make It Faster?" chapter in the MAXScript Reference - the second example in the "Disable Undo system when possible" (at least in the Max 2008 and 2009 version) shows the difference. On my ancient 800MHz system where the original test was performed about 5 years ago, it made the code 20 times faster...
__________________
Bobo
 
Old 05-26-2008, 03:07 PM   #8
SyncViewS
IC.Developer
 
SyncViewS's Avatar
Enrico Gullotti
Technical Artist and Programmer
United Kingdom
 
Join Date: Dec 2004
Posts: 344
Hi noontz,
I may have found something that could help you with the speed issue: use the "maxOps.CloneNodes", in place of "copy".
Here two sample scripts and comparison.

First version with "copy" -> 107.109 seconds
Code:
( -- init number of scattered objects iNumObjects = 10000 -- init the transfom matrix array am3Transform = #() am3Transform[iNumObjects] = matrix3 0 -- build the transform matrix array for i = 1 to iNumObjects do ( am3Transform[i] = matrixFromNormal(normalize (random [-1, -1, -1] [1, 1, 1])) am3Transform[i] = translate am3Transform[i] (random [-100, -100, -100] [100, 100, 100]) ) -- create sample object to scatter oSample = box() -- init the scattered objects array aoScatter = #() aoScatter[iNumObjects] = oSample iTimeStart = timeStamp() -- scatter sample object undo off ( with redraw off for i = 1 to iNumObjects do ( oTemp = copy oSample oTemp.transform = am3Transform[i] aoScatter[i] = oTemp ) ) iTimeStop = timeStamp() format "Processing took % seconds\n" ((iTimeStop - iTimeStart) / 1000.0) ) -- Processing took 107.109 seconds


Alternate version with "maxOps.CloneNodes" -> 46.828 seconds
Code:
( -- init number of scattered objects iNumObjects = 10000 -- init the transfom matrix array am3Transform = #() am3Transform[iNumObjects] = matrix3 0 -- build the transform matrix array for i = 1 to iNumObjects do ( am3Transform[i] = matrixFromNormal(normalize (random [-1, -1, -1] [1, 1, 1])) am3Transform[i] = translate am3Transform[i] (random [-100, -100, -100] [100, 100, 100]) ) -- create sample object to scatter oSample = box() -- init the scattered objects array aoScatter = #() aoScatter[iNumObjects] = oSample iTimeStart = timeStamp() -- scatter sample object -- NOTE: do not use undo off, according to the MAXScript reference it crashes -- Max if an undo is performed after this operation. with redraw off ( for i = 1 to iNumObjects do ( maxOps.CloneNodes oSample offset:[0,0,0] expandHierarchy:false cloneType:#copy newNodes:&aoTemp aoTemp[1].transform = am3Transform[i] aoScatter[i] = aoTemp[1] ) ) iTimeStop = timeStamp() format "Processing took % seconds\n" ((iTimeStop - iTimeStart) / 1000.0) ) -- Processing took 46.828 seconds


The alternate version required less than half time.
I hope this helps.
 
Old 05-26-2008, 04:11 PM   #9
noontz
Older Member
 
noontz's Avatar
portfolio
Steffen Dyhr-Nielsen
noontz
Roedkaersbro, Denmark
 
Join Date: Dec 2007
Posts: 23
Thumbs up

Hi all..

Thanks for your efforts. I allways feel a good spirit in this forum!

@ Bobo: Youve saved my ### before, but as you see in the initial code, I allready went through the help content ( unless Im using the wrong syntax/scope offcourse )

@ Dave & SyncView: Ill go through both & maybe a combo & see what happens..

Ill be back with some results & code. ( Im a little busy ATM so please give me a few days )

Thx again to all three of you!

Last edited by noontz : 05-26-2008 at 04:17 PM.
 
Old 05-26-2008, 05:39 PM   #10
noontz
Older Member
 
noontz's Avatar
portfolio
Steffen Dyhr-Nielsen
noontz
Roedkaersbro, Denmark
 
Join Date: Dec 2007
Posts: 23
Smile

Code:
with redraw off for i = 1 to total do ( maxOps.CloneNodes ny offset:[0,0,0] newNodes:&l l = l[1] undo off ( l.transform = pos[i] attach olleaves l ) )


Well that maxOps dropped the runtime to the half as pointed out! Great! I moved the undo off into the loop, as theres a known issue with this & maxOps.CloneNodes.

@ Dave: The attach iterations work linear: 10000 iterations takes 100 times longer than 100 iterations, so there doesnt seem to be any gain on grouping them.

Last edited by noontz : 05-26-2008 at 08:56 PM. Reason: checked up on chunking up iterations
 
Old 05-26-2008, 09:22 PM   #11
davestewart
Repeat-customer
 
davestewart's Avatar
Dave Stewart
Animator / scripter
United Kingdom
 
Join Date: Sep 2004
Posts: 488
Well, here in London it's a bank holiday (so no work), and it's pissing down with rain (so no play).

I've also been working on a timestamping / benchmarking struct in the past few weeks, so this seemed like a perfect case study opportunity!

The results are actually really interesting but with the concept and data in front of you, perhaps not that surprising.

The good news is that I've managed to speed things up 30 times!

Turns out the slowdown IS related caused by the size of the mesh you're attaching the mesh to, so when in a loop, this has a rather nasty cumulative effect.

Also, the square root DOES turn out (4 times out of 5 anyway) to be the most efficient number to split the loop up into.

Anyway - I put the results up on my blog, so feel free to take a look.

Cheers,
Dave
__________________
Portfolio | Keyframes and Code
 
Old 05-29-2008, 12:44 AM   #12
erilaz
Stealthy Tea Monkey
 
erilaz's Avatar
portfolio
Martin Brennand
VFX Artist
Melbourne, Australia
 
Join Date: Jun 2002
Posts: 13,756
Hot damn, I love optimised code.

Perhaps we should have a general discussion of what makes things faster/less memory intensive.
__________________
"There Really is No Secret"
Martin Brennand - mocha Product Manager - Imagineer Systems
 
Old 05-29-2008, 01:17 AM   #13
ZeBoxx2
Lord of the posts
 
ZeBoxx2's Avatar
Richard Annema
Caustic Graphics / SplutterFish
Groningen, Netherlands
 
Join Date: Jul 2006
Posts: 1,461
Quote:
Originally Posted by erilaz
Perhaps we should have a general discussion of what makes things faster/less memory intensive.

The MaxScript Help file is a good start, then; see the "How to make it faster?" topic %)
 
Old 05-29-2008, 01:19 AM   #14
erilaz
Stealthy Tea Monkey
 
erilaz's Avatar
portfolio
Martin Brennand
VFX Artist
Melbourne, Australia
 
Join Date: Jun 2002
Posts: 13,756
Quote:
Originally Posted by ZeBoxx2
The MaxScript Help file is a good start, then; see the "How to make it faster?" topic %)


Oh I'm aware of that, I think it would be interesting if other methods have come up in people's scripting journeys to expand the manual's recommendations.
__________________
"There Really is No Secret"
Martin Brennand - mocha Product Manager - Imagineer Systems
 
Old 05-29-2008, 02:45 AM   #15
ZeBoxx2
Lord of the posts
 
ZeBoxx2's Avatar
Richard Annema
Caustic Graphics / SplutterFish
Groningen, Netherlands
 
Join Date: Jul 2006
Posts: 1,461
Alright... here's a few I recall off the top of my head - haven't dug into my scripts to find old comments on oddball speed-ups.


At one point I needed random point3 integers, lots and lots of them. The problem is, random <point3> <point3> makes the values within those point3s floats.
So...

-- --------------------------------------------------
Code:
startTime = timeStamp() for i = 1 to 3000000 do ( randP3 = random [0,0,0] [10,10,10] randP3.x = randP3.x as integer randP3.y = randP3.y as integer randP3.z = randP3.z as integer ) format "time: %\n" ((timeStamp() - startTime) / 1000.0) time: 16.854 startTime = timeStamp() for i = 1 to 3000000 do ( randP3x = random 0 10 randP3y = random 0 10 randP3z = random 0 10 randP3 = [randP3x,randP3y,randP3z] ) format "time: %\n" ((timeStamp() - startTime) / 1000.0) time: 12.629

Subtle, but I actually had to generate tens of millions; becomes a little less subtle. This is on a slower machine, though

-- --------------------------------------------------

Here's another favorite.. UI updates. UI updates are slow.
ProgressBars are a very popular method of showing, well, progress. But updating them all the time is slow. Update them only periodically. For example, only if the update would actually show in the progress bar (depending on its width).
Code:
rollout test "test" ( progressbar pb_test ) createDialog test pb = test.pb_test -- pre-initialize, lest we incur a speedhit for getting it from the rollout all the time. startTime = timeStamp() for i = 1 to 1000000 do ( pb.value = (i / 1000000.0) * 100 ) format "time: %\n" ((timeStamp() - startTime) / 1000.0) time: 29.012 startTime = timeStamp() for i = 1 to 1000000 do ( if (mod i 7500 == 0) then ( -- 7500 in this case depending on progressbar width of 133px pb.value = (i / 1000000.0) * 100 ) ) pb.value = 100 -- make sure it does read 100% at the end format "time: %\n" ((timeStamp() - startTime) / 1000.0) time: 2.043 -- lets' get rid of that mult as well startTime = timeStamp() for i = 1 to 1000000 do ( if (mod i 7500 == 0) then ( -- 7500 in this case depending on progressbar width of 133px pb.value = (i / 10000.0) ) ) pb.value = 100 format "time: %\n" ((timeStamp() - startTime) / 1000.0) time: 1.943


-- --------------------------------------------------

Another one, no code for obvious reasons.. f you have an intense loop with a lot of if-tests to validate a value; for example to prevent OOB accesses or so, consider try/catch. Typically try/catch is slower than if-tests, but with enough if-tests, try/catch may just win. Pretty rare, and probably not recommended practice; but if you're going for speed...

-- --------------------------------------------------

An old favorite... always name the objects you create, as max will otherwise waste time trying to find a unique name for the new object (obviously only do this if you have no fear of creating non-unique names). This assumes cloneNodes cannot be used for whatever reason.


Code:
delete objects startTime = timeStamp() undo off ( for i = 1 to 5000 do ( newSphere = geoSphere() ) ) format "time: %\n" ((timeStamp() - startTime) / 1000.0) time: 60.226 delete objects startTime = timeStamp() undo off ( for i = 1 to 5000 do ( newSphere = geoSphere name:("mySphere" + i as string) ) ) format "time: %\n" ((timeStamp() - startTime) / 1000.0) time: 34.149

Last edited by ZeBoxx2 : 05-29-2008 at 02:48 AM.
 
Thread Closed share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 02:30 PM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.