美文网首页
多线程多进程以及python中的实现

多线程多进程以及python中的实现

作者: DUTZCS | 来源:发表于2020-10-31 10:42 被阅读0次

    多线程和多进程

    通常在硬件层面上和操作系统层面上都存在线程的概念。但是这两个概念是完全不同的,是一个词汇在不同层面上的不同意思。

    CPU数,核心数,硬件的线程数

    • CPU数指的是一个计算机主板上实际上卡槽中插入的CPU个数,由卡槽socket决定。一般的计算机是一个卡槽,因为多个卡槽的CPU之间共享内存等资源需要高级的技术。一般服务器是多个物理CPU的,也就是CUP数对于个人计算机是1,对于服务器是>1.

    • 核心数指的是单个CPU的内部存在的可以同时处理的处理器。

      • 这里首先强调是这里的核心是CPU内部存在一定的硬件支持的
      • 第二是这里的同时指的是真正的同时处理,不同于操作系统层面上的同时可以是单个核心不断切换导致的同时。
    • 线程数thread,逻辑处理器logical processor,或者虚拟核心virtual core,是同一个东西,指的是一个核心中可以存在着SMT(simultaneous multithreading)或者HT(hyper-threading)技术,这些技术可以使得单个核心同时执行多个线程,就相当于上文提到的单个核心数内部又存在多个子核心,总的核心是这些子核心数之和。

    所以系统总的核心数实际上是上面所有的乘积。也就是逻辑处理器数量= CPU数* 核心数 * 超线程数(SMT or HT) 。

    最后在硬件层面上其实线程和进程是一样的,指的就是几个核心或者存在超线程时候的总的线程数。

    Linux查看以上信息的命令,lscpu或者到/proc/cpuinfo查看。

    Windows可以直接看任务管理器。

    操作系统层面的进程和线程

    1. 操作系统层面上(不严格讲)
    • 一个线程指的是一串又有逻辑的指令,要先执行a,在执行b,等等。
    • 一个进程简单理解就指的是一个程序,或者应用程序。
    1. 举例来说,打开一个应用程序,比如word,就会启动一个或者多个进程,每个进程执行一个任务,同时为了执行一个任务可能需要多个子任务,这些子任务就是线程。比如写入word时候需要自动保存也需要拼写检查,这就是同一个进程下的不同的线程。

    2. 操作系统层面的多进程和多线程指的是,基于单核没有超线程的CPU来说,操作系统会调度这些进程或者线程进行极短时间内的切换,以至于我们看不出来是切换的。所以任务是同时的。所以单核当CPU没办法实现真正的并行,单次或者每个时间只能进行一个线程或者进程,但是只要我切换的够快,时间就追不上我。还需要注意,一般我们使用程序数量远远多于计算机总的逻辑处理器数量,所以即便对于多核CPU来说,系统的切换也是极其重要的。

    3. 进程和线程本质是一个包含的关系,所以多进程和多线程机制是不同的,比如同一个进程内的多线程可以共享内存等等资源,通信也更加简单,每个线程需要自己的堆栈寄存器,所以占用资源少,多进程就是相对独立的,需要更多的内存等。所以分为多线程,多进程,和多线程多进程三种。多线程是指在一个进程中存在多个线程。

    python的多进程(多线程)

    python数值计算应该使用多进程的,对于计算密集型的,这样比较稳定稳定可靠,另外多线程对于有些变量会交错使用,导致结果容易错误。I/O密集型的大部分都在等待写入到硬盘时间, 对于I/O密集型的可以用多线程。另外python还有GIL。

    多进程

    • 利用multiprocessing中的Process实例,方法

      from multiprocessing import Process
      
      p=Process(target=func,args=(arg,))#要进行多进程的程序需要写入到一个函数中。
      p.start()
      p.join()#等待进程都结束,用于同步。
      
      
    • 利用multiprocessing 中的Pool实现,启动大量的进程。

      from multiprocessing import Pool
      
      p=Pool(4)#需要的logical 核心数量,一般和计算机有关。
      
      def func():
          pass
      
      for ii in range(5)
          p.apply_async(target=func,args=(arg,))
          p.close()#在close之后就不能加入新的进程。
          p.join()#用于等待所有进程结束,必须在close之后。
      
    • 子进程之间的通信,利用queue.可以实现不同的进程写或者读取同一个结果。

      from multiprocessing import Process, Queue
      import time
      
      def wirte(a):
          valus=['A','B','C']
          for ii in valus:
              a.put(ii)
              time.sleep(5)
      
      def read(a):
          while True:
              q.get(True)
      
      q=Queue()
      pw=processing(target=,args=(q,))
      pr=processing(target=,args=(q,))
      pw.start()
      pr.start()
      pw.join()
      pr.join() or pr.terminate()#手动终止程序。
      
    • 多进程的返回值

      返回值初级用法

      • join的作用是主程序等待这个程序结束继续执行p.join以后的内容,如果没有join则执行完程序不再执行以后的内容。
      • 这里使用结束并行之后使用get或者多进程的返回值。

    多线程

    • 利用threading,方法和multiprocessing类似

      import threading
      
      p=threading.Thread(target=,name='loop')
      p.start()
      p.join()
      threading.current_thread().name用于返回当前线程名字。
      
    • 启动一个进程内的多线程时候, 都会首先建立一个主线程名字是Mainthread,接着会建立其他的子线程,名字默认是thread-1,Thead-2,或者是我们可以给定一个名字,比如上面所示,我们给定了一个loop的名字name.

    • 该模块中又一个current_thread()的实例,用于返回当前线程。

    • 多线程会有时候出错,例如

    一般来说用计算过程中多进程就够了。

    python中qutip的并行

    • 并行使用 qutip.parapallel.parfor,和 parallel.parallel_map,这两种函数进行并行。本质上qutip中的并行是借用了multiprocessing, 而且mcsolve方法中多条轨迹也是并行的,所以不能嵌套并行和mcsolve。

    • 使用方法:首先定义一个函数该函数是要进行并行的函数,之后使用parfor传入函数和参数进行并行。

      def func(x):
          return x**2
      
      parfor(func,range(10))
      ##
      parallwl_map(func,range(10))
      
    • 这两个函数略有区别,返回的结果的顺序是不同的。(具体参考文档P127)

    • 该函数可以输入的变量不限于数字。

    • 该函数可以传入多个参数,这些参数的遍历方法不同,对于parfor和parallel有不同的遍历参数方法,同时支持传入任意关键词参数,但是不会用于计算。进行计算的仅仅是函数要求的那些。此外parfor的关键词不可以是num_cpus这是用于给定计算所需要的核心的。具体参考(128)

    • 此外还可以加入progress_bar,只有parallel 有.

    最后

    Linux 并行嵌套会报错,子进程不能有守护进程。但是可以在循环之内写并行。

    相关文章

      网友评论

          本文标题:多线程多进程以及python中的实现

          本文链接:https://www.haomeiwen.com/subject/ebksvktx.html