为什么我的线程python合并的CPU使用率只为每个核心排序50%?

时间:2013-05-04 23:07:12

标签: python multithreading algorithm sorting cpu-usage

问题

  • 为什么我的线程python合并的CPU使用率只为每个核心排序50%?
  • 为什么这会导致“无法为相对较小的输入创建新线程”错误(100000)
  • 我怎样才能使这更加pythonic? (这很难看。)
  • Linux / Ubuntu 12.4 64位i5移动版(四核)

    from random import shuffle
    from threading import *
    
    import time
    import Queue
    
    
    q = Queue.LifoQueue()
    
    def merge_sort(num, q):
      end = len(num)
    
      if end > 1:
        mid = end / 2
        thread = Thread(target=merge_sort, args=(num[0:mid],q,))
        thread1 = Thread(target=merge_sort, args=(num[mid:end],q,))
    
        thread.setDaemon(True)
        thread1.setDaemon(True)
    
        thread.start()
        thread1.start()
    
        thread.join()
        thread1.join()
    
        return merge(q.get(num), q.get(num))
      else:
        if end != 0:
         q.put(num)
        else:
         print "?????"
         return
    
    
    def merge(num, num1):
      a = []
      while len(num) is not 0 and len(num1) is not 0:
        if num[0] < num1[0]:
          a.append(num.pop(0))
        else:
          a.append(num1.pop(0))
      if len(num) is not 0:
        for i in range(0,len(num)):
          a.append(num.pop(0))
      if len(num1) is not 0:
        for i in range(0,len(num1)):
          a.append(num1.pop(0))
      q.put(a)
      return a
    
    
    
    def main():
    
        val = long(raw_input("Please enter the maximum value of the range:")) + 1
        start_time = time.time()
        numbers = xrange(0, val)
        shuffle(numbers)
    
    
        numbers = merge_sort(numbers[0:val], q)
    
    #    print "Sorted list is: \n"
    #    for number in numbers:
    #      print number
    
        print str(time.time() - start_time) + " seconds to run.\n"
    
    if __name__ == "__main__":
        main()
    

    2 个答案:

    答案 0 :(得分:3)

    对于100000输入,您的代码会尝试创建~200000个线程。 Python线程是真正的操作系统线程,因此您看到的50%CPU负载可能是系统忙于处理线程。在我的系统上,错误发生在~32000个线程附近。

    您编写的代码无法正常工作:

    from random import shuffle
    
    #XXX won't work    
    numbers = xrange(0, val)
    shuffle(numbers)
    

    xrange()不是一个可变序列。

    注意:排序所需的时间比阵列的随机混乱少得多:

    import numpy as np
    
    numbers = np.random.permutation(10000000) # here spent most of the time
    numbers.sort()
    

    如果要使用不同的线程对数组的某些部分进行排序;你可以做到:

    from multiprocessing.dummy import Pool # use threads 
    
    Pool(2).map(lambda a: a.sort(), [numbers[:N//2], numbers[N//2:]])
    

    a.sort()发布GIL,因此代码使用2个CPU。

    如果包括合并已排序部分所需的时间;在单个线程中一次对整个数组进行排序(numbers.sort())可能会更快。

    答案 1 :(得分:1)

    您可能希望使用Parallel Python进行调查,因为默认CPythonGlobal Interpreter Lock (GIL)而限制为一个核心。这就是CPython无法执行真正的CPU绑定并发操作的原因。但是,CPython仍然很擅长执行IO绑定任务。

    有一篇很好的文章描述了CPyton here的线程限制。