我有一个模拟代码,可以创建N个样本,并逐个处理。使用IoC(控制反转),处理器方法被赋予一个被调用的方法。 从配置[“迭代”]映射控制样本数。
这是处理器方法:
def processor(configuration:Map[String, Any], f:(Int, Summary) => Unit) = {
val byteWidth:Int = configuration.getOrElse("byteWidth", 4).asInstanceOf[Int]
...
val iteration:Int = configuration.getOrElse("iteration", 10000).asInstanceOf[Int]
val caller = self
(1 to iteration).foreach { i =>
...
val newBf = Summary.makeIt() // generate simulation data
f(i, newBf)
}
}
}
这是来电者功能:
val conf = MMap[String, Any]()
conf("iteration") = 100000
def calculate(i:Int, bf: Summary) : Unit = {
...
}
processor(configuration = conf.toMap, calculate)
此代码工作正常,但它不使用多核,因此我修改了处理器以使用actor。
def parallelProcess(configuration:Map[String, Any], f:(Int, Summary) => Unit) = {
...
val iteration:Int = configuration.getOrElse("iteration", 10000).asInstanceOf[Int]
val caller = self
(1 to iteration).foreach { i =>
actor {
caller ! {
...
val newBf = Summary.makeIt() // generate simulation data
f(i, newBf)
}
}
}
(1 to iteration).foreach { i =>
receive {
case msg => msg
}
}
}
此代码工作正常,它使用我拥有的所有核心。即使我创建100K样本(以及相应的演员),它也可以正常工作,但是它会减慢100万个演员的速度,它会慢一点,而1000万个样本变得非常慢,所有核心都很忙。
我希望演员可能也是罪魁祸首,即使是100K的演员也已经相当大,但工作得很好。
有多少演员是太多的演员?有没有办法控制这类问题的演员数量?
答案 0 :(得分:4)
演员是一个轻量级的控制单位。它基本上是一个描述如何响应消息和包含消息的邮箱的PartialFunction。中央事件循环从邮箱中取出一条消息,查看该actor是否会响应它,如果是,则调度执行在线程上发生。线程有点重。它们每个线程的内存大约为1MB。在完美的CPU绑定处理中,每个核心只需要1个线程。
有多少演员太多的问题取决于你的申请。您基本上需要弄清楚平均每条消息的CPU使用时间以及您拥有的核心数。如果说每个消息带有8个内核20ms,你可以提供一个大小为8和400个演员的线程池,你应该最大化你所有的cpu时间。仅仅因为你可以提供更多演员和/或更多线程并不意味着你可以更快地完成任务。随着管理线程和角色的开销开始发挥作用,您将达到最低限度,然后开始为您的运行添加时间。
您可以修改Akka的配置来控制线程池大小或管理自定义执行上下文。有关详细信息,请参阅非常好的文档。
答案 1 :(得分:1)
Scala标准库actor已被弃用,建议使用Scala 2.10以后的Akka actor。 Akka声称每GB内存支持250万个参与者(每个参与者约400个字节的开销)。
我认为没有任何内置机制可以对流程中的参与者数量设置上限。你必须为此构建应用程序逻辑。
FWIW,我已经运行了一个拥有240,000名演员的Akka节点,其吞吐量很高,并且MackBook Pro没有明显减速。