【发布时间】:2011-04-21 23:04:51
【问题描述】:
我正在研究一个机器人问题。情况是这样的:
- 最初有 N 个机器人(通常 N>100 个)都处于静止状态。
- 每个机器人都会吸引在其半径
r内的所有其他机器人。 - 我有一组方程式,我可以用这些方程式计算加速度、速度以及机器人在时间 delta
t之后的位置。简单来说就是可以在deltat时间之后找到每个机器人的位置。 - 我需要做的就是为给定的 delta
t。我需要为每个 deltat显示每个机器人的位置。
问题其实很简单。算法将类似于:
del_t = ;its given
initialPositions = ;its given
num_robots = ;its given
以下代码为每个del_t 执行
robots = range(1,no_robots)
for R in robots:
for r in robots:
if distanceBetween(r,R) <= radius and r is not R:
acceleration_along_X[R] += xAcceleration( position(r), position(R) )
acceleration_along_Y[R] += yAcceleration( position(r), position(R) )
currVelocity_along_X[R] = prevVelocity_along_X[R] + acceleration_along_X[R] * del_t
currVelocity_along_Y[R] = prevVelocity_along_Y[R] + acceleration_along_Y[R] * del_t
curr_X_coordinate[R] = prev_X_coordinate[R] + currVelocity_along_X[R] * del_t
curr_Y_coordinate[R] = prev_Y_coordinate[R] + currVelocity_along_Y[R] * del_t
print 'Position of robot ' + str(R) + ' is (' + curr_X_coordinate[R] + ', ' + curr_Y_coordinate[R] +' ) \n'
prev_X_coordinate[R] = curr_X_coordinate[R]
prev_Y_coordinate[R] = curr_Y_coordinate[R]
prevVelocity_along_X[R] = currVelocity_along_X[R]
prevVelocity_along_Y[R] = currVelocity_along_Y[R]
现在我需要并行化算法并设置 MPI 进程的笛卡尔网格。
- 因为每个机器人的计算都是一项独立的任务。每个机器人的计算 可以由一个独立的线程来完成。对吗?
- 我对 MPI 一无所知。这个“MPI 过程的笛卡尔网格”是什么意思?我该如何设置这个网格?我对此一无所知。
编辑:
现在问题变得有趣了。其实,事情并没有我想的那么简单。看完Unode's answer。我继续通过使用多处理进行并行化来应用他的方法二。
这是代码。 printPositionOfRobot 是我的串行算法。基本上,它应该打印机器人的位置(id robot_id)t=1,2,3,4,5,6,7,8,9,10。 (这里 del_t 取为 1。num_iterations = 10。每个机器人打印如下消息:Robot8 : Position at t = 9 is (21.1051065245, -53.8757356694 )
此代码中存在错误。 t=0 机器人的位置由position() 给出,用于确定 xAcceleration 和 yAcceleration。我们需要使用所有其他粒子先前迭代的位置。
from multiprocessing import Pool
import math
def printPositionOfRobot(robot_id):
radius = 3
del_t = 1
num_iterations = 10
no_robots = 10
prevVelocity_along_X = 0
prevVelocity_along_Y = 0
acceleration_along_X = 0
acceleration_along_Y = 0
(prev_X_coordinate,prev_Y_coordinate) = position(robot_id)#!!it should call initialPosition()
for i in range(1,num_iterations+1):
for r in range(no_robots):
if distanceBetween(r,robot_id) <= radius and r is not robot_id:
acceleration_along_X += xAcceleration( position(r), position(robot_id) ) #!! Problem !!
acceleration_along_Y += yAcceleration( position(r), position(robot_id) )#!! Problem !!
currVelocity_along_X = prevVelocity_along_X + acceleration_along_X * del_t
currVelocity_along_Y = prevVelocity_along_Y + acceleration_along_Y * del_t
curr_X_coordinate = prev_X_coordinate + currVelocity_along_X * del_t
curr_Y_coordinate = prev_Y_coordinate + currVelocity_along_Y * del_t
print 'Robot' + str(robot_id) + ' : Position at t = '+ str(i*del_t) +' is (' + str(curr_X_coordinate) + ', ' + str(curr_Y_coordinate) +' ) \n'
prev_X_coordinate = curr_X_coordinate
prev_Y_coordinate = curr_Y_coordinate
prevVelocity_along_X = currVelocity_along_X
prevVelocity_along_Y = currVelocity_along_Y
def xAcceleration((x1,y1),(x2,y2)):
s = distance((x1,y1),(x2,y2))
return 12*(x2-x1)*( pow(s,-15) - pow(s,-7) + 0.00548*s )
def yAcceleration((x1,y1),(x2,y2)):
s = distance((x1,y1),(x2,y2))
return 12*(y2-y1)*( pow(s,-15) - pow(s,-7) + 0.00548*s )
def distanceBetween(r,robot_id):
return distance(position(r), position(robot_id))
def distance((x1,y1),(x2,y2)):
return math.sqrt( (x2-x1)**2 + (y2-y1)**2 )
def Position(r): #!!name of this function should be initialPosition
k = [(-8.750000,6.495191) , (-7.500000,8.660254) , (-10.000000,0.000000) , (-8.750000,2.165064) , (-7.500000,4.330127) , (-6.250000,6.495191) , (-5.000000,8.660254) , (-10.000000,-4.330127) , (-8.750000,-2.165064) , (-7.500000,0.000000) ]
return k[r]
if __name__ == "__main__":
no_robots = 10 # Number of robots you need
p = Pool(no_robots) # Spawn a pool of processes (one per robot in this case)
p.map(printPositionOfRobot, range(no_robots))
acceleration_along_X 和 acceleration_along_Y 中的 position 函数应该返回机器人的最新位置。最新是指上一次迭代结束时的位置。因此,每个进程都必须通知其他进程它的最新位置。在知道机器人的最新位置之前,该过程必须等待。
其他方式可以是所有进程都编辑一个全局位置。(我想知道它是否可能,因为每个进程都有自己的虚拟地址空间)。如果一个进程尚未达到该迭代,则所有其他进程都必须等待。
关于如何去做的任何想法?我想这就是为什么在问题中建议使用 MPI 的原因。
【问题讨论】:
-
MPI = 消息传递接口 (?) This document 提供了一些关于 MPI 和设置并行系统的不同方法的体面信息。 (不过,这是一个 Word 文档。)
-
如果你一直坚持使用 MPI 来做这件事,我最近做了一个关于 N 体问题的简单 MPI 方法的课程(这就是你在这里试图模拟的,尽管在不同的上下文中)。幻灯片和视频在这里:cita.utoronto.ca/~ljdursi/PSP/Nbody-MPI/Nbody-MPI.html 这是一个棘手的并行化问题,因为每个机器人都需要来自其他机器人的信息。 (模拟这类事情的实际问题使用近似值,基于这样一个事实,即更远的物体越来越不重要,因此不需要精确处理;但这可能对您没有帮助)
标签: python parallel-processing mpi