Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.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_Python 3.x_Python Multithreading - Fatal编程技术网

Python 具有多处理功能的特定标准输出行订单

Python 具有多处理功能的特定标准输出行订单,python,python-3.x,python-multithreading,Python,Python 3.x,Python Multithreading,我有以下问题: g数据生成器,每一个都是独立的过程,生成n值,我需要以循环(overg)的方式写出该值。因此,对于发电机A,B,C,输出的顺序必须如下所示: <value 1 of A> <value 1 of B> <value 1 of C> <value 2 of A> <value 2 of B> <value 2 of C> <value 3 of A> ... 在执行时,它占用了我所有的4个CPU内

我有以下问题:

g
数据生成器,每一个都是独立的
过程
,生成
n
值,我需要以循环(over
g
)的方式写出该值。因此,对于发电机
A
B
C
,输出的顺序必须如下所示:

<value 1 of A>
<value 1 of B>
<value 1 of C>
<value 2 of A>
<value 2 of B>
<value 2 of C>
<value 3 of A>
...
在执行时,它占用了我所有的4个CPU内核,但在性能方面,它比顺序执行慢:

总值10000000的单线程执行时间:

$ time python3 threading_output.py --threads 1 --count 10000000 | wc -l
10000000

real    0m16.557s
user    0m16.443s
sys     0m0.437s
…对于
多处理
实现也是如此:

$ time python3 threading_output.py --threads 4 --count 10000000 | wc -l
10000000

real    1m6.446s
user    3m10.073s
sys     0m54.274s
如果不使用
mp.Queue
并在
product
循环中直接打印生成的值,我将获得约9.6秒的时间,但当然,输出行的顺序不确定

我怎样才能加快速度

更新#1 使用
mp.Array
不是共享缓冲区的选项,因为我需要对字符串数组使用ctype
c\u wchar\u p
,而根据上下文,这是完全行不通的

更新#2 将
mp.Queue(1000)
替换为
mp.Pipe(False)
,这将1000万个值的时间缩短到45秒左右。生产者进程现在不再占用CPU,消费者是明显的瓶颈:

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 5943 ancoron   20   0   28420  15168   8348 R  99.9   0.0   0:12.23 `- python3 threading_output.py --threads 4 --count 10000000
 5947 ancoron   20   0   28284  10336   3536 R  29.9   0.0   0:03.69     `- python3 threading_output.py --threads 4 --count 10000000
 5948 ancoron   20   0   28284  10336   3536 R  30.8   0.0   0:03.71     `- python3 threading_output.py --threads 4 --count 10000000
 5949 ancoron   20   0   28284  10336   3536 R  30.8   0.0   0:03.71     `- python3 threading_output.py --threads 4 --count 10000000
 5950 ancoron   20   0   28284  10340   3536 R  29.0   0.0   0:03.58     `- python3 threading_output.py --threads 4 --count 10000000
更新#3
我尝试了,使用了一个简单的
字节队列
,将其缩短到23秒。仍然比单线程慢。

好的,所以我做了一些测试,现在我很困惑。我既做了多线程解决方案,也做了异步解决方案,但都没有做得特别好。我还复制并粘贴了你的代码,它总是挂起,即使“完成”了

需要注意的是,在我的代码中,我使用了作为TID的数字,而不是4个随机的十六进制数字,因为我想确保它做的是你想要的。用另一种方法很难分辨,而且很容易改成十六进制

单螺纹:

import random
import sys

def generate():
    return random.randrange(-10, 10)

if len(sys.argv) < 2:
    print("NEED ARGS")
    exit(0)

num = int(sys.argv[1])
for x in range(num):
    for _ in range(x):
        print("[{}]: {}".format(x, generate()))
随机导入
导入系统
def generate():
返回random.randrange(-10,10)
如果len(系统argv)<2:
打印(“需要参数”)
出口(0)
num=int(sys.argv[1])
对于范围内的x(num):
对于范围(x)内的uu:
打印(“[{}]:{}”。格式(x,generate())
多线程:

from concurrent.futures import TimeoutError
from pebble import ThreadPool, ProcessExpired
import random
import multiprocessing as mp
import sys 

def generate():
    return random.randrange(-10, 10) 

def produce(num):
    #tid = '%04x' % random.getrandbits(16)
    tid = num 
    i = 0 
    while i < num:
        print('[%s] %3d' % (tid, generate()))
        i += 1

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("NEED ARGS")
        exit(0)

    num = int(sys.argv[1])
    with ThreadPool(max_workers=mp.cpu_count()) as pool:
        future = pool.map(produce, range(num), timeout=3)
        iterator = future.result()
        while True:
            try:
                result = next(iterator)
            except StopIteration:
                break
            except TimeoutError as error:
                print(error)
                break
            except ProcessExpired as error:
                print(error)
                break
            except Exception as error:
                print(error)
                break
来自concurrent.futures导入TimeoutError
从pebble导入线程池,ProcessExpired
随机输入
将多处理作为mp导入
导入系统
def generate():
返回random.randrange(-10,10)
def产品(数量):
#tid='%04x'%random.getrandbits(16)
tid=num
i=0
而我
老实说,我没看到速度有什么大的变化。多处理的一个实际上是较慢的,这是基本的,因为它可以得到。我刚刚记得的是,它以计算速度著称。我真的不想设置它,但考虑到你的问题的简单、重复和纯粹的计算性质,我认为它可能是你的解决方案

基准是:

.3秒,重复100次

对于1000次迭代,单次为10秒,多次为11秒

我放弃了,因为它花了我很长时间。我不知道如何描述它,但每增加一个数量级,你所做的工作就会增加100倍。使用高斯模式的证明:

你要做的是把每个数的和加到num,这意味着1+2+。。。高斯的模式涵盖了这一点。这应该可以让我们大致了解它有多大:

10作为输入需要550次迭代

100作为输入,需要5050次迭代

1000作为输入需要500500次迭代

10000次输入需要50005000次迭代

通过excel输入数据后,结果是O(n^2),我想这还不错。如果你好奇的话,方程是~.55x^2

您是否介意将您制作的其他程序变体链接起来,以便我可以将它们与我自己的程序进行基准测试?因为老实说,我很想看看他们是否工作正常/我是否做错了什么

Tl;DR:为了便于比较,您使用了哪些测试/代码?你试过派比吗?与打印数字相比,数据库还可以吗(几乎可以肯定会更快)?您是如何让程序单线程运行得如此之快的?

希望这有帮助

编辑:只是为了检查,您确实想执行以下操作,对吗?在第一次迭代中,您打印一次ID和一个随机数。在第二次迭代中,将ID和随机数打印两次。我只是想看看

编辑2:代码应该是固定的

from concurrent.futures import TimeoutError
from pebble import ThreadPool, ProcessExpired
import random
import multiprocessing as mp
import sys

def generate():
    return random.randrange(-10, 10)

def produce(num):
    tid = '%04x' % random.getrandbits(16)
    for _ in range(num):
        print('[%s] %3d' % (tid, generate()))

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("NEED ARGS")
        exit(0)

    num = int(sys.argv[1])
    workers = int(sys.argv[2])
    num_per_worker = int(num/workers)

    #The magic numbers here are just optimizations. Feel free to change them
    with ThreadPool(max_workers=workers, max_tasks=50) as pool:
        future = pool.map(produce, (num_per_worker for _ in range(workers)),
                          chunksize=round(num/1024))
        iterator = future.result()
        while True:
            try:
                result = next(iterator)
            except StopIteration:
                break
来自concurrent.futures导入TimeoutError
从pebble导入线程池,ProcessExpired
随机输入
将多处理作为mp导入
导入系统
def generate():
返回random.randrange(-10,10)
def产品(数量):
tid='%04x'%random.getrandbits(16)
对于范围内的u(num):
打印(“[%s]%3d%”(tid,generate())
如果名称=“\uuuuu main\uuuuuuuu”:
如果len(sys.argv)<3:
打印(“需要参数”)
出口(0)
num=int(sys.argv[1])
workers=int(sys.argv[2])
num_per_worker=int(num/workers)
#这里的神奇数字只是优化。请随意更改它们
线程池(最大工作线程数=工作线程数,最大任务数=50)作为线程池:
from pebble import ThreadPool, ProcessExpired
import random
import multiprocessing as mp
import sys 
from functools import partial

def generate():
    return random.randrange(-10, 10) 

def produce(num, magic_array):
    tid = '%04x' % random.getrandbits(16)
    for _ in range(num):
        magic_array.append('[%s] %3d' % (tid, generate()))

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("NEED ARGS")
        exit(0)

    num = int(sys.argv[1])
    workers = int(sys.argv[2])
    num_per_worker = int(num/workers)
    magic_array = []

    #This is the how the magic array is used as an argument.
    #There's probably a better way to do it, but I don't know it
    part_produce = partial(produce, magic_array=magic_array)
    #The magic numbers here are just optimizations. Feel free to change them
    with ThreadPool(max_workers=workers, max_tasks=50) as pool:
        future = pool.map(part_produce, (num_per_worker for _ in range(workers)), chunksize=num_per_worker)
        iterator = future.result()
        while True:
            try:
                result = next(iterator)
            except StopIteration:
                break

    #This is the important part. For every iteration/worker unit, it will go
    #through the list in steps of iteration/worker units, with a start offset
    #of x
    #Just printing takes about 5 seconds, but I don't think there's a faster
    #method because printing takes a long time anyway
    for x in range(num_per_worker):
        for y in magic_array[x::num_per_worker]:
            print(y)

$ time python3 threading_output.py --threads 1 --count 10000000 | wc -l
10000000

real    0m15.915s
user    0m16.045s
sys     0m0.629s
$ time python3 threading_output.py --threads 4 --count 10000000 | wc -l
10000000

real    0m30.005s
user    0m53.543s
sys     0m28.072s
$ time python3 threading_output.py --threads 4 --count 10000000 --output-file test.txt

real    0m6.637s
user    0m18.688s
sys     0m1.265s