python-マルチタスク操作(マルチプロセス、マルチスレッド、プロセスプール)


文書ディレクトリ
  • 1、プロセス、スレッドとコモン
  • 2、マルチタスク
  • 3、threadingモジュールはマルチタスク
  • を実現する
  • 4、multiprocessingモジュール実現マルチタスク
  • 5、プロセスプール実現マルチタスク
  • 1、プロセス、スレッドと協力
  • プロセス:プログラム+リソース、すなわち実行中のプログラムは、オペレーティングシステムのリソース割り当ての最小単位
  • である.
  • スレッド:軽量プロセス、オペレーティングシステムのスケジューリング実行の最小単位
  • コパス:スレッドよりも軽量レベルで、オペレーティングシステムによって管理されるのではなく、プログラムによって制御される(関数に似ている、または中断されている)
  • の3つの区分:
  • スレッドはプロセスに依存し、1つのプロセスには少なくとも1つのスレッド
  • がある.
  • プロセスとプロセスは独立しており、グローバル変数は共有されず、1つのプロセスのスレッド間は共有リソースの
  • である.
  • プロセスとスレッドはマルチタスクを実現できますが、プロセスのオーバーヘッドは
  • より大きいです.
  • プロセスとスレッドによるマルチタスクの実現は、タイムスライスホイールフローによる実行であり、コヒーレントによるマルチタスクの実現は、割り込みと同様の方法による
  • である.
  • プロセス、スレッドとスレッドの紹介、および3つの異同については、ここでは重点ではないので、
  • はよくわかりません.
    2、マルチタスク
  • タイムスライスローテーション:各プロセスに1つのタイムスライスが割り当てられ、複数のプロセスサイクルが交互に
  • を実行する.
  • 優先度スケジューリング:異なるプロセスの優先度が異なり、優先度の高いプロセスはcpuリソース
  • をプリエンプトすることができる.
  • パラレルと同時
  • パラレル:cpuコア数がタスク数より多い
  • 同時:タスク数がcpuコア数より多い
  • スレッドの実行順序は、オペレーティングシステムによって決定する
  • .
    3、threadingモジュールはマルチタスクを実現する
  • threadingモジュールは、マルチスレッド方式でマルチタスクを実現する
  • である.
  • メソッド
  • threading.Thread()サブスレッドオブジェクト(サブスレッドは作成されていません)を作成し、threadObjectオブジェクト
  • を返します.
  • threadObject.start()サブスレッドを作成し、サブスレッド
  • の実行を開始する.
  • threadObject.enumerate()現在のスレッド情報を表示
  • キー
  • サブスレッドは、関数をバインドすることもできるし、オブジェクトをバインドすることもできる(threading.Threadを継承することによって)
    class Demo(threading.Thread):  #        Demo,     threading.Thread
        def run(self):  #       ,     start     
            pass
        def func1(self):
            pass
    
    t = Demo()
    t.start()  #    start   ,         run  
    
  • .
  • サブスレッドは、キーワードパラメータargsを介して参照(バインド関数)
    In [1]: import threading
    
    In [2]: import time
    
    In [3]: num = 0
    
    In [4]: def demo1(temp):
       ...:     global num
       ...:     for i in range(temp):
       ...:         num += 1
       ...:         
    
    In [5]: def demo2(temp):
       ...:     global num
       ...:     for i in range(temp):
       ...:         num += 1
       ...:         
    
    In [6]: def test():
       ...:     t1.start()
       ...:     t2.start()
       ...:     time.sleep(2)
       ...:     
    
    In [7]: t1 = threading.Thread(target=demo1, args=(1000,))  
    # target         
    # args      ,     ,  args          ,       
    
    In [8]: t2 = threading.Thread(target=demo2, args=(2000,))
    
    In [9]: test()
    
    In [10]: num
    Out[10]: 3000
      
    
    # args     
    In [15]: def demo(temp1, temp2, temp3):
        ...:     print(temp1, temp2, temp3)
        ...:     
    
    In [16]: t = threading.Thread(target=demo, args=(1,2,3))
    
    In [17]: t.start()
    1 2 3
    
  • を伝達することができる.
  • サブスレッドバインドの関数の実行が終了すると、そのサブスレッドは
  • を終了する.
  • サブスレッド間共有グローバル変数
  • メインスレッドは最後に終了する必要があります.メインスレッドが終了すると、すべてのサブスレッドも
  • 殺されます.
  • サブスレッド共有グローバル変数による問題
  • サブスレッド共有グローバル変数は、リソースプリエンプト、リソース割り当ての不合理さ、プログラムエラー
  • などの問題をもたらす可能性があります.
  • リソース割り当ての不合理な解決方法
  • は、ステップ毎に必要な操作を原子的操作に分ける、各原子的操作はサブスレッド内で完了しなければならず、
  • を途中で退出することはできない.
  • pythonでは、次の方法でスレッドをロックします.
  • threadingObject.Lock()
  • スレッドロックオブジェクトを作成する(`threadingObject ), lockObject`オブジェクト
  • lockObject.acquire()
  • はスレッドにロックをかけ、この方法を実行した後、スレッドロックを解放しない限り、プロセスのリソースはこのスレッドによって
  • 占有される.
  • lockObject.release()
  • スレッドロック
  • を解放する

  • 注意:どのスレッドがacquire()を先に実行するか、そのスレッドは
  • にロックされます.

    4、multiprocessingモジュールはマルチタスクを実現する
  • multiprocessingモジュールは、マルチプロセスによりマルチタスク
  • を実現する.
  • 基本使用
    import multiprocessing
    def f1(parameter1, parameter2, ...):
        pass
    def f2():
        pass
    p1 = multiprocessing.Process(target=f1, args=(parameter1, parameter2, ...))  
    #         
    
    p2 = multiprocessing.Process(target=f2)
    p1.start()  #         ,                    
    p2.start()
    
  • キューを使用してマルチプロセス間の通信を完了する
    import multiprocessing
    q = multiprocessing.Queue()  #     ,      n,            
    q.put(111)  
    #   put          ,          ,     ,put         ,      
    
    q.put_nowait(111)  #   put_nowait put  ,       ,put_nowait             
    q.get()  #       ,       
    q.get_nowait()
    q.empty()  #   bull ,        
    q.full()  #     empty
    
  • .
  • In [28]: import multiprocessing
      
    In [29]: import time
    
    In [30]: def recv_data(q, data):
        ...:     if not q.full():
        ...:         print("    ,    ")
        ...:         q.put(data)
        ...:     else:
        ...:         print("    !")
        ...:         
    
    In [31]: def get_data(q):
        ...:     if q.empty():
        ...:         print("    !")
        ...:     else:
        ...:         print("         :%s" % q.get())
        ...:         
    
    In [38]: def main():
        ...:     q = multiprocessing.Queue(5)  #     ,      1   2  
        ...:     p1 = multiprocessing.Process(target=recv_data, args=(q, 'data1'))  #   1
        ...:     p2 = multiprocessing.Process(target=recv_data, args=(q, 'data2'))  #   2
        ...:     p3 = multiprocessing.Process(target=recv_data, args=(q, 'data3'))  #   3
        ...:     p4 = multiprocessing.Process(target=get_data, args=(q,))  #   42
        ...:     p1.start()
        ...:     time.sleep(1)
        ...:     p2.start()
        ...:     time.sleep(1)
        ...:     p3.start()
        ...:     time.sleep(1)
        ...:     p4.start()
        ...: 
    
    In [39]: main()
        ,    
        ,    
        ,    
             :data1    
    
  • 5、プロセスプールでマルチタスクを実現する
  • 手動でプロセスを作成する方法を使用すると、より多くのプロセスが作成されると、システムの大量のリソース(プロセスの作成と破棄によってシステムリソースが消費される)
  • が消費されます.
  • プロセスプール:一度に複数のプロセス代替を直接作成し、各プロセスが自分のタスクを処理した後、すぐに破棄されることはなく、次のタスクの実行を待つことになります.メインプロセスがプロセスプールを閉じることを決定しない限り、プロセスの作成と破棄に消費されるリソースを削減します.例を挙げると、100のタスクが完了する必要があります.手動でプロセスを作成して実行する場合は、100個のプロセスを作成する必要がありますが、プロセスプールを使用すると、10個のプロセスが十分である可能性があります.この100個のタスクは、長さ10のキューで、プロセスプールに入って
  • を実行するのを順番に待っています.
  • プロセスプールを初期化すると、最大プロセス数を指定できます.新しいリクエストがプロセスプールにコミットされたとき、プロセスプールがまだいっぱいでない場合、リクエストを実行するために新しいプロセスが作成されます.プロセスプール内のプロセス数が最大値に達すると、プロセスが終了するまで待機し、先ほど終了したプロセスを使用して新しいリクエスト
  • を実行します.
  • pythonでプロセスプールを使用する方法
  • from multiprocessing import Pool
  • p = Pool(3)はプロセスプールオブジェクトを返します.ここのプロセスプールには3つのプロセス代替
  • があります.
  • p.apply(func, args=(), kwds={}, callback=None, error_callback=None)
  • バインド関数、argsおよびkwdsは、バインドされた関数に渡す位置パラメータおよびキーワードパラメータ
  • である.
  • p.close()プロセスプールを閉じ、閉じた後に新しい要求
  • を受け入れない.
  • p.join()は、すべてのサブプロセスの完了を待つ.メインプロセスをブロックする役割を果たし、p.close()の後ろに
  • を置く必要がある.
  • プロセスプール内のプロセス間の通信
  • q = multiprocessing.Manager().Queue()
  • multiprocessing.Queue()
  • に類似する.
  • q.get()およびq.put()は、multiprocessing.Queue().get()およびmultiprocessing.Queue().put()
  • に類似する.