【问题标题】:Estimate Python to Python IPC latency估计 Python 到 Python IPC 的延迟
【发布时间】:2019-09-21 09:08:11
【问题描述】:

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

由于显示和串行输出需要精确同步,我试图弄清楚 Python 中的进程间通信有多快(例如,使用 multiprocessing.Pipe)。但是我遇到了一个问题,试图针对给定的硬件配置进行基准测试。

如果我使用time.time() 来估计 IPC 延迟,它似乎小于 1us,这对我来说似乎太快了。 另一方面,当我尝试使用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()一起运行:

Start master
Running in referred mode
Run main loop
Run p2 at 1569056480.1104207
Run p1 at 1569056480.1104207
Sending...
0.0000000
Sending...
0.0000000
Sending...
0.0000000

time.perf_counter()一起运行:

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

有没有人知道对延迟进行基准测试的明智方法,或者对我可以实际预期的延迟有任何经验吗?

【问题讨论】:

    标签: python synchronization multiprocessing ipc


    【解决方案1】:

    经过更多修改后,我发现,似乎可行的方法只是将消息退回到最初发送它的进程并使用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() 的文档,参考点应该是系统范围的,所以我仍然不知道为什么当我从两个单独的进程调用它时我的初始方法不起作用(也许有人对此有答案?)。但至少上述解决方案似乎可行,因为它使 Pipes 的 2 路通信延迟刚好低于 1ms,这似乎是合理的(i9-9820X@3.3GHz 基本速度):

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-06
      • 1970-01-01
      相关资源
      最近更新 更多