2011-04-09 32 views
11

好吧,這可能是一個相當愚蠢的問題,但是在一個actor框架中使用並行集合有什麼好處?也就是說,如果我只從一個演員的郵箱中處理一條消息,是否還需要一個並行收集?平行收藏和演員是相互排斥的嗎?什麼是涉及兩者的用例?Scala 2.9和Actor中的並行集合

回答

15

他們解決了不同的問題。演員擅長解決task parallel problems。儘管並行收集很好地解決了data parallel problems。我不認爲它們是相互排斥的 - 你可以在包含演員的演員和平行集合中使用平行集合。


編輯 - 快速測試: 即使是一些簡單的像一個演員的通知循環的好處。

在下面的代碼中,我們向一個演員註冊表註冊了一百萬個演員,他們必須通知他們一個事件。

非並行通知循環(registry foreach {})在我的機器(4核2.5 GHz筆記本)上平均需要2.8秒。 使用並行採集循環(registry.par.foreach {})時,需要1.2秒鐘,並使用全部四個核心。在斯卡拉

import actors.Actor 

case class Register(actor: Actor) 
case class Unregister(actor: Actor) 
case class Message(contents: String) 

object ActorRegistry extends Actor{ 
    var registry: Set[Actor] = Set.empty 

    def act() { 
    loop{ 
     react{ 
     case reg: Register => register(reg.actor) 
     case unreg: Unregister => unregister(unreg.actor) 
     case message: Message => fire(message) 
     } 
    } 
    } 

    def register(reg: Actor) { registry += reg } 

    def unregister(unreg: Actor) { registry -= unreg } 

    def fire(msg: Message){ 
    val starttime = System.currentTimeMillis() 

    registry.par.foreach { client => client ! msg } //swap registry foreach for single th 

    val endtime = System.currentTimeMillis() 
    println("elapsed: " + (endtime - starttime) + " ms") 
    } 
} 

class Client(id: Long) extends Actor{ 
    var lastmsg = "" 
    def act() { 
    loop{ 
     react{ 
     case msg: Message => got(msg.contents) 
     } 
    } 
    } 
    def got(msg: String) { 
    lastmsg = msg 
    } 
} 

object Main extends App { 

    ActorRegistry.start 
    for (i <- 1 to 1000000) { 
    var client = new Client(i) 
    client.start 
    ActorRegistry ! Register(client) 
    } 

    ActorRegistry ! Message("One") 

    Thread.sleep(6000) 

    ActorRegistry ! Message("Two") 

    Thread.sleep(6000) 

    ActorRegistry ! Message("Three") 

} 
+0

感謝您的回答。我可以看到一個* CAN *可以在演員中使用平行集合,但似乎並不比在這種情況下使用常規集合更有利。另一方面,使用包含演員的平行集合的想法看起來很有用。我喜歡這個想法。謝謝你給我一些想法... – 2011-04-10 18:10:33

+1

感謝你創建一些測試代碼,這太棒了!對此,我真的非常感激。 – 2011-04-11 15:17:20

+0

@Bruce。注意在這裏有另一個使用並行集合的機會 - 上面的代碼需要大約12秒來完成init循環。如果我們並行化了大約4秒((1到1000000).par.foreach {i => ...})。 – 2011-04-11 17:07:40

2

Actors庫只是其中一個選項,接近並行,許多(線程&鎖,STM,期貨/承諾)之一,它不應該被用於各種各樣的問題,或可以與所有東西組合(雖然演員和STM可以在一起做出很好的交易)。在某些情況下,建立一組演員(工作人員+監督員)或明確地將任務分成若干部分並將它們饋送到叉式連接池太繁瑣,而且在現有設備上調用.par你已經在使用這個集合,並且簡單地在並行中進行遍歷,幾乎可以免費獲得性能優勢(就設置而言)。

總而言之,參與者和並行集合是問題的不同維度 - 參與者是併發範例,而並行集合僅僅是一個有用的工具,應該將其視爲不是並行選擇,而是作爲集合工具集。

+0

感謝您對此的看法。這說得通。 – 2011-04-10 22:57:34