光纤(协同多线程) [英] fiber(cooperative multi-threading)

查看:94
本文介绍了光纤(协同多线程)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



大家好。


我发现合作多线程(一次只运行一个线程,

显式线程切换)对于编写一些模拟器非常有用。

有了它,我就可以摆脱烦人的互斥,并且确定

结果确定性。


出于这个目的,并且受Ruby(1.9)光纤的启发,我用Python编写了我自己的

版光纤。


它只是工作,但使用本机Python线程非抢占

线程是不划算的。 Python有生成器,但它对于通用脚本来说似乎非常有限。我希望我能够至少轻松地写入嵌套(生成器)函数。


是否有任何在Python中实现真实(轻量级)光纤的计划? />

---------------------------------------- --------------------

导入线程


类光纤(threading.Thread):

def __init __(自我):

threading.Thread .__ init __(self)


self.semaphore_running = threading.Semaphore( 0)

self.semaphore_finish =无

self.val =无


self.setDaemon(True)

self.start()

self.start = self.start_fiber


def start_fiber(个体经营):

self.semaphore_finish = threading.Semaphore(0)

self.semaphore_running.release()

self.semaphore_finish.acquire()


def run(self):#over

self.semaphore_running.acquire()

self.main()

if self.semaphore_finish不是没有:

self.sema phore_finish.release()


def switchto(self,fiber,val = None):

fiber.val = val

fiber.semaphore_running.release()

self.semaphore_running.acquire()

返回self.val

def main(self ):#应该被覆盖

通过


类F1(光纤):

def main(self):

print" f1 start"

self.switchto(f2)

print" f1 foo"

v = self。 switchto(f2)

print" f1 v =%s world" %v

self.switchto(f2,OK)

print" f1 end"


class F2( Fiber):

def main(self):

print" f2 start"

self.switchto(f1)

print" f2 bar"

result = self.switchto(f1," Hello,")

print" f2 result =%s" %result

打印" f2 end"

self.switchto(f1)


f1 = F1()

f2 = F2()


打印"开始"

f1.start()

打印" ;结束


- kayama

解决方案

12月22日,12:10 * pm,Akihiro KAYAMA< kay ... @ st.rim.or.jpwrote:


大家好。


我发现合作社多线程(一次只运行一个线程,

显式线程切换)对于编写一些模拟器很有用。

有了它,我就可以从令人讨厌的互斥,并使得
结果确定无疑。


为此目的,并且受Ruby(1.9)光纤的启发,我自己写了
Python中的
光纤版本。


它只是有效,但使用本机Python线程进行非抢占式的b $ b线程不符合成本效益。 Python有生成器,但它对于通用脚本来说似乎非常有限。我希望我能够至少轻松地写入嵌套(生成器)函数。


是否有任何在Python中实现真实(轻量级)光纤的计划? />

---------------------------------------- --------------------

导入线程


类光纤(threading.Thread):

* * def __init __(自我):

* * * * threading.Thread .__ init __(self)


* * * * self.semaphore_running = threading.Sephphore(0)

* * * * self.semaphore_finish =无

* * * * self.val =无


* * * * self.setDaemon(True)

* * * * self.start()

* * * * self.start = self.start_fiber


* * def start_fiber(self):

* * * * self.semaphore_finish = threading.Semaphore(0)

* * * * self.semaphore_running.release()

* * * * self.semaphore_finish.acquire()


* * def run (个体经营):* * * * * * * #over

* * * * self.semaphore_runni ng.acquire()

* * * * self.main()

* * * *如果self.semaphore_finish不是None:

* * * * * * self.semaphore_finish.release()


* * def switchto(self,fiber,val = None):

* * * * fiber.val = val

* * * * fiber.semaphore_running.release()

* * * * self.semaphore_running.acquire()

* * * *返回self.val


* * def main(self):* * * * * *#应该被覆盖

* * * *通过


级F1(光纤):

* * def main(个体经营):

* * * *打印f1 start

* * * * self.switchto(f2)

* * * * print" f1 foo"

* * * * v = self.switchto(f2)

* * * * print" f1 v =%s world" %v

* * * * self.switchto(f2," OK")

* * * * print" f1 end"

>
F2级(光纤):

* * def main(个体经营):

* * * * print" f2 start"

* * * * self.switchto(f1)

* * * * print" f2 bar"

* * * * result = self.switchto(f1 ,你好,)

* * * * print" f2 result =%s" %result

* * * * print" f2 end"

* * * * self.switchto(f1)


f1 = F1()

f2 = F2()


print" start"

f1.start()

打印结束


- kayama



我对ruby并不熟悉但是这些纤维似乎是一些协同作用。从python 2.5开始,生成器可以发送值,

这可以用来实现你想要的。我有一个得到它的好处,这是我想出来的:请注意,对于特定的类或线程,不需要

。我只在您的

示例中对此进行了测试,但它提供了与您的代码相同的结果:)


---------- ---------------------------


#A''''''是一种发电机功能产生元组(光纤,值)

#或(光纤,)。 ''run''函数启动光纤,然后使用它产生的光纤进行
#。如果光纤也产生一个值,则

#这个值被发送到''next''光纤。


def run(光纤):

it,val = fiber(),[]

fibers = {fiber:it}

试试:

而真:

n = it.send(* val)if val else it.next()

co,val = n [0],n [1:]

it = fibers.get(co)

如果是无:

纤维[co] = it = co()

除了StopIteration:

返回val [0]如果其他没有


#现在两个''纤维''


def f1():

打印" f1 start"

收益f2,

打印" f1 foo" ;

v =收益率f2,

打印" f1 v =%s world" %v

收益率f2,确定

打印f1结束


def f2():

打印" f2 start"

收益f1,

打印" f2 bar"

result = yield f1, 你好,

print" f2 result =%s" %result

打印" f2 end"

收益率f1,


打印开始

run(f1)

print" end"


------------------- -------------------

HTH


-

Arnaud


Arnaud Delobelle< ar ***** @ googlemail.comwrote:


我对红宝石并不熟悉,但这些纤维似乎是一些协同作用的b
。从python 2.5开始,生成器可以发送值,

这可以用来实现你想要的。我有一个得到它的好处,这是我想出来的:请注意,对于特定的类或线程,不需要

。我只在您的

示例中对此进行了测试,但它给出了与您的代码相同的结果:)



我认为是微软谁发明了纤维一词作为

coroutine的同义词。请参阅 http://msdn2.microsoft.com/en-us /library/ms682661.aspx


不幸的是,生成器只保存一个级别的堆栈框架,所以它们

并不是真正的替代品纤维/协程。 OP应该看看Stackless Python或Greenlets。请参阅
http://codespeak.net/py/dist/greenlet .html


12月22日下午2:37 * pm,Duncan Booth< duncan.bo ... @ invalid.invalidwrote:


Arnaud Delobelle< arno ... @ googlemail.comwrote:


我不是很熟悉与红宝石,但这些纤维似乎是一些协同作用的b
。 *从python 2.5开始,生成器可以发送值,

这可以用来实现你想要的。 *我有一个得到它

的乐趣,这就是我想出的:请注意,对于特定的类或线程,不需要

。 *我仅在您的

示例中对此进行了测试,但它提供了与您的代码相同的结果:)



我认为这是Microsoft谁发明了纤维一词作为

coroutine的同义词。 Seehttp://msdn2.microsoft.com/en-us/library/ms682661.aspx



OK


不幸的是,生成器只保存一个级别的堆栈框架,所以它们

并不能真正替代光纤/协同程序。 OP应该看看Stackless Python或Greenlets。 Seehttp://codespeak.net/py/dist/greenlet.html



我建议的仍然提供一个合作多层次的水平
对于OP来说可能足够的线程。事实上,现在还不清楚是否可以通过运行无法实现的OP'的Fiber

类可以做到(明智地):) ()函数我建议。

这让我觉得有一些重要的东西我没有考虑到b $ b。如果它是指向我的话,我将不胜感激。


-

Arnaud



Hi all.

I found cooperative multi-threading(only one thread runs at once,
explicit thread switching) is useful for writing some simulators.
With it, I''m able to be free from annoying mutual exclusion, and make
results deterministic.

For this purpose, and inspired by Ruby(1.9) fiber, I wrote my own
version of fiber in Python.

It just works, but using native Python threads for non-preemptive
threading is not cost-effective. Python has generator instead but it
seemed to be very restricted for general scripting. I wish I could
write nested (generator) functions easily at least.

Is there any plan of implementing real (lightweight) fiber in Python?

------------------------------------------------------------
import threading

class Fiber(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)

self.semaphore_running = threading.Semaphore(0)
self.semaphore_finish = None
self.val = None

self.setDaemon(True)
self.start()
self.start = self.start_fiber

def start_fiber(self):
self.semaphore_finish = threading.Semaphore(0)
self.semaphore_running.release()
self.semaphore_finish.acquire()

def run(self): # override
self.semaphore_running.acquire()
self.main()
if self.semaphore_finish is not None:
self.semaphore_finish.release()

def switchto(self, fiber, val=None):
fiber.val = val
fiber.semaphore_running.release()
self.semaphore_running.acquire()
return self.val

def main(self): # should be overridden
pass

class F1(Fiber):
def main(self):
print "f1 start"
self.switchto(f2)
print "f1 foo"
v = self.switchto(f2)
print "f1 v=%s world" % v
self.switchto(f2, "OK")
print "f1 end"

class F2(Fiber):
def main(self):
print "f2 start"
self.switchto(f1)
print "f2 bar"
result = self.switchto(f1, "Hello, ")
print "f2 result=%s" % result
print "f2 end"
self.switchto(f1)

f1 = F1()
f2 = F2()

print "start"
f1.start()
print "end"

-- kayama

解决方案

On Dec 22, 12:10*pm, Akihiro KAYAMA <kay...@st.rim.or.jpwrote:

Hi all.

I found cooperative multi-threading(only one thread runs at once,
explicit thread switching) is useful for writing some simulators.
With it, I''m able to be free from annoying mutual exclusion, and make
results deterministic.

For this purpose, and inspired by Ruby(1.9) fiber, I wrote my own
version of fiber in Python.

It just works, but using native Python threads for non-preemptive
threading is not cost-effective. Python has generator instead but it
seemed to be very restricted for general scripting. I wish I could
write nested (generator) functions easily at least.

Is there any plan of implementing real (lightweight) fiber in Python?

------------------------------------------------------------
import threading

class Fiber(threading.Thread):
* * def __init__(self):
* * * * threading.Thread.__init__(self)

* * * * self.semaphore_running = threading.Semaphore(0)
* * * * self.semaphore_finish = None
* * * * self.val = None

* * * * self.setDaemon(True)
* * * * self.start()
* * * * self.start = self.start_fiber

* * def start_fiber(self):
* * * * self.semaphore_finish = threading.Semaphore(0)
* * * * self.semaphore_running.release()
* * * * self.semaphore_finish.acquire()

* * def run(self): * * * * * * *# override
* * * * self.semaphore_running.acquire()
* * * * self.main()
* * * * if self.semaphore_finish is not None:
* * * * * * self.semaphore_finish.release()

* * def switchto(self, fiber, val=None):
* * * * fiber.val = val
* * * * fiber.semaphore_running.release()
* * * * self.semaphore_running.acquire()
* * * * return self.val

* * def main(self): * * * * * * # should be overridden
* * * * pass

class F1(Fiber):
* * def main(self):
* * * * print "f1 start"
* * * * self.switchto(f2)
* * * * print "f1 foo"
* * * * v = self.switchto(f2)
* * * * print "f1 v=%s world" % v
* * * * self.switchto(f2, "OK")
* * * * print "f1 end"

class F2(Fiber):
* * def main(self):
* * * * print "f2 start"
* * * * self.switchto(f1)
* * * * print "f2 bar"
* * * * result = self.switchto(f1, "Hello, ")
* * * * print "f2 result=%s" % result
* * * * print "f2 end"
* * * * self.switchto(f1)

f1 = F1()
f2 = F2()

print "start"
f1.start()
print "end"

-- kayama

I am not really familiar with ruby but these fibers seem to be some
sort of coroutines. Since python 2.5, generators can be sent values,
this can be used to implement what you want. I have had a got at it
for fun and this is what I came up with: note that there is no need
for a specific class, or for threads. I have tested this only on your
example, but it gives the same result as your code :)

-------------------------------------

# A ''fiber'' is a generator function that yields tuples (fiber, value)
# or (fiber,). The ''run'' function starts the the fiber and carries on
# with the fiber it yields. If the fiber also yields a value, then
# this value is sent to the ''next'' fiber.

def run(fiber):
it, val = fiber(), []
fibers = { fiber: it }
try:
while True:
n = it.send(*val) if val else it.next()
co, val = n[0], n[1:]
it = fibers.get(co)
if it is None:
fibers[co] = it = co()
except StopIteration:
return val[0] if val else None

# Now the two ''fibers''

def f1():
print "f1 start"
yield f2,
print "f1 foo"
v = yield f2,
print "f1 v=%s world" % v
yield f2, "OK"
print "f1 end"

def f2():
print "f2 start"
yield f1,
print "f2 bar"
result = yield f1, "Hello, "
print "f2 result=%s" % result
print "f2 end"
yield f1,

print "start"
run(f1)
print "end"

--------------------------------------

HTH

--
Arnaud


Arnaud Delobelle <ar*****@googlemail.comwrote:

I am not really familiar with ruby but these fibers seem to be some
sort of coroutines. Since python 2.5, generators can be sent values,
this can be used to implement what you want. I have had a got at it
for fun and this is what I came up with: note that there is no need
for a specific class, or for threads. I have tested this only on your
example, but it gives the same result as your code :)

I think it was Microsoft who invented the term ''fiber'' as a synonym for
coroutine. See http://msdn2.microsoft.com/en-us/library/ms682661.aspx

Unfortunately generators only save a single level of stack-frame, so they
are not really a replacement for fibers/coroutines. The OP should perhaps
look at Stackless Python or Greenlets. See
http://codespeak.net/py/dist/greenlet.html


On Dec 22, 2:37*pm, Duncan Booth <duncan.bo...@invalid.invalidwrote:

Arnaud Delobelle <arno...@googlemail.comwrote:

I am not really familiar with ruby but these fibers seem to be some
sort of coroutines. *Since python 2.5, generators can be sent values,
this can be used to implement what you want. *I have had a got at it
for fun and this is what I came up with: note that there is no need
for a specific class, or for threads. *I have tested this only on your
example, but it gives the same result as your code :)


I think it was Microsoft who invented the term ''fiber'' as a synonym for
coroutine. Seehttp://msdn2.microsoft.com/en-us/library/ms682661.aspx

OK

Unfortunately generators only save a single level of stack-frame, so they
are not really a replacement for fibers/coroutines. The OP should perhaps
look at Stackless Python or Greenlets. Seehttp://codespeak.net/py/dist/greenlet.html

Still what I am proposing offers a level of cooperative multi-
threading which may be enough for the OP. In fact it is not clear to
me at the moment what can be done (sensibly :) with the OP''s Fiber
class that cannot be achieved with the run() function I suggested.
This makes me think that there is something important that I am
failing to take into consideration; I would be grateful if it was
pointed out to me.

--
Arnaud


这篇关于光纤(协同多线程)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆