Multithread in Maxscript

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

THREAD CLOSED
 
Thread Tools Search this Thread Display Modes
  11 November 2011
Multithread in Maxscript

Not once I seen peoples argue that we have multithreads in Maxscript.
Of course we can run .net threads (that execute scripts) in Max but
how does this make Maxscript truly multithread?

I'll be happy if someone prove this somehow with sample code.
Thanks
__________________
* everyone can win previous war
 
  11 November 2011
well, what is your definition of 'truly multithreaded'? What kind of proof do you expect to see?
 
  11 November 2011
Here some sample code I did while doing a mini challenge a while back:

http://forums.cgsociety.org/showpos...23&postcount=79

And remember, multi thread != multicore. How threads are distributed over the cores is something the OS takes care of.
__________________
The GPU revolution will not be rasterized! - http://www.jdbgraphics.nl
 
  11 November 2011
Thanks to both.

Rotem, good question multithreads are not very clean subject to me, so it is possible some lack of understanding from my side, maybe Jonathan's example answer already, s'd check, but here is my definition.

Lets say i have 2 blocks of codes taskA() and taskB(), each one do different job and each one if runs alone will finish it work for 1 second. But if those tasks run at 2 threads they s'd finish for 1 or closer to 1 sec, and for sure not for 2 seconds, right?

Also lets say taskA update some data, global variables for instance, and that happens at time 0.1 sec after it start, when taskB s'd can get fresh data at that time or very soon after that, i.e. not just at the end of taskA (after 1 sec.).

In other words, i suspect that the code blocks executed sequential, and that is not 'truly multithreaded', but of'cuz i might be wrong, and this is what i want to clarify to myself.

Thanks in advance!
__________________
* everyone can win previous war
 
  11 November 2011
The code blocks are not executed sequentially, they are indeed executed in parallel.
The degree to which code is executed faster as more threads are used is known as the code's scalability, and is very dependent on the code being executed.
If a block of code executed in X seconds on one thread and in X/N seconds on N threads, then it is said that the code scales linearly, which is the best possible situation.
The ideal number of threads to use for a particular task depends heavily on the code and on the hardware. Most likely using 100 threads for a certain task will be slower than using 10 threads due to the overhead of starting and managing that many threads.

As for code blocks accessing the same data together, it is up to you to ensure your code is 'thread-safe', and does not cause fatal collisions. There was a thread on this topic not long ago.
Maxscript does not currently contain any instruments to help you with this task, as it
was not designed for multithreaded execution, but as far as I remember, the main guideline was that you must not redraw the viewport from a background thread.
 
  11 November 2011
Thumbs up

Originally Posted by lo: The code blocks are not executed sequentially, they are indeed executed in parallel.
The degree to which code is executed faster as more threads are used is known as the code's scalability, and is very dependent on the code being executed.
If a block of code executed in X seconds on one thread and in X/N seconds on N threads, then it is said that the code scales linearly, which is the best possible situation.
The ideal number of threads to use for a particular task depends heavily on the code and on the hardware. Most likely using 100 threads for a certain task will be slower than using 10 threads due to the overhead of starting and managing that many threads.

As for code blocks accessing the same data together, it is up to you to ensure your code is 'thread-safe', and does not cause fatal collisions. There was a thread on this topic not long ago.
Maxscript does not currently contain any instruments to help you with this task, as it
was not designed for multithreaded execution, but as far as I remember, the main guideline was that you must not redraw the viewport from a background thread.

Excellent! That was all what I need to know, many thanks!
__________________
* everyone can win previous war
 
  11 November 2011
FYI at time <n> does not work in multiple threads...
 
  11 November 2011
Quote: but as far as I remember, the main guideline was that you must not redraw the viewport from a background thread.

^ That helps make a background worker thread more stable in some cases, but it can still crash max if the user is doing something when the thread tries to update the viewport when it's finished (like merging a max file in the background, or creating a box, updating a mesh, etc...). For doing calculations and non-viewport related stuff, the background worker is great. I wish it worked 100% of the time.

I did some race condition tests on the background worker and found that I could not create a fatal collision between two functions operating on the same mesh at the same time. This has led me to believe that a .net background thread does not execute at the same time as the maxscript "main" thread in 3ds max. In addition to that assumption, I think that the main thread has precedence over any background threads, meaning that identical functions will take different times to compute depending on if they are in the main thread or a background thread.

For example, here are two identical functions operating on the same array, yet the background function finishes after the foreground function, despite being called first:


 Race 2:
    (	--which thread finishes last?
   	local myBox = box() --create a box()
   	--create an array, fill the array with references to the box
   	local myArray = #(myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox) 
   
   	fn bkgWrkr =
   	(	--move the box position in a background thread
   		for i=1 to myArray.count do
   			(myArray[i].pos = [0,100,0])
   	)
   	fn foregroundWrkr =
   	(	--move the box position in a foreground thread
   		for i=1 to myArray.count do
   			(myArray[i].pos = [0,0,0])
   	)
   	
   	MainThread = dotnetobject "CSharpUtilities.SynchronizingBackgroundWorker"
   	dotNet.addEventHandler MainThread "DoWork" bkgWrkr
   	MainThread.RunWorkerAsync()
   	foregroundWrkr()
   )	--in this example, the bkgWrkr always finishes last (for me) 
 


I think any function put into a background thread takes a slight performance hit due to the precedence of the main thread, if any code is executing in the main thread. So, if you care about performance and stability, you probably shouldn't put your code in a background thread. And I love the background thread too - I'm not hatin' - just being honest about my discoveries.
__________________

 
  11 November 2011
I have a few remarks about this race test:

* It is somewhat unfair due to the extremely fast task you are measuring. If you benchmark this task it takes less than 1 milisecond for the foreground worker to complete, so by the time the background worker sets up a thread to work with, the foreground worker is done.

* Consider this test instead:
(	--which thread finishes last?
   	local myBox = box() --create a box()
   	--create an array, fill the array with references to the box
   	local myArray = for i = 1 to 200 collect myBox
	global bgStart = undefined, fgStart = undefined, bgEnd = undefined, fgEnd = undefined
   
   	fn bkgWrkr =
   	(	
		::bgStart = timestamp()
   		for i=1 to myArray.count do
   			(myArray[i].pos = [0,100,0])
		::bgEnd = timestamp()
   	)
   	fn foregroundWrkr =
   	(
		::fgStart = timestamp()
   		for i=1 to myArray.count do
   			(myArray[i].pos = [0,0,0])
		::fgEnd = timestamp()
   	)
   	
   	MainThread = dotnetobject "CSharpUtilities.SynchronizingBackgroundWorker"
   	dotNet.addEventHandler MainThread "DoWork" bkgWrkr
   	MainThread.RunWorkerAsync()
   	foregroundWrkr()
	sleep 2 --let everyone catch up
	format "BG thread started % ms after FG thread and finished % ms after it\n" (bgStart-fgStart) (bgEnd-fgEnd)
   )


half the times you will get a result proving that the BG worker started working after the FG worker, and finished its work by the same offset.
Other times, max will crash due to the race condition.
 
  11 November 2011
Originally Posted by TheGrak: So, if you care about performance and stability, you probably shouldn't put your code in a background thread.


I think that is a somewhat misleading statement.
If your task can benefit from parallel execution, you should probably put it in a background thread, ideally more than one. That is the whole idea of multithreading.
If your task does not benefit from parallel execution, or due to thread conflicts is not stable when executed in parallel, you shouldn't put your code in a background thread.
 
  12 December 2011
Quote: I think that is a somewhat misleading statement.

I agree with you now, looking back on that statement.
__________________

 
  01 January 2012
I'm probably going to look into this tomorrow for a bit and see what I can find.

I'm trying to not use the SDK, just normal script, but instance/copy objects as fast as possible. Right now I can do around 1100 a second if all goes well. However i'd like to try and do this faster if possible.

But multi-threading what I have might get to be too hairy code wise, but we'll see I guess.

If Maxscript only uses 1 core, which I'm pretty sure it does? If I could use 2 or 4 cores, I should potentially be able to create around 4400 objects a second if max allows so. Even if I got a 2-3x increase in speed that would be pretty nice.
 
  01 January 2012
Quote: If Maxscript only uses 1 core, which I'm pretty sure it does? If I could use 2 or 4 cores...


FAIK maxscript uses only 1 core.
Do not know of a way to make maxscript use more than 1 core (maybe dynamically compiling C# code to do such a thing? denisT -> is that possible?).
Could send data to GPUs, but that won't help with most operations in max.
Vray, mentalray, and other programs use all the cores, but that is C++ magic.
So, if you can write C++ magic, max can use all cores.
__________________

 
  01 January 2012
Yeah, that's kinda of what I figured. I'm learning C#. Maybe I'll attempt to learn C++ at some point.
 
  01 January 2012
What do you mean that maxscript is limited to one core? You've already shown it can multithread mostly anything using threading.
 
Thread Closed share thread



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 04:12 AM.


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