python - 估计 Python 到 Python IPC 的延迟
问题描述
对于 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
有谁知道对延迟进行基准测试的明智方法,或者对我可以实际期望的延迟有任何经验吗?
解决方案
经过一些修改后,我发现,似乎工作的只是将消息反弹回最初发送它的进程并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
推荐阅读
- regex - sed 正则表达式:组重复选项?
- c++ - C++ 可变数量的可变参数模板参数
- r - 按向量计算矩阵运算分组的有效策略
- vue.js - 如何使用 vuex 控制数组状态?
- php - RegEx:不包括特定数字的数字范围
- python - 如何在对输入数据进行归一化后对神经网络预测进行反规范化?
- node.js - Cost, Performance and pitfall of Invalidating JWT
- typescript - 从枚举值查找中返回枚举
- web - 是否有可能查看最后一次请求是何时发送到 IIS 网站中的特定文件夹
- javascript - JS .show .hide 方向