- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题:
我正在尝试提高 Python 中空气动力学函数的速度。
功能集:
import numpy as np
from numba import njit
def calculate_velocity_induced_by_line_vortices(
points, origins, terminations, strengths, collapse=True
):
# Expand the dimensionality of the points input. It is now of shape (N x 1 x 3).
# This will allow NumPy to broadcast the upcoming subtractions.
points = np.expand_dims(points, axis=1)
# Define the vectors from the vortex to the points. r_1 and r_2 now both are of
# shape (N x M x 3). Each row/column pair holds the vector associated with each
# point/vortex pair.
r_1 = points - origins
r_2 = points - terminations
r_0 = r_1 - r_2
r_1_cross_r_2 = nb_2d_explicit_cross(r_1, r_2)
r_1_cross_r_2_absolute_magnitude = (
r_1_cross_r_2[:, :, 0] ** 2
+ r_1_cross_r_2[:, :, 1] ** 2
+ r_1_cross_r_2[:, :, 2] ** 2
)
r_1_length = nb_2d_explicit_norm(r_1)
r_2_length = nb_2d_explicit_norm(r_2)
# Define the radius of the line vortices. This is used to get rid of any
# singularities.
radius = 3.0e-16
# Set the lengths and the absolute magnitudes to zero, at the places where the
# lengths and absolute magnitudes are less than the vortex radius.
r_1_length[r_1_length < radius] = 0
r_2_length[r_2_length < radius] = 0
r_1_cross_r_2_absolute_magnitude[r_1_cross_r_2_absolute_magnitude < radius] = 0
# Calculate the vector dot products.
r_0_dot_r_1 = np.einsum("ijk,ijk->ij", r_0, r_1)
r_0_dot_r_2 = np.einsum("ijk,ijk->ij", r_0, r_2)
# Calculate k and then the induced velocity, ignoring any divide-by-zero or nan
# errors. k is of shape (N x M)
with np.errstate(divide="ignore", invalid="ignore"):
k = (
strengths
/ (4 * np.pi * r_1_cross_r_2_absolute_magnitude)
* (r_0_dot_r_1 / r_1_length - r_0_dot_r_2 / r_2_length)
)
# Set the shape of k to be (N x M x 1) to support numpy broadcasting in the
# subsequent multiplication.
k = np.expand_dims(k, axis=2)
induced_velocities = k * r_1_cross_r_2
# Set the values of the induced velocity to zero where there are singularities.
induced_velocities[np.isinf(induced_velocities)] = 0
induced_velocities[np.isnan(induced_velocities)] = 0
if collapse:
induced_velocities = np.sum(induced_velocities, axis=1)
return induced_velocities
@njit
def nb_2d_explicit_norm(vectors):
return np.sqrt(
(vectors[:, :, 0]) ** 2 + (vectors[:, :, 1]) ** 2 + (vectors[:, :, 2]) ** 2
)
@njit
def nb_2d_explicit_cross(a, b):
e = np.zeros_like(a)
e[:, :, 0] = a[:, :, 1] * b[:, :, 2] - a[:, :, 2] * b[:, :, 1]
e[:, :, 1] = a[:, :, 2] * b[:, :, 0] - a[:, :, 0] * b[:, :, 2]
e[:, :, 2] = a[:, :, 0] * b[:, :, 1] - a[:, :, 1] * b[:, :, 0]
return e
语境:
import timeit
import matplotlib.pyplot as plt
import numpy as np
n_repeat = 2
n_execute = 10 ** 3
min_oom = 0
max_oom = 3
times_py = []
for i in range(max_oom - min_oom + 1):
n_elem = 10 ** i
n_elem_pretty = np.format_float_scientific(n_elem, 0)
print("Number of elements: " + n_elem_pretty)
# Benchmark Python.
print("\tBenchmarking Python...")
setup = '''
import numpy as np
these_points = np.random.random((''' + str(n_elem) + ''', 3))
these_origins = np.random.random((''' + str(n_elem) + ''', 3))
these_terminations = np.random.random((''' + str(n_elem) + ''', 3))
these_strengths = np.random.random(''' + str(n_elem) + ''')
def calculate_velocity_induced_by_line_vortices(points, origins, terminations,
strengths, collapse=True):
pass
'''
statement = '''
results_orig = calculate_velocity_induced_by_line_vortices(these_points, these_origins,
these_terminations,
these_strengths)
'''
times = timeit.repeat(repeat=n_repeat, stmt=statement, setup=setup, number=n_execute)
time_py = min(times)/n_execute
time_py_pretty = np.format_float_scientific(time_py, 2)
print("\t\tAverage Time per Loop: " + time_py_pretty + " s")
# Record the times.
times_py.append(time_py)
sizes = [10 ** i for i in range(max_oom - min_oom + 1)]
fig, ax = plt.subplots()
ax.plot(sizes, times_py, label='Python')
ax.set_xscale("log")
ax.set_xlabel("Size of List or Array (elements)")
ax.set_ylabel("Average Time per Loop (s)")
ax.set_title(
"Comparison of Different Optimization Methods\nBest of "
+ str(n_repeat)
+ " Runs, each with "
+ str(n_execute)
+ " Loops"
)
ax.legend()
plt.show()
以前的尝试:
points = np.expand_dims(points, axis=1)
r_1 = points - origins
r_2 = points - terminations
两次调用以下函数:
@njit
def subtract(a, b):
c = np.empty((a.shape[0], b.shape[0], 3))
for i in range(a.shape[0]):
for j in range(b.shape[0]):
for k in range(3):
c[i, j, k] = a[i, k] - b[j, k]
return c
这导致速度从 227 秒增加到 220 秒。这个更好!但是,它仍然不够快。
最佳答案
首先Numba可以执行并行计算 如果您主要使用 parallel=True
手动请求它,则会产生更快的代码和 prange
.这对大数组很有用(但对小数组没有用)。
而且,你的计算主要是内存限制 .因此,当它们没有被多次重用时,或者更普遍地,当它们不能被重新计算时(以相对便宜的方式),你应该避免创建大数组。 r_0
就是这种情况。例如。
此外,内存访问模式重要:当访问为 时,向量化更有效连续 在内存中,缓存/RAM的使用效率更高。因此,arr[0, :, :] = 0
应该比 arr[:, :, 0] = 0
更快.同样,arr[:, :, 0] = arr[:, :, 1] = 0
应该比 arr[:, :, 0:2] = 0
慢因为前者执行不连续的内存传递,而后者只执行一个更连续的内存传递。有时,转置数据可能会有所帮助,以便以下计算更快。
此外,Numpy 往往会创建许多 临时数组 分配成本很高。当输入数组很小时,这是一个大问题。在大多数情况下,Numba jit 可以避免这种情况。
最后,关于您的计算,使用 可能是个好主意。 GPU 对于大数组(绝对不是小数组)。可以看一下丘比 或 clpy 很容易做到这一点。
这是在 CPU 上工作的优化实现:
import numpy as np
from numba import njit, prange
@njit(parallel=True)
def subtract(a, b):
c = np.empty((a.shape[0], b.shape[0], 3))
for i in prange(c.shape[0]):
for j in range(c.shape[1]):
for k in range(3):
c[i, j, k] = a[i, k] - b[j, k]
return c
@njit(parallel=True)
def nb_2d_explicit_norm(vectors):
res = np.empty((vectors.shape[0], vectors.shape[1]))
for i in prange(res.shape[0]):
for j in range(res.shape[1]):
res[i, j] = np.sqrt(vectors[i, j, 0] ** 2 + vectors[i, j, 1] ** 2 + vectors[i, j, 2] ** 2)
return res
# NOTE: better memory access pattern
@njit(parallel=True)
def nb_2d_explicit_cross(a, b):
e = np.empty(a.shape)
for i in prange(e.shape[0]):
for j in range(e.shape[1]):
e[i, j, 0] = a[i, j, 1] * b[i, j, 2] - a[i, j, 2] * b[i, j, 1]
e[i, j, 1] = a[i, j, 2] * b[i, j, 0] - a[i, j, 0] * b[i, j, 2]
e[i, j, 2] = a[i, j, 0] * b[i, j, 1] - a[i, j, 1] * b[i, j, 0]
return e
# NOTE: avoid the slow building of temporary arrays
@njit(parallel=True)
def cross_absolute_magnitude(cross):
return cross[:, :, 0] ** 2 + cross[:, :, 1] ** 2 + cross[:, :, 2] ** 2
# NOTE: avoid the slow building of temporary arrays again and multiple pass in memory
# Warning: do the work in-place
@njit(parallel=True)
def discard_singularities(arr):
for i in prange(arr.shape[0]):
for j in range(arr.shape[1]):
for k in range(3):
if np.isinf(arr[i, j, k]) or np.isnan(arr[i, j, k]):
arr[i, j, k] = 0.0
@njit(parallel=True)
def compute_k(strengths, r_1_cross_r_2_absolute_magnitude, r_0_dot_r_1, r_1_length, r_0_dot_r_2, r_2_length):
return (strengths
/ (4 * np.pi * r_1_cross_r_2_absolute_magnitude)
* (r_0_dot_r_1 / r_1_length - r_0_dot_r_2 / r_2_length)
)
@njit(parallel=True)
def rDotProducts(b, c):
assert b.shape == c.shape and b.shape[2] == 3
n, m = b.shape[0], b.shape[1]
ab = np.empty((n, m))
ac = np.empty((n, m))
for i in prange(n):
for j in range(m):
ab[i, j] = 0.0
ac[i, j] = 0.0
for k in range(3):
a = b[i, j, k] - c[i, j, k]
ab[i, j] += a * b[i, j, k]
ac[i, j] += a * c[i, j, k]
return (ab, ac)
# Compute `np.sum(arr, axis=1)` in parallel.
@njit(parallel=True)
def collapseArr(arr):
assert arr.shape[2] == 3
n, m = arr.shape[0], arr.shape[1]
res = np.empty((n, 3))
for i in prange(n):
res[i, 0] = np.sum(arr[i, :, 0])
res[i, 1] = np.sum(arr[i, :, 1])
res[i, 2] = np.sum(arr[i, :, 2])
return res
def calculate_velocity_induced_by_line_vortices(points, origins, terminations, strengths, collapse=True):
r_1 = subtract(points, origins)
r_2 = subtract(points, terminations)
# NOTE: r_0 is computed on the fly by rDotProducts
r_1_cross_r_2 = nb_2d_explicit_cross(r_1, r_2)
r_1_cross_r_2_absolute_magnitude = cross_absolute_magnitude(r_1_cross_r_2)
r_1_length = nb_2d_explicit_norm(r_1)
r_2_length = nb_2d_explicit_norm(r_2)
radius = 3.0e-16
r_1_length[r_1_length < radius] = 0
r_2_length[r_2_length < radius] = 0
r_1_cross_r_2_absolute_magnitude[r_1_cross_r_2_absolute_magnitude < radius] = 0
r_0_dot_r_1, r_0_dot_r_2 = rDotProducts(r_1, r_2)
with np.errstate(divide="ignore", invalid="ignore"):
k = compute_k(strengths, r_1_cross_r_2_absolute_magnitude, r_0_dot_r_1, r_1_length, r_0_dot_r_2, r_2_length)
k = np.expand_dims(k, axis=2)
induced_velocities = k * r_1_cross_r_2
discard_singularities(induced_velocities)
if collapse:
induced_velocities = collapseArr(induced_velocities)
return induced_velocities
在我的机器上,此代码是
快 2.5 倍 比在
10**3
大小的数组上的初始实现.它还使用了一点
内存少 .
关于python - 我可以使用 Numba、矢量化或多处理加速这种空气动力学计算吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66750661/
我正在尝试将字符串列表转换为字符向量的向量: import collection.breakOut def stringsToCharVectors(xs: List[String]) = x
我正在尝试使用 Pytorch 通过 2D 向量(嘈杂语音帧序列)的回归来预测 1D 向量(干净语音数据帧) data) - 之前已经完成过。帧序列为帧提供时间上下文,以更准确地预测干净帧。这些向量可
在尝试构建时,我收到此错误: Operator '+=' is ambiguous on operands of type 'Vector3' and 'Vector2' 这是问题出处的脚本代码: u
是否存在实现 FIFO 意义上的循环数组或向量的 R 包? 假设我们有这个数组: 2 4 7 1 当在位置 1 插入一个新的观察值(比如 3)时,我希望第 n 个元素被第 n-1 个元素替换: 3 2
我在游戏中有两个对象,为此可以将其视为 2d 平面上的点,但我使用 Vector3s,因为游戏本身是 3d。 我有一个游戏相机,我想将其与两个物体垂直(也在平面上)对齐,以便它们都在相机的视野中。由于
我做了一个Telegram robot ,它的工作之一是从音频文件创建样本。现在对于发送给它的大多数音频,样本都非常好;像这样: 但是,对于一些音频,样本看起来有点奇怪: 如您所见,此文件中的波形未显
由于对 JavaScript 非常陌生,我在使用 JQuery VectorMaps 时遇到了以下问题: 当我用这种语法突出显示一个国家时,一切都很完美: jQuery('#vmap').vector
我正在使用 ChartJS 在我的网站中包含一些 map ,但 ChartJS 库没有我想要的 map 。 我想知道这种类型的矢量 map 是否很容易在网上免费找到,还是必须从头开始构建? Chart
我需要创建一个函数。在此范围内,我需要发生以下事情: List 1: '(a 5 6) List 2: '(c 8 10) List 3: '(d 4 9) 以上是列表。我需要忽略每个列表的第一列(这
我在地球表面有一个点,我正在将其从地球中心转换为向量。 我有一个以度数表示的真北航向,描述了该点将在地球表面行进的路径。 我需要计算一个向量,该向量垂直于该点沿地球表面的路径所创建的平面。 我尝试
大家好,这是我的 JavaScript 代码,用于为矢量 map 制作 ip 标记以显示在线 ip.. 所有 ips 都有 3 个不同的端口,例如:ip1:1020 或 ip2:5050 或 ip3:
我正在使用 Three.js 透视相机,我需要了解相机所注视的点。 如何使用相机的矩阵/旋转向量计算它? 最佳答案 相机向下看它的内部负 z 轴。所以选择相机负 z 轴上的任意点,如下所示: var
重要提示:请注意这个问题是关于 VECTOR map 的。不是高度图。 我正在尝试在 Scenekit 中实现 Vector 位移,如 apple 演示文稿中所述: https://www.youtu
我正在处理一个稳定增长的语料库。我使用用 Python 实现的 Doc2Vec 来训练我的文档向量。 是否可以更新文档向量? 我想使用文档向量进行文档推荐。 最佳答案 单个向量可以更新,但是 gens
我正在努力寻找一种比较(测量)两个不同信号之间相似性的好方法。我不想找出一个信号到另一个信号的时间延迟,但我想看看它们之间有何相似之处。例如,我有以下两个信号,比如说 s1 ans s2。这两个信号看
我想绘制 y 与 x 线,然后在它上面我想绘制向量。我可以使用 matplotlib 的 plot 和 quiver 函数来做到这一点。但是,矢量将始终绘制在线的后面,而不是在线的顶部。也就是说,线将
包含复数的向量 a 的大小为 N×1。任务是找到乘法a * a^HA (N-by-N) >,其中 H 是 Hermitian 算子(共轭转置),因此矩阵 A 是 Hermitian。 有没有比 O(N
三天来,我一直在努力从我的响应中获取复杂类型(列表),但总是收到 ClassCastException D/SOAPEnvelope(1552): Error: java.lang.ClassCast
在我的 android 项目中,我想要离线 map 。使用图 block ,我的 map 占用 500 MB 的空间,我还想在 map 上离线搜索地址。我认为减小尺寸并使搜索成为可能的唯一方法是矢量
什么是 Android Compose 方法来平铺图像以用小图案填充我的背景? 没有旋转的位图的天真方法可能是这样的: @Composable fun TileImage() { val pa
我是一名优秀的程序员,十分优秀!