Reputation: 15
def parallel_operations(points, primitives):
batch_size,number_of_points,_ = points.shape
_,_,number_of_primitives = primitives.shape
gradient = torch.zeros(batch_size,number_of_points,number_of_primitives)
def process(_lock,i):
_lock.acquire()
temp_points = points[i,:,:]
temp_primitives= primitives[i,:,:].transpose(1,0) #[7,1024]
#print("temp_shape{}".format(temp_primitives.shape))
temp = torch.zeros(number_of_points,number_of_primitives)
for k in range(number_of_points):
for j in range(number_of_primitives):
temp[k,j] = torch.norm(temp_points[k,:]*temp_primitives[j,:3]+temp_primitives[j,3:6])
gradient[i,:,:] = temp
print("gradient update {} {}".format(i, gradient))
lock.release()
return (i, gradient[i,:,:])
result = []
pool = Pool(multiprocessing.cpu_count())
lock = Manager().Lock()
for i in range(10):
result.append(pool.apply_async(process,args=(lock,i)))
pool.close()
pool.join()
print(len(result))
for i in result:
print(i.get())if __name__ == "__main__":
points = torch.randn(10,3,3)
primitives = torch.randn(10,7,3)
result1 = parallel_operations(points,primitives)
The above is my parellized code but when I run it, it throw an error :`AttributeError: Can't pickle local object 'parallel_operations.<locals>.process'
. Why is that?
Upvotes: 1
Views: 985
Reputation: 77387
When multiprocessing
executes a function in a subprocess, it serializes the function and its parameters via the pickle protocol. But pickle doesn't serialize the code object itself, just its module and name. The unpickler loads the module and can get the right function via its name in that module.
But inner functions can't be reached by name like that. They are compiled once but they are only assigned to a function's local variable namespace when the function is executed. Otherwise, they are anonymous objects known to the function byte code. You can see this by disassembling a very simple program:
from dis import dis
def foo():
def bar(x):
return x
print(dis(foo))
The output is
5 0 LOAD_CONST 1 (<code object bar at 0x7f18c7f5b890, file "/home/td/tmp/l/w1.py", line 5>)
2 LOAD_CONST 2 ('foo.<locals>.bar')
4 MAKE_FUNCTION 0
6 STORE_FAST 0 (bar)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
Disassembly of <code object bar at 0x7f18c7f5b890, file "/home/td/tmp/l/w1.py", line 5>:
6 0 LOAD_FAST 0 (x)
2 RETURN_VALUE
The first section is the outer function. It binds an anonymous code object to local variable "bar" each time the function is run. When no instance of the outer function is running, the inner function has no name. The second section is the anonymous code object itself.
You should move process
outside of parallel_operations
so that pickle can find it.
Upvotes: 1