Ash*_*Ash 0 python performance for-loop if-statement nested-loops
在2d平面上,有一个以(0,0)为中心的大圆,半径为.它包含约100个左右的较小圆圈,这些圆圈在父圆上随机分布,否则具有相对于原点的已知半径和位置.(有些较小的子圆可能部分或全部位于较大的子圆内.)
整个平面均匀地网格化为像素,边长为水平和垂直(沿坐标轴).像素的大小是固定的并且是先验已知的,但是远小于父圆的大小; 在父圆圈上有大约1000个特殊像素的顺序.我们给出了所有这些特殊网格(的中心)的2D笛卡尔坐标.包含这些特殊网格中的至少一个的那些子圆被命名为*特殊的"子圆圈以供以后使用.
现在,想象一下所有这个3d空间都充满了~100,000,000个粒子.我的代码尝试在每个特殊子圈内添加这些粒子.
我设法调试我的代码,但似乎当我处理如此大量的粒子时,它很慢,如下所示.我想看看我是否可以使用任何技巧来加速它至少一个数量级.
.
.
.
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()
.
.
.
Run Code Online (Sandbox Code Playgroud)
第二个规则下的rule1和rule2花费的时间最长.
内联rule1和rule2.and如果它知道第一部分是假的,则不会评估第二部分.也尝试交换它们,看看是否更好.
根据计算这些规则的详细信息,您可以找到其他快捷方式.
总是寻找瓶颈来找到瓶颈.您可以浪费大量时间来优化其他无用的部分.
可能的捷径; 不要浪费时间计算你不需要的东西.
通过内联循环避免嵌套循环中的函数调用.CPython中的呼叫有点慢.
展开内部循环以减少循环开销.
尽可能计算循环外的东西,而不是每次循环重做它.
考虑使用Nutika,Cython或PyPy编译整个事物.(或者只是Cython或Numba的慢速部分.)
考虑在Julia中重写这个部分,这可以更快,更容易地从Python调用.最好提取并调用整个内部循环,而不仅仅是它的主体,以避免每个循环的调用开销.
考虑尽可能使用numpy进行矢量化计算,即使它只是循环的一部分.Numpy的内部循环比Python快得多.这可能会占用更多内存.如果你可以使numpy矢量化工作,你可以使用CuPy(使用GPU或可以处理更大数据集的Dask)获得更大的加速.