Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何加快多处理队列的同时读写?_Python_Queue_Multiprocessing - Fatal编程技术网

Python 如何加快多处理队列的同时读写?

Python 如何加快多处理队列的同时读写?,python,queue,multiprocessing,Python,Queue,Multiprocessing,tl;dr-有没有办法提高同时读取和写入多处理队列的速度 我有一个处理审计数据的应用程序。将其视为系统日志中继。它接收数据,解析数据,然后向前发送事件。事件发生率可能非常高——我每秒要拍摄15000个事件(EPS) in_queue=multiprocessing.queue() out\u queue=multiprocessing.queue() ReaderProc-单个进程,套接字读取器,使用in\u queue.put()接收数据并将其放入in\u queue ParserProcs

tl;dr-有没有办法提高同时读取和写入多处理队列的速度

我有一个处理审计数据的应用程序。将其视为系统日志中继。它接收数据,解析数据,然后向前发送事件。事件发生率可能非常高——我每秒要拍摄15000个事件(EPS)

in_queue=multiprocessing.queue()

out\u queue=multiprocessing.queue()

  • ReaderProc-单个进程,套接字读取器,使用
    in\u queue.put()接收数据并将其放入
    in\u queue
  • ParserProcs-多个进程,使用
    in_queue.get()
    获取数据,处理数据,然后使用
    out_queue.put()将完成的结果放入
    out_queue
  • WriterProc-单进程,使用
    out\u queue.get()
    读取
    out\u queue
    ,并通过TCP套接字连接向前发送数据
我使用队列运行测试——我可以以25000 EPS的速度将事件放入或拉入队列。当多个解析进程(4)在数据写入队列时从队列中拉出数据时,就会出现减速。利率下降到每股收益低于10000英镑。我猜底层的管道、锁等是造成延迟的原因


我在管道上读到,它看起来只支持两个端点。我需要将CPU密集型解析分给多个进程。诸如多处理内存共享之类的替代方法能否获得更好的结果?如何更好地从队列中同时执行
.put()
.get()
操作?

考虑到您的性能需求,我认为您最好使用像或这样的第三方消息代理。我发现了一个比较multi的基准(尽管它与您的用例不太匹配)。性能上的差异是巨大的:

multiprocesing.Queue结果

1
2
3

python2 ./multiproc_with_queue.py
Duration: 164.182257891
Messages Per Second: 60907.9210414
1
2
3

python2 ./multiproc_with_zeromq.py
Duration: 23.3490710258
Messages Per Second: 428282.563744
0mq结果

1
2
3

python2 ./multiproc_with_queue.py
Duration: 164.182257891
Messages Per Second: 60907.9210414
1
2
3

python2 ./multiproc_with_zeromq.py
Duration: 23.3490710258
Messages Per Second: 428282.563744
我进行了这两个测试,并提供了一个更复杂的工作负载,因为
多处理.Queue
的好处之一是它可以为您处理序列化。以下是新脚本:

mult_queue.py

import sys
import time
from  multiprocessing import Process, Queue

def worker(q):
    for task_nbr in range(1000000):
        message = q.get()
    sys.exit(1)

def main():
    send_q = Queue()
    Process(target=worker, args=(send_q,)).start()
    msg = {
            'something': "More",
            "another": "thing",
            "what?": range(200),
            "ok": ['asdf', 'asdf', 'asdf']
            }
    for num in range(1000000):
        send_q.put(msg)

if __name__ == "__main__":
    start_time = time.time()
    main()
    end_time = time.time()
    duration = end_time - start_time
    msg_per_sec = 1000000 / duration

    print "Duration: %s" % duration
    print "Messages Per Second: %s" % msg_per_sec
多_zmq.py

import sys
import zmq
from  multiprocessing import Process
import time
import json
import cPickle as pickle

def worker():
    context = zmq.Context()
    work_receiver = context.socket(zmq.PULL)
    work_receiver.connect("tcp://127.0.0.1:5557")

    for task_nbr in range(1000000):
        message = work_receiver.recv_pyobj()

    sys.exit(1)

def main():
    Process(target=worker, args=()).start()
    context = zmq.Context()
    ventilator_send = context.socket(zmq.PUSH)
    ventilator_send.bind("tcp://127.0.0.1:5557")
    msg = {
            'something': "More",
            "another": "thing",
            "what?": range(200),
            "ok": ['asdf', 'asdf', 'asdf']
            }
    for num in range(1000000):
        ventilator_send.send_pyobj(msg)

if __name__ == "__main__":
    start_time = time.time()
    main()
    end_time = time.time()
    duration = end_time - start_time
    msg_per_sec = 1000000 / duration

    print "Duration: %s" % duration
    print "Messages Per Second: %s" % msg_per_sec
输出:

dan@dan:~$ ./mult_zmq.py 
Duration: 14.0204648972
Messages Per Second: 71324.3110935
dan@dan:~$ ./mult_queue.py 
Duration: 27.2135331631
Messages Per Second: 36746.4229657

我发现这个测试有点像序列化/酸洗。我会做更多的研究,谢谢你的回复!实际上我自己也试过了,zmq速度更快,不过你应该用你的消息负载试试,看看会发生什么。我将编辑我的答案。非常令人印象深刻的结果。前两个测试使用了您的精确代码。最后两个使用我的长字符串作为消息。使用zeromq,字符串似乎可以非常快速地序列化/pickle。queue_speed.py持续时间:31.4633660316条消息/秒:31782.9948326 queue_speed_zmq.py持续时间:41.1004679203条消息/秒:24330.6232411 queue_speed_long_string.py持续时间:28.4459819794条消息/秒:35154.3497681 queue_speed_zmq_long_string.py持续时间:14.816603899条消息/秒:67491.8494695更多结果,这一次使用我的out_队列,这是一个dict.zmq较慢。queue_speed_zmq_outqueue.py持续时间:65.6619861126消息/秒:15229.5119171 queue_speed_outqueue.py持续时间:43.4732539654消息/秒:23002.6489574