高性能的Python扩展(1)
admin
2023-07-31 01:42:42
0

简介

通常来说,Python不是一种高性能的语言,在某种意义上,这种说法是真的。但是,随着以Numpy为中心的数学和科学软件包的生态圈的发展,达到合理的性能不会太困难。

当性能成为问题时,运行时间通常由几个函数决定。用C重写这些函数,通常能极大的提升性能。

在本系列的第一部分中,我们来看看如何使用NumPy的C API来编写C语言的Python扩展,以改善模型的性能。在以后的文章中,我们将在这里提出我们的解决方案,以进一步提升其性能。

文件

这篇文章中所涉及的文件可以在Github上获得。

模拟

作为这个练习的起点,我们将在像重力的力的作用下为N体来考虑二维N体的模拟。

以下是将用于存储我们世界的状态,以及一些临时变量的类。

123456789101112131415161718192021222324252627282930313233343536373839     # lib/sim.py     class World(object):        \”\”\”World is a structure that holds the state of N bodies and        additional variables.         threads : (int) The number of threads to use for multithreaded                  implementations.         STATE OF THE WORLD:          N : (int) The number of bodies in the simulation.        m : (1D ndarray) The mass of each body.        r : (2D ndarray) The position of each body.        v : (2D ndarray) The velocity of each body.        F : (2D ndarray) The force on each body.         TEMPORARY VARIABLES:         Ft : (3D ndarray) A 2D force array for each thread\’s local storage.        s  : (2D ndarray) The vectors from one body to all others.         s3 : (1D ndarray) The norm of each s vector.          NOTE: Ft is used by parallel algorithms for thread-local              storage. s and s3 are only used by the Python              implementation.        \”\”\”        def __init__(self, N, threads=1,                      m_min=1, m_max=30.0, r_max=50.0, v_max=4.0, dt=1e3):            self.threads = threads            self.N  = N            self.m  = np.random.uniform(m_min, m_max, N)            self.r  = np.random.uniform(r_max, r_max, (N, 2))            self.v  = np.random.uniform(v_max, v_max, (N, 2))            self.F  = np.zeros_like(self.r)            self.Ft = np.zeros((threads, N, 2))            self.s  = np.zeros_like(self.r)            self.s3 = np.zeros_like(self.m)            self.dt = dt

在开始模拟时,N体被随机分配质量m,位置r和速度v。对于每个时间步长,接下来的计算有:

  1. 合力F,每个体上的合力根据所有其他体的计算。
  2. 速度v,由于力的作用每个体的速度被改变。
  3. 位置R,由于速度每个体的位置被改变。

第一步是计算合力F,这将是我们的瓶颈。由于世界上存在的其他物体,单一物体上的力是所有作用力的总和。这导致复杂度为O(N^2)。速度v和位置r更新的复杂度都是O(N)。

如果你有兴趣,这篇维基百科的文章介绍了一些可以加快力的计算的近似方法。

纯Python

在纯Python中,使用NumPy数组是时间演变函数的一种实现方式,它为优化提供了一个起点,并涉及测试其他实现方式。

12345678910111213141516     # lib/sim.py     def compute_F(w):        \”\”\”Compute the force on each body in the world, w.\”\”\”        for i in xrange(w.N):            w.s[:] = w.r w.r[i]            w.s3[:] = (w.s[:,0]**2 + w.s[:,1]**2)**1.5            w.s3[i] = 1.0 # This makes the self-force zero.            w.F[i] = (w.m[i] * w.m[:,None] * w.s / w.s3[:,None]).sum(0)     def evolve(w, steps):        \”\”\”Evolve the world, w, through the given number of steps.\”\”\”        for _ in xrange(steps):            compute_F(w)            w.v += w.F * w.dt / w.m[:,None]            w.r +=span>:,None]            w.r +=Ǎ意义上,这种说法是真的。但是,随着以Numpy为中心的数学和科学软件包的生态圈的发展,达到合理的性能不会太困难。

当性能成为问题时,运行时间通常由几个函数决定。用C重写这些函数,通常能极大的提升性能。

在本系列的第一部分中,我们来看看如何使用NumPy的C API来编写C语言的Python扩展,以改善模型的性能。在以后的文章中,我们将在这里提出我们的解决方案,以进一步提升其性能。

文件

这篇文章中所涉及的文件可以在Github上获得。

模拟

作为这个练习的起点,我们将在像重力的力的作用下为N体来考虑二维N体的模拟。

以下是将用于存储我们世界的状态,以及一些临时变量的类。

123456789101112131415161718192021222324252627282930313233343536373839     # lib/sim.py     class World(object):        \”\”\”World is a structure that holds the state of N bodies and        additional variables.         threads : (int) The number of threads to use for multithreaded                  implementations.         STATE OF THE WORLD:          N : (int) The number of bodies in the simulation.        m : (1D ndarray) The mass of each body.        r : (2D ndarray) The position of each body.        v : (2D ndarray) The velocity of each body.        F : (2D ndarray) The force on each body.         TEMPORARY VARIABLES:         Ft : (3D ndarray) A 2D force array for each thread\’s local storage.        s  : (2D ndarray) The vectors from one body to all others.         s3 : (1D ndarray) The norm of each s vector.          NOTE: Ft is used by parallel algorithms for thread-local              storage. s and s3 are only used by the Python              implementation.        \”\”\”        def __init__(self, N, threads=1,                      m_min=1, m_max=30.0, r_max=50.0, v_max=4.0, dt=1e3):            self.threads = threads            self.N  = N            self.m  = np.random.uniform(m_min, m_max, N)            self.r  = np.random.uniform(r_max, r_max, (N, 2))            self.v  = np.random.uniform(v_max, v_max, (N, 2))            self.F  = np.zeros_like(self.r)            self.Ft = np.zeros((threads, N, 2))            self.s  = np.zeros_like(self.r)            self.s3 = np.zeros_like(self.m)            self.dt = dt

在开始模拟时,N体被随机分配质量m,位置r和速度v。对于每个时间步长,接下来的计算有:

  1. 合力F,每个体上的合力根据所有其他体的计算。
  2. 速度v,由于力的作用每个体的速度被改变。
  3. 位置R,由于速度每个体的位置被改变。

第一步是计算合力F,这将是我们的瓶颈。由于世界上存在的其他物体,单一物体上的力是所有作用力的总和。这导致复杂度为O(N^2)。速度v和位置r更新的复杂度都是O(N)。

如果你有兴趣,这篇维基百科的文章介绍了一些可以加快力的计算的近似方法。

纯Python

在纯Python中,使用NumPy数组是时间演变函数的一种实现方式,它为优化提供了一个起点,并涉及测试其他实现方式。

12345678910111213141516     # lib/sim.py     def compute_F(w):        \”\”\”Compute the force on each body in the world, w.\”\”\”        for i in xrange(w.N):            w.s[:] = w.r w.r[i]            w.s3[:] = (w.s[:,0]**2 + w.s[:,1]**2)**1.5            w.s3[i] = 1.0 # This makes the self-force zero.            w.F[i] = (w.m[i] * w.m[:,None] * w.s / w.s3[:,None]).sum(0)     def evolve(w, steps):        \”\”\”Evolve the world, w, through the given number of steps.\”\”\”        for _ in xrange(steps):            compute_F(w)            w.v += w.F * w.dt / w.m[:,None]            w.r +=span>

上一篇:重写Reddit

下一篇:超酷算法:基数估计

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...