目前个人计算机大都是多核的,但是在运行python程序的时候会发现实际上只有一个核心(CPU)在跑代码,另外几个核心都在偷懒呢,如下图


Python 并行计算函数 python并行计算框架_Python 并行计算函数

 


并行计算的目的是将所有的核心都运行起来以提高代码的执行速度,在python中由于存在全局解释器锁(GIL)如果使用默认的python多线程进行并行计算可能会发现代码的执行速度并不会加快,甚至会比使用但核心要慢!!!


一些并行模块通过修改pyhton的GIL机制突破了这个限制,使得Python在多核电脑中也能够有效的进行并行计算。PP(Parallel Python)模块就是其中一种。


pp模块是python的一个轻量级并行模块,能够有效提高程序运行效率,使用非常方便。


下面这段测试代码是计算从0到给定范围内所有质数的和,即计算0~100000,0~100100,... ,0~100700这8个范围内的所有质数的和:



    1.  import pp,time,math
    2.  def isprime(n):
    3.      """Returns True if n is prime and False otherwise"""
    4.      if not isinstance(n, int):
    5.          raise TypeError("argument passed to is_prime is not of 'int' type")
    6.      if n < 2:
    7.          return False
    8.      if n == 2:
    9.          return True
    10.      max = int(math.ceil(math.sqrt(n)))
    11.      i = 2
    12.      while i <= max:
    13.          if n % i == 0:
    14.              return False
    15.          i += 1
    16.      return True
    17. 18.  def sum_pimes(n):
    19.      """Calculates sum of all primes below given integer n"""
    20.      return sum([x for x in range(2, n) if isprime(x)])
    21. 22.  #串行代码
    23.  print("{beg}串行程序{beg}".format(beg='-'*16))
    24.  startTime = time.time()
    25. 26.  inputs = (100000, 100100, 100200, 100300, 100400, 100500, 100600, 100700)
    27.  results = [ (input,sum_primes(input)) for input in inputs ]
    28. 29.  for input, result in results:
    30.      print("Sum of primes below %s is %s" % (input, result))
    31. 32.  print("用时:%.3fs"%( time.time()-startTime ) )
    33. 34.  #并行代码
    35.  print("{beg}并行程序{beg}".format(beg='-'*16))
    36.  startTime = time.time()
    37. 38.  job_server = pp.Server()
    39.  inputs = (100000, 100100, 100200, 100300, 100400, 100500, 100600, 100700)
    40.  jobs = [(input, job_server.submit(sum_primes, (input, ), (isprime, ),
    41.          ("math", )) ) for input in inputs]
    42. 43.  for input, job in jobs:
    44.      print("Sum of primes below %s is %s" % (input, job()))
    45. 46.  print("用时:%.3fs"%( time.time()-startTime ) )
    47.


    复制代码



    运行效果图:


    Python 并行计算函数 python并行计算框架_并行计算_02

     


    由于楼主的电脑是伪4核(实际是2核,由于intel使用了超线程把它变成了4核的样子),因此效率只是提高了两倍,不过也还是不错了~

    理论上你的电脑中实际有多少的个核心,通过并行计算就能提高多少被效率(实际的提高倍速会低一点)。


    可以看到并行代码只是比串行代码多了几行,然而效率就翻倍了,看到这各位鱼油有木有动心呢

    Python 并行计算函数 python并行计算框架_元组_03

     


    下面就开始正式介绍这个模块了


    一:安装


    1.从官网下载对应版本的PP模块:http://www.parallelpython.com/content/view/18/32/

    我的系统是Windows,python版本是3.4.4因此选择了下面这个版本


    Python 并行计算函数 python并行计算框架_Python 并行计算函数_04

     


    2.在解压目录下打开命令行,输入python setup.py install就自动开始安装了(就是这么简单

    Python 并行计算函数 python并行计算框架_元组_03

     )


    Python 并行计算函数 python并行计算框架_python_06

     


    二:使用


    1.导入模块



    1. import pp



    复制代码



    2.开启服务



      1.  job_server = pp.Server() 
      2.  #ncpus = 4 #可以自己指定使用的核心数
      3.  #job_server = pp.Server(ncpus) #创建服务
      4.  #默认为使用全部核心


      复制代码



      3.提交任务



      1.  f1 = job_server.submit(func1, args1, depfuncs1, modules1) 
      2.  #func1: 被并行执行的函数
      3.  #args1: func的参数,以元组的形式传入
      4.  #depfuncs1: 被func调用的函数,以元组的形式传入
      5.  #modules1: 函数执行需要调用的模块,以元组的形式传入



      复制代码



      4.获取结果



      1. r1 = f1()



      复制代码




      下面根据之前的测试例子解释下pp模块的使用


      子程序



        1.  math
        2.  def isprime(n):
        3.      if not isinstance(n, int):
        4.          raise TypeError("argument passed to is_prime is not of 'int' type")
        5.      if n < 2:
        6.          return False
        7.      if n == 2:
        8.          return True
        9.      max = int(math.ceil(math.sqrt(n)))
        10.      i = 2
        11.      while i <= max:
        12.          if n % i == 0:
        13.              return False
        14.          i += 1
        15.      return True
        16. 17.  def sum_pimes(n):
        18.      return sum([x for x in range(2, n) if isprime(x)])
        19.

        复制代码



        主程序



          1.  import pp
          2.  job_server = pp.Server()
          3.  inputs = (100000, 100100, 100200, 100300, 100400, 100500, 100600, 100700)
          4.  jobs = [(input, job_server.submit(sum_primes, (input, ), (isprime, ),
          5.          ("math", )) ) for input in inputs]
          6.  for input, job in jobs:
          7.      print("Sum of primes below %s is %s" % (input, job()))
          8.


          复制代码



          第1行:导入pp模块

          第2行:开启pp服务,没有填参数表示使用全部核心进行计算

          第3行:设定任务,即程序需要计算0~100000,0~100100,... ,0~100700这8个范围内的所有质数的和

          第4行:是一个列表推导式,它的作用是将inputs中的值传递给sum_primes,并且执行job_server.submit函数。




            1.  在job_server.submit的参数:
            2.  - sum_primes为被并行执行的函数,注意这里不能写成sum_primes()
            3.  - (input,)为sum_primes的参数即100000,100100,...,100700。注意这里要以元组形式传入,而","是元组的标志,因此括号中的逗号不能漏了
            4.  - (isprime,)是sum_primes执行过程中需要用到的函数,以元组形式传入
            5.  - ("math",)是sum_primes或isprime函数中需要用到的模块,以元组形式传入


            复制代码



            最后两行:执行完第四行后得到的jobs列表中的每个元素都是一个二元组即(input,func)的形式。这两行的意思就是循环调用func,并打印结果。(通过函数调用的方式获取并行计算结果)

            到这里一个使用pp模块进行并行计算的代码就实现了(并行计算就是如此简单

            Python 并行计算函数 python并行计算框架_并行计算_07

             )。


            随着任务的需求不同,代码量也会有所变化,不过基本过程就是以上四步。