估计Python到Python的IPC延迟

估计Python到Python的IPC延迟,python,synchronization,multiprocessing,ipc,Python,Synchronization,Multiprocessing,Ipc,对于Python应用程序,我需要同时处理OpenGL显示输出和串行输出(例如到Arduino)。然而,理想情况下,我希望在不同的进程中运行不同类型的输出 由于显示和串行输出需要精确同步,因此我试图弄清楚Python中进程间通信的速度(例如,使用多处理.Pipe)。但我在尝试为给定的硬件配置进行基准测试时遇到了一个问题 如果我使用time.time()来估计IPC延迟,它似乎小于1U,对我来说,这似乎太快了。 另一方面,当我尝试使用time.perf_counter()时,我总是得到负延迟,这甚至

对于Python应用程序,我需要同时处理OpenGL显示输出和串行输出(例如到Arduino)。然而,理想情况下,我希望在不同的进程中运行不同类型的输出

由于显示和串行输出需要精确同步,因此我试图弄清楚Python中进程间通信的速度(例如,使用
多处理.Pipe
)。但我在尝试为给定的硬件配置进行基准测试时遇到了一个问题

如果我使用
time.time()
来估计IPC延迟,它似乎小于1U,对我来说,这似乎太快了。 另一方面,当我尝试使用
time.perf_counter()
时,我总是得到负延迟,这甚至更奇怪

以下是示例代码:

from multiprocessing import Pipe, Process, Event
import time

direct = False

timing_fun = time.time
#timing_fun = time.perf_counter

def p1(p1out, p2in, start):

    start.wait()
    print('Run p1 at %s' % str(timing_fun()))
    while True:
        print('Sending...')
        if not(direct):
            p1out.send(timing_fun())
        else:
            p2in.send(timing_fun())

        time.sleep(2.)

def p2(p2out, start):

    start.set()
    print('Run p2 at %s' % str(timing_fun()))
    while True:
        if p2out.poll():
            print('%.7f' % (timing_fun() - p2out.recv()))


def master():

    print('Start master')
    print('Running in %s mode' % ('direct' if direct else 'referred'))
    p1in, p1out = Pipe()
    p2in, p2out = Pipe()
    start = Event()

    process1 = Process(target=p1, args=(p1out, p2in, start))
    process1.start()

    process2 = Process(target=p2, args=(p2out, start))
    process2.start()


    print('Run main loop')
    while True:
        if p1in.poll():
            p2in.send(p1in.recv())


if __name__ == '__main__':

    master()
使用
time.time()运行

使用
时间运行。性能计数器()


是否有人知道一种合理的方法来基准测试延迟,或者有任何经验表明我可以实际期望什么样的延迟

经过进一步的修补后,我发现似乎有效的方法是将消息反弹回最初发送消息的进程,并使用
time.perf_counter()
计算差异:

from multiprocessing import Pipe, Process, Event
import time

timing_fun = time.perf_counter

def p1(p1out, p2in, start):

    start.wait()
    print('Run p1 at %s' % str(timing_fun()))
    while True:
        if p1out.poll(timeout=0.1):
            print('%.7f' % (timing_fun() - p1out.recv()))

        time.sleep(2.)

        print('Sending...')
        p2in.send(timing_fun())


def p2(p2out, p1in, start):

    start.set()
    print('Run p2 at %s' % str(timing_fun()))
    while True:
        if p2out.poll():
            msg = p2out.recv()
            p1in.send(msg)


def master():

    print('Start master')
    p1in, p1out = Pipe()
    p2in, p2out = Pipe()
    start = Event()

    process1 = Process(target=p1, args=(p1out, p2in, start))
    process1.start()

    process2 = Process(target=p2, args=(p2out, p1in, start))
    process2.start()

if __name__ == '__main__':

    master()

根据
time.perf_counter()
的文档,参考点应该是系统范围内的,所以我仍然不知道当我从两个单独的进程调用它时,为什么我的初始方法不起作用(也许有人知道答案?)。但至少上述解决方案似乎可行,因为它使管道的双向通信延迟略低于1ms,这似乎是合理的(i9)-9820X@3.3GHz基本速度):

Start master
Running in referred mode
Run main loop
Run p2 at 0.0628994
Run p1 at 0.0821299
Sending...
-0.0187006
Sending...
-0.0187737
Sending...
-0.0190505
Sending...
-0.0191084
from multiprocessing import Pipe, Process, Event
import time

timing_fun = time.perf_counter

def p1(p1out, p2in, start):

    start.wait()
    print('Run p1 at %s' % str(timing_fun()))
    while True:
        if p1out.poll(timeout=0.1):
            print('%.7f' % (timing_fun() - p1out.recv()))

        time.sleep(2.)

        print('Sending...')
        p2in.send(timing_fun())


def p2(p2out, p1in, start):

    start.set()
    print('Run p2 at %s' % str(timing_fun()))
    while True:
        if p2out.poll():
            msg = p2out.recv()
            p1in.send(msg)


def master():

    print('Start master')
    p1in, p1out = Pipe()
    p2in, p2out = Pipe()
    start = Event()

    process1 = Process(target=p1, args=(p1out, p2in, start))
    process1.start()

    process2 = Process(target=p2, args=(p2out, p1in, start))
    process2.start()

if __name__ == '__main__':

    master()

Start master
Run p2 at 0.0653889
Run p1 at 0.0928306
Sending...
0.0004457
Sending...
0.0003819
Sending...
0.0006137
Sending...
0.0005876
Sending...
0.0005943