光纤(协同多线程) [英] fiber(cooperative multi-threading)
问题描述
大家好。
我发现合作多线程(一次只运行一个线程,
显式线程切换)对于编写一些模拟器非常有用。
有了它,我就可以摆脱烦人的互斥,并且确定
结果确定性。
出于这个目的,并且受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"
-- kayamaI 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.aspxOK
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.htmlStill 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屋!