python多线程“最大递归深度超过”

时间:2010-04-26 03:43:13

标签: python recursion depth multithreading

我使用Python多线程来实现Quicksort。 Quicksort是在函数中实现的。它是一个递归函数。 每个线程调用Quicksort对它拥有的数组进行排序。每个线程都有自己的数组,用于存储需要排序的数字。 如果阵列大小较小(<10,000)。它运行正常。 但是,如果数组大小较大,则显示“最大递归深度超过”。 所以,我使用setrecursionlimit()函数将递归深度重置为1500.但程序直接崩溃... 以下是快速排序代码。如果不在多线程环境中,它可以很好地工作。 似乎多线程是递归深度问题的原因。

def partition (array, p, r):
    x = array[r]
    i = (p-1)
    j = p
    while (1):
        if array[j] <= x:
            i = (i+1)
            temp = array[j]
            array[j] = array[i]
            array[i] = temp
        j+=1
        if j == r:
            break
    temp = array[i+1]
    array[i+1] = array[r]
    array[r] = temp
    return i+1

def quicksort (array, p, r):
    if p < r:
        q = partition (array, p, r)
        quicksort (array, p, q-1)
        quicksort (array, q+1, r)

5 个答案:

答案 0 :(得分:6)

听起来你真正的问题是“为什么使用线程时递归深度更短”?我会尝试回答这个问题。

首先,背景。每个级别的递归都存储在称为堆栈的内存区域中。不幸的是,系统必须提前分配堆栈空间,并且事先并不知道程序可能需要多少堆栈空间。这就是太多递归导致“最大递归深度”错误的原因:你的程序耗尽了所有的堆栈空间。

每个线程都需要自己的堆栈来存储当前在该线程中执行的函数列表。在单线程程序中,系统可以为该一个线程提供大量内存给堆栈。在多线程程序中,系统必须更加保守,并且每个线程只提供一个小堆栈。否则,具有多个线程的程序可能会快速耗尽所有系统内存,只有堆栈空间(大部分不会被使用)。

所有这些都是由操作系统和/或C库完成的,而Python(更确切地说,CPython)运行在C库之上。 Python努力阻止您使用整个C堆栈,因为这会导致硬崩溃而不仅仅是异常。您可以告诉Python如何使用setrecursionlimit函数执行操作,但这不会更改实际可用堆栈空间量。

在具有bash shell的unix-ish系统上,您可以使用ulimit -s命令更改堆栈大小。在bash shell提示符下键入help ulimit以获取更多信息。

答案 1 :(得分:1)

你为什么要编写自己的快速例程?这是家庭作业吗?

如果没有,我建议使用内置的排序机制;它们对绝大多数情况都很好,并且不会受到递归深度问题的影响。如果您正在查看非常大的数据集,我建议您查看scipy和numpy提供的各种容器和算法。

如果纯粹是为了实现例程的好奇心,正如Marcelo在评论中所说,我们需要看代码。

答案 2 :(得分:1)

  • 您正在使用quicksort的递归实现。 您希望使用迭代实现快速排序。

    递归在Python中是不可扩展的(至少在CPython中),因此对于较大的输入,它将失败。您可以增加递归限制,但这只会让您扩展到更大的范围,而不是让您的实现真正扩展。如果你有太多的递归,它的代价是允许段错误的可能性。这种方法对于多线程代码也有效(或者说确实不起作用),你只需要做更多,因为每个线程的递归限制会更低。总而言之,这是一个失败的主张:改为使用迭代。

  • 您正在使用线程(或计划),这通常是一个不好的迹象。线程令人困惑,危险和困难。更重要的是,Python中的线程不会为您提供并行执行,如果这是您所期望的。使用线程进行快速排序实现,特别是在Python中,可能不太理想。 (如果你被要求这样做,你至少应该退后一步,理解它可能不是最好的方法。)

答案 3 :(得分:0)

你遇到的问题是一个递归函数使用内存,并且有大量的元素,因而大量的递归,你的内存不足。这解释了为什么提高递归限制会使程序崩溃 - 你要求的内存比你的要多。

如果你真的想为大量元素实现快速排序,你会想要特别使用quicksort阅读有关内存使用情况的维基百科上的this文章。否则,正如Nathan建议的那样,Python已经内置了sorted()函数。除非这是家庭作业或好奇心,否则我强烈建议使用它。

答案 4 :(得分:0)

以下是QuickSort的迭代代码

    import time
    import random

    stack = []

    def partition(data,p,q):
        global stack
        pivot = p
        pivotvalue = data[q]
        for index in range(p,q+1):
            if data[index] < pivotvalue:
                temp = data[index]
                data[index] = data[pivot]
                data[pivot] = temp
                pivot = pivot + 1
        temp = data[q]
        data[q] = data[pivot]
        data[pivot] = temp
        return pivot

    def qSort(data,p,q):
        global stack
        push(stack,p,q)
        while isEmpty(stack) == False:
            q = pop(stack)
            p = pop(stack)
            pivot = partition(data,p,q)
            if pivot-1 > p:
                push(stack,p,pivot-1)
            if pivot+1 < q:
                push(stack,pivot+1,q)


    def push(stack,p,q):
        stack.append(p)
        stack.append(q)

    def pop(stack):
        global top
        if(len(stack)==0):
            return -1
        element = stack.pop()
        return element

    def isEmpty(stack):
        return len(stack) == 0

    if __name__ == '__main__':
        start_time = time.time()
        data = (range(1000000,0,-1))
        random.shuffle(data)
        #print data
        qSort(data,0,len(data)-1)
        #print data
        print time.time() - start_time, "seconds"