c4d threading runs only on one core and is slower than single threaded
-
put this code in a python generator and place any polygon object under it. run it single threaded , then increase the maxThreads.
it is significant slower when maxThreads > 1.
import c4d import math import time #Welcome to the world of Python RootNull = c4d.BaseObject(c4d.Onull) def currStateToObject(source): return c4d.utils.SendModelingCommand( command = c4d.MCOMMAND_CURRENTSTATETOOBJECT, list = [source], mode=c4d.MODELINGCOMMANDMODE_ALL, bc=c4d.BaseContainer(), doc = doc)[0] def connectDelete(source): return c4d.utils.SendModelingCommand( command = c4d.MCOMMAND_JOIN, list = [source], mode=c4d.MODELINGCOMMANDMODE_ALL, bc=c4d.BaseContainer())[0] class ThreadedCut(c4d.threading.C4DThread): def TestBreak(self): return None def __init__(self, sList): print "thread init" self.sList = sList def Main(self): print "thread start" for s in self.sList: self.CutObject(s) print "thread finish" def CutObject(self,s): global objReference # create a copy obj = objReference.GetClone() allPoints = obj.GetAllPoints() bbox = obj.GetRad() p1 = c4d.Vector(bbox.x*10,s,bbox.z*10) v1 = c4d.Vector(bbox.x*10,0,bbox.z*-10) p2 = c4d.Vector(bbox.x*-10,0,bbox.z*10) v2 = c4d.Vector(bbox.x*-10,0,bbox.z*-10) data = c4d.BaseContainer() data.SetVector(c4d.MDATA_KNIFE_P1, p1) data.SetVector(c4d.MDATA_KNIFE_P2, p2) data.SetVector(c4d.MDATA_KNIFE_V1, v1) data.SetVector(c4d.MDATA_KNIFE_V2, v2) c4d.utils.SendModelingCommand(c4d.MCOMMAND_KNIFE, [obj], bc=data, doc=doc) newPoints = obj.GetAllPoints() pointSelection = obj.GetPointS() for i in range(len(allPoints),len(newPoints)): pointSelection.Select(i) bc = c4d.BaseContainer() bc.SetData(c4d.MDATA_CONVERTSELECTION_LEFT, 0) bc.SetData(c4d.MDATA_CONVERTSELECTION_RIGHT, 1) bc.SetData(c4d.MDATA_CONVERTSELECTION_TOLERANT, False) c4d.utils.SendModelingCommand(c4d.MCOMMAND_CONVERTSELECTION, [obj], bc=bc, doc=doc) c4d.utils.SendModelingCommand(c4d.MCOMMAND_EDGE_TO_SPLINE, [obj]) if obj.GetDown(): return obj.GetDown().InsertUnder(RootNull) return None def chunkIt(seq, num): """ https://stackoverflow.com/questions/2130016/splitting-a-list-into-n-parts-of-approximately-equal-length/37414115 """ avg = len(seq) / float(num) out = [] last = 0.0 while last < len(seq): out.append(seq[int(last):int(last + avg)]) last += avg return out objReference = None def main(): global objReference runningThreads = 0 starttime = time.time() obj = currStateToObject(op.GetDown()) objReference = obj maxThreads = 1 minHeight = -200 maxHeight = 200 offset = 0.5 maxSlices = 10000 sliceList= [] for i in range(0,maxSlices): s = minHeight + i*offset if (s <= maxHeight and s < obj.GetRad().y*2): sliceList.append(s) else: break chunks = chunkIt(sliceList,maxThreads) tList = [] for c in chunks: print len(c),len(sliceList) t = ThreadedCut(c) tList.append(t) print "threadlist rdy" for t in tList: t.Start() for t in tList: t.Wait(True) spline = connectDelete(RootNull) spline[c4d.SPLINEOBJECT_TYPE] = 3 spline[c4d.SPLINEOBJECT_CLOSED] = True end = time.time() print end-starttime return spline
-
Hi @pyr,
In Python, there is a GIL which do not allow Python by design to execute something in parallel.
In Cinema 4D all our functions (so everything which is in the c4d python module) is "GIL safe" in order to avoid any issue with Python memory.
So in Cinema 4D thread are designed for doing GUI, or background stuff.
Moreover, keep in mind creating a Thread have a cost in term of time (to create, execute, delete them).Finally, I would like to point you to multiprocessing vs multi-threading.
Note that since it's more an algorithm problem than an issue related to our API, we can only provide you hints.
btw, I also turned your topic as a question. See Q&A New Functionality.
Cheers,
Maxime.