Python:缓慢嵌套for循环

时间:2016-09-19 08:57:09

标签: python performance linear-programming constraint-programming

我需要根据某些限制条件找出最佳的媒体选择。我在四个嵌套for循环中进行它,因为它需要大约O(n ^ 4)次迭代,所以它很慢。我一直试图让它更快,但它仍然很慢。我的变量可能高达几千。

以下是我想要做的一个小例子:

    max_disks = 5
    max_ssds = 5
    max_tapes = 1
    max_BR    = 1
    allocations = []
    for i in range(max_disks):
     for j in range(max_ssds):
        for k in range(max_tapes):
            for l in range(max_BR):
                allocations.append((i,j,k,l)) # this is just for example. In actual program, I do processing here, like checking for bandwidth and cost constraints, and choosing the allocation based on that. 

每种媒体类型达数百种并不慢,但数千种速度会慢下来。

我试过的其他方式是:

    max_disks = 5
    max_ssds = 5
    max_tapes = 1
    max_BR    = 1

    allocations = [(i,j,k,l) for i in range(max_disks) for j in range(max_ssds) for k in range(max_tapes) for l in range(max_BR)]

这种方式即使这么小的数字也很慢。

两个问题:

  1. 为什么第二个对于小数字来说速度慢?
  2. 如何让我的程序适用于大数字(数千个)?
  3. 以下是itertools.product

    的版本
                max_disks = 500
                max_ssds = 100
                max_tapes = 100
                max_BR    = 100
                # allocations = []
                for i, j, k,l in itertools.product(range(max_disks),range(max_ssds),range(max_tapes),range(max_BR)):
                    pass
    

    完成这些数字需要19.8秒。

2 个答案:

答案 0 :(得分:3)

从评论中我得知你正在处理一个可以重写为ILP的问题。您有几个约束,需要找到(近)最优解决方案。

现在,ILP很难解决,而且强迫它们迅速变得难以处理(正如您已经目睹过的那样)。这就是为什么业内使用的几种非常聪明的算法真正起作用的原因。

对于Python,有很多接口可以与现代解算器连接;有关详细信息,请参阅例如SO post。您也可以考虑使用优化器,如SciPy optimize,但那些通常不进行整数编程。

答案 1 :(得分:0)

在Python中执行任何操作万亿次都会很慢。但是,这不是你所做的全部。通过尝试将所有万亿项目存储在一个列表中,您将大量数据存储在内存中,并以一种为计算机创建大量工作的方式对其进行操作,以便在内存不再适合RAM时将内存交换进出。 / p>

Python列出的工作方式是它们分配一些内存来存储列表中的项目。当您填写列表并且需要分配更多内容时,Python将分配两倍的内存并将所有旧条目复制到新的存储空间中。这很好,只要它适合内存 - 即使它每次扩展存储时都必须复制列表的所有内容,它必须不那么频繁地这样做,因为它会使大小增加一倍。当内存不足并且必须将未使用的内存交换到磁盘时,问题就出现了。下次尝试调整列表大小时,它必须从磁盘重新加载所有现在交换到磁盘的条目,然后再将它们全部重新交换以获得写入新条目的空间。因此,这会产生大量缓慢的磁盘操作,这些操作会妨碍您的任务并减慢速度。

您真的需要将每个项目存储在列表中吗?你做完后他们会怎么做?您可以将它们写入磁盘,而不是将它们累积在一个巨大的列表中,但如果你有一万亿个,那么仍然是一个非常大量的数据!或者你可能过滤了大部分?这会有所帮助。

所有这一切,如果没有看到实际的程序本身,很难知道你是否希望通过详尽的搜索来完成这项工作。所有变量都可以一次成千上万吗?你真的需要考虑这些变量的每个组合吗?当max_disks == 2000时,你真的需要区分i = 1731的结果和i = 1732吗?例如,也许您可​​以考虑i 1,2,3,4,5,10,20,30,40,50,100,200,300,500,1000,2000的值?或许还有一个数学解决方案呢?你只是在计算物品吗?