我目前正在为体积建模(使用有符号距离场)编写一个 python 包,并希望提高线段 sdf 计算的性能。我尝试了几种不同的实现,但似乎无法获得任何额外的速度。我将总结如下:
生成 sdf 的当前代码:
x_ = np.linspace(lowerx, upperx, res)[:, None, None]
y_ = np.linspace(lowery, uppery, res)[None, :, None]
z_ = np.linspace(lowerz, upperz, res)[None, None, :]
self.p1_ = np.array([0,0,-0.5])
self.p1_ = np.array([0,0,0.5])
self.r = 0.25
def evaluate_point_bc(self, x_, y_, z_):
pa_x = x_ - self.p1_[0]
pa_y = y_ - self.p1_[1]
pa_z = z_ - self.p1_[2]
ba_ = self.p1_ - self.p2_
baba_ = np.dot(ba_, ba_)
paba_ = np.dot(np.array([pa_x, pa_y, pa_z], dtype=object), ba_)
h_ = np.clip((paba_ / baba_), 0.0, 1.0) # 11.3% of execution time
# self.design_space.x_grid has shape (res, res, res)
# Hence arr has shape (3, res, res, res)
# The DATA_TYPE is np.float32
arr = np.empty_like([self.design_space.x_grid, self.design_space.x_grid,
self.design_space.x_grid], dtype=self.design_space.DATA_TYPE) # 17.1% of execution time
arr[0] = pa_x - np.dot(ba_[0], h_) # 17.7% of execution time
arr[1] = pa_y - np.dot(ba_[1], h_) # 17.6% of execution time
arr[2] = pa_z - np.dot(ba_[2], h_) # 16.5% of execution time
return np.linalg.norm(arr, axis=0) - self.r # 17.6% of execution time
x_、y_ 和 z_ 是样本点的 3D 坐标。我正在尝试使用广播来节省内存并加快速度。通常,“res”参数的范围是 100-300。我添加了注释以显示哪些行占据了大部分执行时间。我使用 pycharm line profiler 插件对函数计时。
目前,此实现有效,但对我的需求来说太慢了。我需要能够为格网络中的许多行运行数百次(输入点 x_、y_ 和 z_ 将相同,但每个点的 p1_ 和 p2_ 都会改变)。如果有一种方法可以加快速度,那就太好了,否则更有效的方法来多次运行它(例如像 numba 之类的东西)也会很棒。我也尝试过将 numexpr 与完整的 meshgrid 数组一起使用,而不是广播。
我希望这很清楚!