问题描述
在二维平面上,有一个以(0,0)为中心、半径为𝑅𝑜的大圆。它包围了∼100左右的较小的圆,这些圆随机分布在父圆上,否则相对于原点的半径和位置是已知的。(一些较小的子圆可能部分或全部位于较大的子圆内。)
整个平面被均匀地网格化为像素,边是水平的和垂直的(沿坐标轴)。像素的大小是固定的,并且是先验已知的,但在其他方面比父圆的大小小得多;整个父圆大约有1000个特殊像素。我们得到了所有这些特殊网格(中心)的二维笛卡尔坐标。包围这些特殊网格中至少一个的子圆被命名为*特殊"子圆,以备以后使用。
现在,想象所有的3D空间都充满了大约1亿个粒子。我的代码尝试将这些粒子相加到每个特殊的子圆内。
我设法调试了我的代码,但似乎当我处理如此大量的粒子时,它非常慢,如下所示。我想看看我是否可以使用任何技巧将其加快至少一个数量级。
.
.
.
for x, y in zip(vals1, vals2): # vals1, vals2 are the 2d position array of the *special* grids each with a 1d array of size ~1000
enclosing_circles, sub_circle_catalog, some_parameter_catalog, totals = {}, [], [], {}
for id, mass in zip(ids_data, masss_data): # These two arrays are equal in size equal to an array of size ~100,000,000
rule1 = some_condition # this check if each special grid is within each circle
rule2 = some_other_condition # this makes sure that we are only concerned with those circles larger than some threshold size
if (rule1 and rule2):
calculated_property = some_function
if condition_3:
calculated_some_other_property = some_other_function
if condition_4:
some_quantity = something
enclosing_circles[id] = float('{:.4f}'.format(log10(mass)))
some_parameter[id] = float('{:.3e}'.format(some_quantity))
# choose all sub-circles' IDs enclosing the special pixel
enclosing_circles_list = list(enclosing_circles.keys())
some_parameter_list = list(some_parameter.keys())
sub_circle_catalog += [(enclosing_circles[i], 1) for i in enclosing_circles_list]
some_parameter_catalog += [(enclosing_circles[i], some_parameter[j]) for i, j in zip(enclosing_circles_list, some_parameter_list)]
# add up all special grids in each sub-circle when looping over all grids
for key, value in sub_circle_catalog:
totals[key] = totals.get(key, 0) + value
totals_dict = collections.OrderedDict(sorted(totals.items()))
totals_list = list(totals.items())
with open(some_file_path, "a") as some_file:
print('{}'.format(totals_list), file=some_file)
some_file.close()
.
.
.
推荐答案
内联rule1
和rule2
。如果and
知道第一部分为假,则它不会计算第二部分。也试着调换一下,看看这样会不会更好。
根据这些规则的计算方式的详细信息,您可能会发现其他类似快捷方式的机会。
始终分析以查找瓶颈。您可能会浪费大量时间来优化其他不会有太大帮助的部分。
尽可能走捷径;不要浪费时间计算不需要的东西。
通过内联来避免嵌套循环中的函数调用。在CPython中调用有点慢。
展开内部循环以减少循环开销。
尽可能在循环外计算,而不是每次循环都重做。
考虑使用Nutika、Cython或PyPy编译整个代码。(或者只使用Cython或Numba的较慢部分。)
考虑用Julia重写这一部分,它更快、更容易从Python中调用。最好提取并调用整个内部循环,而不仅仅是它的主体,以避免每个循环的调用开销。
考虑在可能的情况下使用NumPy向量化计算,即使它只是循环的一部分。Numpy的内部循环比Python的快得多,这会占用更多的内存。如果你能让NumPy矢量化工作,你也许能通过使用GPU的CuPy或可以处理更大数据集的Dask来获得更大的加速比。这篇关于加快For循环下嵌套的IF循环的速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!