Notifications
Clear all

[Closed] Optimization ideas needed

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 I´m 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…

21 Replies

I did a quick test with spheres, and replaced your loop code:

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

Taking out the copy made it 3 times quicker on average

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 I´m not the only one thankfull

Great stuf

Hi Dave…

For what ever crazy reason im afraid your loop doesn´t 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…

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

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…

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


 (
 	-- 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
" ((iTimeStop - iTimeStart) / 1000.0)
 )
 
 -- Processing took 107.109 seconds

 

Alternate version with “maxOps.CloneNodes” -> 46.828 seconds


 (
 	-- 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
" ((iTimeStop - iTimeStart) / 1000.0)
 )
 
 -- Processing took 46.828 seconds

 

The alternate version required less than half time.
I hope this helps.

Hi all…

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

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

@ Dave & SyncView: I´ll go through both & maybe a combo & see what happens…

I´ll be back with some results & code. ( I´m a little busy ATM so please give me a few days )

Thx again to all three of you!

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 there´s a known issue with this & maxOps.CloneNodes.

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

Page 1 / 2