@p1r4t3b0y wrote:
Hello everybody,
I’m trying to implement multithreading (parallel computing), for a demanding for loop-portion of a Python script, I’m currently working on.
I’ve read @stevebaer’s post on the subject from a while back and tried to accomplish a similar thing with
System.Threading.Tasks.Parallel.ForEach()
.I get the following error:
Runtime error (ArgumentTypeException): The type arguments for method ‘ForEach’ cannot be inferred from the usage. Try specifying the type arguments explicitly.
Traceback:
line 28, in updateI understand that
Parallel.ForEach
takes 2 parameters: a list of objects of type x, and a method that takes in one object of the same type x and returns nothing.
Here may reside one problem, since in Python (at least I think so), you don’t declare the type of the items in your list, and the type of the list itself would be, well, ‘list’ and not type x.Here’s how I call
Parallel.ForEach
:import System.Threading.Tasks as tasks tasks.Parallel.ForEach(self.agents, self._compute_agent_velocity)
I pass it a list of class instances
self.agents
, of the same classAgent
, as an iterable, and the methodself._compute_agent_velocity()
. The method takes in one agent instance and returns nothing. The list of agent instances, as well the method, are both parts of the classParticleSystem
.import Rhino.Geometry as rg import System.Threading.Tasks as tasks import random class ParticleSystem: def __init__(self, agent_count=100, use_parallel=True): self.agent_count = agent_count self.use_parallel = use_parallel self.agents = [] # gets passed to Parallel.ForEach() for i in range(self.agent_count): agent = Agent( self._get_random_point(0.0, 30.0, 0.0, 30.0, 0.0, 30.0), self._get_random_unit_vector() * 4.0) agent.flock_system = self self.agents.append(agent) def update(self): """Method that calls Parallel.ForEach().""" # Regular for loop if not self.use_parallel: for agent in self.agents: neighbours = self._find_neighbours(agent) agent._compute_desired_velocity(neighbours) # Multithreaded for loop else: tasks.Parallel.ForEach(self.agents, self._compute_agent_desired_velocity) for agent in self.agents: agent.update_veloctiy_and_position() def _compute_agent_desired_velocity(self, agent): """Method that gets passed to Parallel.ForEach().""" neighbours = self._find_neighbours(agent) agent._compute_desired_velocity(neighbours) def _find_neighbours(self, agent): neighbours = [] for neighbour in self.agents: dist = neighbour.position.DistanceTo(agent.position) if neighbour != agent and dist < 1.500: neighbours.append(neighbour) return neighbours def _get_random_point(self, min_x, max_x, min_y, max_y, min_z, max_z): x = min_x + (max_x - min_x) * random.random() y = min_y + (max_y - min_y) * random.random() z = min_z + (max_z - min_z) * random.random() return rg.Point3d(x, y, z) def _get_random_unit_vector(self, three=True): phi = 2.0 * math.pi * random.random() theta = math.acos(2.0 * random.random() - 1.0) x = math.sin(theta) * math.cos(phi) y = math.sin(theta) * math.sin(phi) z = math.cos(theta) return rg.Vector3d(x, y, z) class Agent: def __init__(self, position, velocity): self.position = position self.velocity = velocity self.desired_velocity = rg.Vector3d.Zero self.particle_system = None def update_veloctiy_and_position(self): self.velocity = 0.97 * self.velocity + 0.03 * self.desired_velocity if self.velocity.Length > 8.0: self.velocity *= 8.0 / self.velocity.Length elif self.velocity.Length < 4.0: self.velocity *= 4.0 / self.velocity.Length self.position += self.velocity * self.particle_system.time_step def _compute_desired_velocity(self, neighbours): self.desired_velocity = rg.Vector3d.Zero bounding_box_size = 30.0 # Control boundary if self.position.X < 0.0: self.desired_velocity += rg.Vector3d(-self.position.X, 0.0, 0.0) elif self.position.X > bounding_box_size: self.desired_velocity += rg.Vector3d(bounding_box_size - self.position.X, 0.0, 0.0) if self.position.Y < 0.0: self.desired_velocity += rg.Vector3d(0.0, -self.position.Y, 0.0) elif self.position.Y > bounding_box_size: self.desired_velocity += rg.Vector3d(0.0, bounding_box_size - self.position.Y, 0.0) if self.position.Z < 0.0: self.desired_velocity += rg.Vector3d(0.0, 0.0, -self.position.Z) elif self.position.Z > bounding_box_size: self.desired_velocity += rg.Vector3d(0.0, 0.0, bounding_box_size - self.position.Z)
Please note that I’ve abstracted the code a bit, to make it shorter and protect some parts.
Any help is greatly appreciated!
Posts: 1
Participants: 1