7

私はPythonで科学計算ツールを開発しています。これは、NUMA共有メモリ環境の複数のコアに作業を分散できるはずです。私はこれを行う最も効率的な方法を検討しています。

スレッドは-残念ながら-Pythonのグローバルインタープリターロックのためにゲームから外れています。これは私の唯一の選択肢としてフォークを残します。プロセス間通信の場合、オプションはパイプ、ソケット、またはmmapだと思います。このリストに不足しているものがある場合は、それを指摘してください。

私のアプリケーションでは、プロセス間のかなりの通信と、ある程度の共通データへのアクセスが必要になります。私の主な関心事はレイテンシーです。

私の質問:プロセスをフォークすると、そのメモリは割り当てられているコアの近くに配置されますか?書き込み時の*nixコピーのフォークとして、最初はこれが当てはまらないと思います。メモリアクセスを高速化するためにコピーを強制しますか?その場合、それを行うための最良の方法は何ですか?通信にmmapを使用する場合、そのメモリは引き続きコアに分散できますか、それとも単一のコアに配置されますか?アクセスを最適化するためにデータを透過的に再配置するプロセスはありますか?物理的な割り当てを直接制御する方法、または最適化を支援するために割り当てに関する情報を要求する方法はありますか?

より高いレベルでは、これらのうちどれが私のハードウェアによって決定され、どれがオペレーティングシステムによって決定されますか?私はハイエンドのマルチソケットマシンを購入している最中であり、AMDOpteronとIntelXeonの間で疑問を抱いています。上記の質問のいずれかに対する特定のハードウェアの影響は何ですか?

4

2 に答える 2

4

Pythonのアキレス腱の1つはGILであるため、より優れたマルチプロセスサポートがあります。たとえば、キュ​​ー、パイプ、ロック、共有値、共有配列があります。マネージャーと呼ばれるものもあります。これを使用すると、多くのPythonデータ構造をラップして、IPCに適した方法で共有できます。これらのほとんどはパイプやソケットを介して機能すると思いますが、内部についてはあまり深く掘り下げていません。

http://docs.python.org/2/library/multiprocessing.html

LinuxはNUMAシステムをどのようにモデル化しますか?

カーネルは、マルチコアマシンで実行されていることを検出してから、ハードウェアの数とトポロジを検出します。次に、ノードのアイデアを使用して、このトポロジのモデルを作成します。ノードは、CPU(おそらく複数のコアを備えた)とそれに接続されたメモリを含む物理ソケットです。コアベースではなくノードベースなのはなぜですか?メモリバスはRAMをCPUソケットに接続する物理的なワイヤであるため、単一のソケット内のCPU上のすべてのコアは、そのメモリバス上にあるすべてのRAMへのアクセス時間が同じになります。

あるメモリバス上のメモリは、別のメモリバス上のコアによってどのようにアクセスされますか?

x86システムでは、これはキャッシュを介して行われます。最新のOSは、トランスレーションルックアサイドバッファー(TLB)と呼ばれるハードウェアを使用して、仮想アドレスを物理アドレスにマップします。キャッシュが取得するようにタスクされているメモリがローカルの場合、ローカルで読み取られます。ローカルでない場合は、AMDシステムのHyperTransportバスまたはIntelのQuickPathを経由してリモートメモリに到達します。キャッシュレベルで行われるため、理論的にはそれについて知る必要はありません。そして、あなたは確かにそれを制御することはできません。ただし、高性能アプリケーションの場合、リモートアクセスの量を最小限に抑えることを理解しておくと非常に役立ちます。

OSは実際に仮想メモリの物理ページをどこに配置しますか?

プロセスがフォークされると、その親のページがすべて継承されます(COWのため)。カーネルは、どのノードが「優先」ノードであるプロセスに「最適」であるかを認識しています。これは変更できますが、デフォルトで親と同じになります。明示的に変更されない限り、メモリ割り当てはデフォルトで親と同じノードになります。

メモリを移動する透過的なプロセスはありますか?

いいえ。メモリが割り当てられると、割り当てられたノードに固定されます。別のノードで新しい割り当てを行い、データを移動し、最初のノードで割り当てを解除することができますが、それは少し面倒です。

割り当てを制御する方法はありますか?

デフォルトでは、ローカルノードに割り当てられます。libnumaを使用する場合は、デフォルトでローカルにする代わりに、割り当ての実行方法(ラウンドロビンやインターリーブなど)を変更できます。

私はこのブログ投稿から多くの情報を取りました:

http://blog.jcole.us/2010/09/28/mysql-swap-insanity-and-the-numa-architecture/

追加情報を収集するために、全体を読むことを強くお勧めします。

于 2012-12-23T01:45:16.263 に答える
-2
##client.py
import socket
import sys

HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])



sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:

    sock.connect((HOST, PORT))
    sock.sendall(bytes(data +"\n", "utf-8"))

    received = str(sock.recv(1024), "utf-8")
finally:
    sock.close()

print("Sent:     {}".format(data))
print("Received: {}".format(received))

##server.py
import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):

    def handle(self):

        self.data = self.request.recv(1024).strip()
        print("{} wrote:".format(self.client_address[0]))
        print(self.data)
        self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "10.0.0.1", 9999
    server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()
于 2015-03-24T15:48:25.660 に答える