发球和重新加入管道

时间:2018-07-31 03:33:27

标签: python coroutine

我正在使用协同例程,通常将它们描述为对管道有用。我发现伯克利(Berkeley)的一个演讲非常有帮助(http://wla.berkeley.edu/~cs61a/fa11/lectures/streams.html#coroutines),但是我遇到了麻烦。在该演讲中,有一个图,其中有一个管道分叉,然后在以后重新组合。如果顺序无关紧要,则重组很容易,使用者有一个产量,但是有两个生产者正在向其发送()。但是,如果订单很重要怎么办?如果我要严格轮换(从左叉获取值,从右叉获取值,起泡,冲洗,重复)怎么办?这可能吗?

私人重组:

def producer1(ncr):
   while True:
       ncr.send(0)
def producer2(ncr):
   while True:
       ncr.send(1)
def combine():
    while True:
        s=(yield)
        print(s)
chain = combine()
chain.__next__()
producer1(chain)
producer2(chain)

我得到的输出为0 1 0 1等,但是我很确定这是调度的副作用。有没有办法保证排序,例如yield-from-1,yield-from-2?

要清楚,我知道yield from__await__,但我还不了解它们。

2 个答案:

答案 0 :(得分:1)

如果您通过管道“拉”而不是“推”,这并不困难:

for k = 1, 2, ..T:
    for t = 0, k, 2k,...T:
        for i = 0, 1,...k - 1:
            Apply the model to s_t+1 to obtain action a'_t+1
            Use the action a'_t+1 to update the next state s_t+i+1
        for i = 0, 1,...,k-1:
            Use the loss between prediction a'_t+1 and ground truth action a_t+1
            to update the recurrent network model using stochastic gradient descent

应该可靠地产生1和0交替出现

您还可以让最终使用者(在这种情况下,与每个值打印一起工作的东西)作为接收者工作,而无需引用 制片人,如果您真的想要:

def producer1():
    while True:
        yield 0


def producer2():
    while True:
        yield 1


def combine(*producers):
    while True:
        for producer in producers:
            val = next(producer)
            print(s)


combine(producer1(), producer2())

答案 1 :(得分:0)

我想知道了怎么做。无论如何,它都适用于琐碎的管道。这是我的联合收割机:

class combiner():
    def __init__(self,n,ncr):
        self.q = [ deque() for i in range(n)]
        self.n = n
        self.x = 0
        self.ncr = ncr

    @coroutine
    def receiver(self,n):
        while True:
            s=(yield)
            self.q[n].append(s)
            self.sender()

    def sender(self):
        while True:
            if self.q[self.x]:
                self.ncr.send(self.q[self.x].popleft())
                self.x = (self.x + 1) % self.n
            else:
                break

这将在n个流之间循环。基本上,combiner.receiver()是一个协程,它从流中获取数据并将其放入队列。每个流都有一个唯一的队列。 Combiner.sender会清除尽可能多的队列,然后返回。

我有点担心从生成器中调用一个函数然后进行发送可能是 bad ,但是我只是将发送器滚动到接收器中,这个问题就消失了。...< / p>