加快For循环下嵌套的IF循环的速度 [英] Speed up nested if loops under a for loop

查看:37
本文介绍了加快For循环下嵌套的IF循环的速度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在二维平面上,有一个以(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()
.
.
.

推荐答案

第二个For下的rule1和rule2耗时最长。

内联rule1rule2。如果and知道第一部分为假,则它不会计算第二部分。也试着调换一下,看看这样会不会更好。

根据这些规则的计算方式的详细信息,您可能会发现其他类似快捷方式的机会。


始终分析以查找瓶颈。您可能会浪费大量时间来优化其他不会有太大帮助的部分。

尽可能走捷径;不要浪费时间计算不需要的东西。

通过内联来避免嵌套循环中的函数调用。在CPython中调用有点慢。

展开内部循环以减少循环开销。

尽可能在循环外计算,而不是每次循环都重做。


考虑使用Nutika、Cython或PyPy编译整个代码。(或者只使用Cython或Numba的较慢部分。)

考虑用Julia重写这一部分,它更快、更容易从Python中调用。最好提取并调用整个内部循环,而不仅仅是它的主体,以避免每个循环的调用开销。

考虑在可能的情况下使用NumPy向量化计算,即使它只是循环的一部分。Numpy的内部循环比Python的快得多,这会占用更多的内存。如果你能让NumPy矢量化工作,你也许能通过使用GPU的CuPy或可以处理更大数据集的Dask来获得更大的加速比。

这篇关于加快For循环下嵌套的IF循环的速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆