def run_benchmark(nm):
a_ch = SL.channel()
b_ch = SL.channel()
c_ch = SL.channel()
SL.tasklet(a)(a_ch, b_ch)
SL.tasklet(b)(b_ch, c_ch)
SL.tasklet(c)(c_ch)
for r in xrange(m-1, -1, -1):
a_ch.send(r)
SL.schedule()
def a(cin, cout):
while True:
r = cin.receive()
cout.send(r)
def b(cin, cout):
while True:
r = cin.receive()
cout.send(r)
def c(cin):
while True:
r = cin.receive()
用tiemit测了下结果:
D:\stepbystep>c:/Python26/python -m timeit -s "import test_stack"
"test_stack.ru
n_benchmark(10000)"
100 loops, best of 3: 17 msec per loop
而直接用顺序的话,代码如下:
import stackless as SL
def run_benchmark(n, m):
for r in xrange(m-1, -1, -1):
a(r)
def a(n):
b(n)
def b(n):
c(n)
def c(n):
pass
测试结果如下:
D:\stepbystep>c:/Python26/python -m timeit -s "import test_comm"
"test_comm.run_
benchmark(10000)"
100 loops, best of 3: 5.03 msec per loop
===========
额,这个结果与我所预想的似乎不一致(机器是双核的,应该支持并发的吧),号称的并发还不如线性的单进程单线程快。
我所能翻到的文档几乎都是将这个‘微线程’与线程作比较,而且都是大量生成微线程和线程,最终得出结论,线程数达到多少
就要崩溃了,或者线程间数据传递,切换慢了等。还没有找到说某个东东本来是单进程的,改成多个微线程配合则提高
效率之类的例子。想问,有这样的例子么?或者说,由于代码的问题并没有能够真正实现并发机制,那要如何修改呢?
个人感觉上面的代码写的倒更有点协程的味道,但是,这也不应该更慢才对啊。。望有大大指导下
--
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:pyth...@googlegroups.com
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
On 7月2日, 下午12时33分, "PT M." <pen...@gmail.com> wrote:
> def func_a():
> #do something
> func_b()
>
> def func_b():
> #do something
> func_a()
>
额,这个可不可以理解成stackless只是在' 多个节点之间互相捣腾 '时有效率上的提高,而节点间的顺序传递就没有效果了?
还有我代码中的这个 schedule可以删掉的,效果一样(还是那么慢)
------
补充一点,一般在多个节点间传递处理数据,如果有节点会有一些类似io之类可能要等待的操作时可以用多线程来解决,这个时候"微线程"似乎也没有效
--
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:pyth...@googlegroups.com
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
On 7月2日, 下午1时04分, "PT M." <pen...@gmail.com> wrote:
> stackless有篇tutorial的例子是模拟一圈人踢毽子,对比系统线程跟微线程,前者在开到几千时候系统就吃不消了,微线程开到十万依然稳定,内存也 很小。
这个例子我看过,就是我说的那种开了一堆 微线程 和 线程 做比较的,不是我想要的
> io等待可以用stackless啊
我做了这么个测试,代码如下:
import urllib
'''单进程'''
def main():
urls =
['www.shopex.cn','www.ibm.com','www.apple.com','www.oracle.com']
for url in urls:
a(url)
def a(url):
url = "http://%s"%url
b(url)
def b(url):
urllib.urlopen(url)
测试结果:
[root@localhost tmp]# python -m timeit -s "import test_comm"
"test_comm.main()"
10 loops, best of 3: 2.46 sec per loop
代码:
'''多线程'''
import urllib
import threading,Queue
class T(threading.Thread):
def __init__(self,queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
url = self.queue.get()
urllib.urlopen(url)
self.queue.task_done()
def main():
global queue
queue = Queue.Queue()
t = T(queue)
t.setDaemon(True)
t.start()
urls =
['www.shopex.cn','www.ibm.com','www.apple.com','www.oracle.com']
for url in urls:
a(url)
def a(url):
global queue
url = "http://%s"%url
queue.put(url)
测试结果:
[root@localhost tmp]# python -m timeit -s "import test_thread"
"test_thread.main()"
1000 loops, best of 3: 4.9 msec per loop
代码:
'''stackless'''
import urllib
import stackless
def main():
urls =
['www.shopex.cn','www.ibm.com','www.apple.com','www.oracle.com']
a_ch = stackless.channel()
b_ch = stackless.channel()
stackless.tasklet(a)(a_ch, b_ch)
stackless.tasklet(b)(b_ch)
for url in urls:
a_ch.send(url)
def a(cin, cout):
while True:
url = cin.receive()
url = "http://%s"%url
cout.send(url)
def b(cin):
while True:
url = cin.receive()
urllib.urlopen(url)
测试结果:
[root@localhost tmp]# python -m timeit -s "import test_stack"
"test_stack.main()"
10 loops, best of 3: 2.43 sec per loop
=========
很明显能够看出 多线程 策略 的效率要高的多,而微线程情何以堪啊。抑或,我这儿没有处理好?
--
好吧,我承认自己真的还不算了解stackless,目前的理解全部都建立在《stackless python并发编程》中文译本上。
里面的一些术语还让我蛮疑惑的,它里面细分了 '微进程' '协程' '轻线程'。总的感觉似乎都差不多,所以就依葫芦画瓢了。。
> 3、协程的好处,在于能创建很多很多,这样能以简单多线程编程方式开发超多并发的应用;至于利用多核,可以结合真实线程和多进程。
>
这个协程,建很多很多和并发有什么关系呢?这里给个简单场景:
def a(data):pass
def b(data):pass
def c(data):pass
if __name__=='__main__':
for data in datas:
data = a(data)
data = b(data)
c(data)
应该怎样改造才能体现出协程的好处,使得效率比以上模式更高呢?
”協程“、”線程“、”進程“三者所在的空間不一樣,”協程“只能在同一線程中切
換,”線程“只能在同一進程中交換。”進程“就不用說了,各個進程都有一個獨立的
內存空間。
這樣也就決定三者對資源的開銷不一樣,協程<線程<進程,如果頻繁進行創建-銷
毀動作,除了內存外,還可以看到三者對創建-銷毀所花的時間不一樣。
另外再說一下“並發”,不知道Yul說的“並發”是指哪個層面的。IO的並發處理?還
是指令的並發執行?還是任務的並發處理?
照我的理解大數情況說的並發是指IO或任務的並發處理。從物理層面來說只有多進
程、多CPU情況下才可能實現指令的並發處理。大多數的並發、多任務都是你用一
會我用一會來實現,至於什麼時候給誰用,這個大多數情況下都是操作系統來作調度。
協程,就是在一個線程內可以自己對任務進行調度,只有涉及到IO等待情況下協程
才會體現優勢。就用下面greenlet協程例子作下說明吧。
buffer=[]
def writetobuffer(io):
#每次從io讀取1024個字節數據到buffer中
#讀取後切換到readfrombuffer處理數據
while not io.close():
buffer.append(io.read(1024)) #建議使用非阻塞方式讀取io
readfrombuffer.switch()
buffer.append('')
def readfrombuffer():
while True:
if buffer:
d=buffer.pop(0)
if d=='':
break
print d
writetobuffer.switch()
if __name__=='__main__':
a=greenlet(writetobuffer)
b=greenlet(readfrombuffer)
a.switch()
我這樣的理解不知道對不對,坐等大牛拍磚。
--
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:pyth...@googlegroups.com
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> 拿协程和单线程比是无比傻的决定,本来就单线程的事情何必费劲要协程做?
> 协程的比较目标是多线程。
个人觉得无论是线程还是协程都是为了提高整个程序的运行速度/效率而运用的一种技巧/手段。
以我之前给的场景:
def a(data):pass
def b(data):pass#有IO等待或其他耗时的操作
def c(data):pass
if __name__=='__main__':
for data in datas:
data = a(data)
data = b(data)
c(data)
这个用多线程效率是远比单线程高的。
那么既然协程的对比目标是多线程,那么要如何修改才能体现出协程的独到高效之处?小子其实最想知道的是这个,呵呵
???这个例子里 a b c不可分吧
On 7月5日, 上午9时42分, 老光 <yaoguangm...@cq.chinatelecom.com.cn> wrote:
> 感觉楼主所举的问题是一个生产流水线的问题,a,b,c分别是三个步骤.
对头!就是个流水线的问题。
> 如果对产出结果的顺序没有要求的话,可以设两个管道文件来存放中间结果.abc可以同步运行.
没有产出结果的顺序要求。至于设管道文件同步运行,是否就是我一开始写的"微线程or协程"方式?
> 不过,若事实是,总是b花的时间多,而不是abc随机花的时间多,那这样的修改对于总时间不会有很大提高,只是可能节约a,c花的时间而已.
实际项目上abc的时间是浮动的。所以对调高效率是可以预期的。本来就是准备用多进程/多线程 并发 来解决。因为上次 上海聚会 有提到
协程的概念,所以想尝试下。于是便有了这一堆东西,可惜似乎离预想的比较远。
不知道有没有大牛用协程/微线程 实现 类似此类 流水线似的的并发,望指教
不是太理解。现在我的程序"脚"已经有了(可以正常运行了),我想让它跑的更快更稳,于是想做双鞋子。
本来是选定用革质的(多线程/多进程)的料子,后来听说皮质的(协程/微线程)不错。于是尝试着做了个
模型(主贴),发现穿上去似乎没有传说中的那么好。怀疑是自己的工艺问题(或者胶质配备不合理等原因)导致的,
所以想咨询下相应的专业人士有没有整改的建议,或者说,皮质的就不适合做这类的鞋子。并没有说为了使用
"协程"这双跑鞋就硬要把脚往里挤。
--
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:pyth...@googlegroups.com
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
--
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:pyth...@googlegroups.com
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp
> 如果你需要切进来多次,接受数据,处理一下,再进入阻塞,这才是利用协程的地方。当然,为了充分利用多核CPU,你还是得用多进程包装一次的。
> 协程的经典问题是长连接http服务器。
似乎抓到点了!这个长连接是不是非阻塞式的?
def main():
global grlist
while True:
msg = socket.get()#长连接
gr = greenlet(msg)
gr.start()
grlist.append(gr)
是不是这个socket的链接做成非阻塞的,就能发挥出协程的能量了?也只有这种类似的非阻塞式长链接模式才能淋漓的体现协程的力量?
--
来自: `python-cn`:CPyUG ~ 华蟒用户组 | 发言:pyth...@googlegroups.com
退订: http://tinyurl.com/45a9tb //针对163/qq邮箱:http://tinyurl.com/4dg6hc
详情: https://groups.google.com/group/python-cn
严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp