使用dask进行高效的n体仿真

时间:2016-10-25 21:07:27

标签: python dask

N-body simulation用于模拟涉及粒子相互作用的物理系统的动力学,或者将问题简化为具有物理意义的某种粒子。粒子可以是气体分子或星系中的恒星。 Dask.bag提供了一种在集群中分布粒子的简单方法,例如,给dask.bag.from_sequence()一个自定义迭代器,它返回一个粒子对象:

class ParticleGenerator():
    def __init__(self, num_of_particles, max_position, seed=time.time()):
        random.seed(seed)
        self.index = -1
        self.limit = num_of_particles
        self.max_position = max_position
    def __iter__(self):
        return self 
    def __next__(self):
         self.index += 1
         if self.index < self.limit :
             return np.array([self.max_position*random.random(), self.max_position*random.random(), self.max_position*random.random()]) 
         else :
             raise StopIteration
b = db.from_sequence( ParticleGenerator(1000, 1, seed=123456789) )

这里,粒子对象只是一个numpy数组,但可以是任何东西。现在,要计算所有粒子之间的相互作用,必须共享有关位置,速度和类似数量的信息。 dask.bag.map将函数映射到集合中的所有元素,在此函数内,计算元素与所有其他粒子之间的相互作用以获得新的粒子状态。

b = b.map(update_position, others=list(b))
b.compute()

对于完整性,这是update_position函数:

def update_position(e, others=None, mass=1, dt=1e-4):
    f = np.zeros(3)
    for o in others:
        r = e - o
        r_mag = np.sqrt(r.dot(r))
        if r_mag == 0 :
            continue 
        f += ( A/(r_mag**7) + B/(r_mag**13) ) * r
    return e + f * (dt**2 / mass)

AB一些任意值。可以在循环内多次调用dask.bag.map()来执行模拟。

  1. Dask.bag是一个很好的集合(抽象)来处理这类问题吗?也许Dask.distributed是一个更好的主意?
  2. 以这种方式对模拟进行编程,处理所有通信的调度程序或有关位置,速度等的信息是否与员工之间的通信共享?
  3. 优化代码的任何评论?特别是在调用dask.bag.map()时将集合转换为列表的过热。

1 个答案:

答案 0 :(得分:1)

一般来说,N-Body模拟需要复杂的算法和数据结构才能有效运行。许多常见的解决方案包括使用复杂的树数据结构。您可能想要搜索kd-tree或barnes-hut等术语。

另一方面,Dask.bag是您可以想象的最简单/最笨的并行编程抽象之一,类似于MapReduce和Spark等其他批量数据处理系统。这些系统不够灵活,无法在N-Body模拟等复杂问题上提供良好的性能。

dask.arraydask.delayed之类的东西会提供更大的灵活性,但即使这些也不会与精心调整的KD树相同。