Solved 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.

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.