![](/img/trans.png)
[英]Is it possible to spawn Java code from Python, and communicate between the two processes?
[英]Spawn processes and communicate between processes in a trio based Python application
對於 Python 庫flowimage的實習,我們正在研究使用庫trio編寫具有客戶端/服務器模型的 HPC 並行應用程序是否是一個好主意。
對於異步編程和 i/o,trio 確實很棒!
然后,我想知道如何
我沒有在文檔中找到使用 trio 執行此操作的推薦方法(即使echo 客戶端/服務器教程是一個好的開始)。
在 Python 中生成進程並進行通信的一種明顯方法是使用multiprocessing 。
在 HPC 環境中,我認為一個好的解決方案是使用 MPI ( http://mpi4py.readthedocs.io/en/stable/overview.html#dynamic-process-management )。 作為參考,我還必須提到rpyc ( https://rpyc.readthedocs.io/en/latest/docs/zerodeploy.html#zerodeploy )。
我不知道是否可以將這些工具與 trio 一起使用,以及這樣做的正確方法是什么。
在我看來, PEP 574 (參見https://pypi.org/project/pickle5/ )也可以成為解決這個問題的好方法的一部分。
截至 2018 年年中,Trio 還沒有這樣做。 迄今為止,您最好的選擇是使用trio_asyncio
來利用 asyncio 對 Trio 仍需要學習的功能的支持。
我發布了一個使用 multiprocessing 和 trio(在主程序和服務器中)的非常簡單的代碼示例。 它似乎工作。
from multiprocessing import Process, Queue
import trio
import numpy as np
async def sleep():
print("enter sleep")
await trio.sleep(0.2)
print("end sleep")
def cpu_bounded_task(input_data):
result = input_data.copy()
for i in range(1000000-1):
result += input_data
return result
def server(q_c2s, q_s2c):
async def main_server():
# get the data to be processed
input_data = await trio.run_sync_in_worker_thread(q_c2s.get)
print("in server: input_data received", input_data)
# a CPU-bounded task
result = cpu_bounded_task(input_data)
print("in server: sending back the answer", result)
await trio.run_sync_in_worker_thread(q_s2c.put, result)
trio.run(main_server)
async def client(q_c2s, q_s2c):
input_data = np.arange(10)
print("in client: sending the input_data", input_data)
await trio.run_sync_in_worker_thread(q_c2s.put, input_data)
result = await trio.run_sync_in_worker_thread(q_s2c.get)
print("in client: result received", result)
async def parent(q_c2s, q_s2c):
async with trio.open_nursery() as nursery:
nursery.start_soon(sleep)
nursery.start_soon(client, q_c2s, q_s2c)
nursery.start_soon(sleep)
def main():
q_c2s = Queue()
q_s2c = Queue()
p = Process(target=server, args=(q_c2s, q_s2c))
p.start()
trio.run(parent, q_c2s, q_s2c)
p.join()
if __name__ == '__main__':
main()
一個簡單的 mpi4py 示例......從三重奏的角度來看,這可能是一個糟糕的工作,但它似乎有效。
通信是通過trio.run_sync_in_worker_thread
完成的,所以( 如 Nathaniel J. Smith 所寫)(1)沒有取消(並且沒有 control-C 支持)和(2)使用比 trio 任務更多的內存(但是一個 Python 線程並沒有使用那么多記憶)。
但是對於涉及大型 numpy 數組的通信,我會這樣做,因為使用 mpi4py 進行類似緩沖區的對象的通信將非常有效。
import sys
from functools import partial
import trio
import numpy as np
from mpi4py import MPI
async def sleep():
print("enter sleep")
await trio.sleep(0.2)
print("end sleep")
def cpu_bounded_task(input_data):
print("cpu_bounded_task starting")
result = input_data.copy()
for i in range(1000000-1):
result += input_data
print("cpu_bounded_task finished ")
return result
if "server" not in sys.argv:
comm = MPI.COMM_WORLD.Spawn(sys.executable,
args=['trio_spawn_comm_mpi.py', 'server'])
async def client():
input_data = np.arange(4)
print("in client: sending the input_data", input_data)
send = partial(comm.send, dest=0, tag=0)
await trio.run_sync_in_worker_thread(send, input_data)
print("in client: recv")
recv = partial(comm.recv, tag=1)
result = await trio.run_sync_in_worker_thread(recv)
print("in client: result received", result)
async def parent():
async with trio.open_nursery() as nursery:
nursery.start_soon(sleep)
nursery.start_soon(client)
nursery.start_soon(sleep)
trio.run(parent)
print("in client, end")
comm.barrier()
else:
comm = MPI.Comm.Get_parent()
async def main_server():
# get the data to be processed
recv = partial(comm.recv, tag=0)
input_data = await trio.run_sync_in_worker_thread(recv)
print("in server: input_data received", input_data)
# a CPU-bounded task
result = cpu_bounded_task(input_data)
print("in server: sending back the answer", result)
send = partial(comm.send, dest=0, tag=1)
await trio.run_sync_in_worker_thread(send, result)
trio.run(main_server)
comm.barrier()
您還可以查看tractor
,它似乎終於發布了第一個 alpha 版本。
它具有使用 TCP 和msgpack
內置功能聚焦式 RPC 系統(很像trio
)(但我認為他們計划了更多的傳輸)。 您只需直接調用其他進程中的函數,然后以各種不同的方式將結果流/返回。
這是他們的第一個例子:
"""
Run with a process monitor from a terminal using::
$TERM -e watch -n 0.1 "pstree -a $$" \
& python examples/parallelism/single_func.py \
&& kill $!
"""
import os
import tractor
import trio
async def burn_cpu():
pid = os.getpid()
# burn a core @ ~ 50kHz
for _ in range(50000):
await trio.sleep(1/50000/50)
return os.getpid()
async def main():
async with tractor.open_nursery() as n:
portal = await n.run_in_actor(burn_cpu)
# burn rubber in the parent too
await burn_cpu()
# wait on result from target function
pid = await portal.result()
# end of nursery block
print(f"Collected subproc {pid}")
if __name__ == '__main__':
trio.run(main)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.