对于数值问题,前期例程是否先发制人多任务?
我对Go的精益设计非常感兴趣,速度,但大部分是因为频道是一流的对象。我希望最后一点可以通过他们应该允许的复杂互连模式为大数据启用全新的深度分析算法。
我的问题域需要对流式传入数据进行实时计算绑定分析。数据可以划分为100-1000个“问题”,每个问题需要10到1000秒才能计算(即它们的粒度高度可变)。然而,在输出有意义之前,结果必须 all ,即说有500个问题,并且在我可以使用它们之前必须解决所有500个问题。应用程序必须能够扩展,可能会成千上万(但不太可能成千上万)问题。
鉴于我不太担心数字库的支持(大部分内容都是自定义的),Go似乎很理想,因为我可以将每个问题映射到goroutine。在我投资学习Go之前,而不是说,朱莉娅,鲁斯特或一种功能性语言(据我所知,没有一个具有一流的渠道,所以对我来说是直接的劣势)我需要知道是否goroutines 正确地先发制人地执行多项任务。也就是说,如果我在一台功能强大的多核计算机上运行500个计算绑定goroutine,我是否可以期望在所有“问题”中合理地进行负载平衡,或者我是否必须一直“合作”地“屈服”1995风格。考虑到问题的可变粒度以及在计算期间我通常不知道需要多长时间的事实,这个问题尤其重要。
如果另一种语言能更好地为我服务,我很高兴听到它,但我要求执行的线程(或执行/协同程序)是轻量级的。例如,Python多处理模块对于我的扩展目标而言太耗费资源。只是先发制人:我做了解并行性和并发性之间的区别。
答案 0 :(得分:4)
Go运行时有一个模型,其中多个Go例程以自动方式映射到多个线程。 No Go例程绑定到某个线程,调度程序可以(并且将)将Go例程调度到下一个可用线程。 Go程序使用的线程数取自GOMAXPROCS
环境变量,可以用runtime.GOMAXPROCS()覆盖。这是一个简化的描述,足以理解。
在下列情况下,Go例程可能会产生:
io.Read()
或可能需要等待其他Go例程的操作,如获取互斥锁或发送或接收频道以下事项阻止Go例程屈服:
答案 1 :(得分:1)
不确定我完全理解你,但你可以设置runtime.GOMAXPROCS
扩展到所有进程,然后使用通道(或锁)来同步数据,例如:
const N = 100
func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) //scale to all processors
var stuff [N]bool
var wg sync.WaitGroup
ch := make(chan int, runtime.NumCPU())
done := make(chan struct{}, runtime.NumCPU())
go func() {
for i := range ch {
stuff[i] = true
}
}()
wg.Add(N)
for i := range stuff {
go func(i int) {
for { //cpu bound loop
select {
case <-done:
fmt.Println(i, "is done")
ch <- i
wg.Done()
return
default:
}
}
}(i)
}
go func() {
for _ = range stuff {
time.Sleep(time.Microsecond)
done <- struct{}{}
}
close(done)
}()
wg.Wait()
close(ch)
for i, v := range stuff { //false-postive datarace
if !v {
panic(fmt.Sprintf("%d != true", i))
}
}
fmt.Println("All done")
}
编辑:有关调度程序@ http://tip.golang.org/src/pkg/runtime/proc.c
的信息Goroutine调度程序
调度程序的工作是在工作线程上分发准备运行的goroutine。
主要概念是:
- G - goroutine。
- M - 工作线程或机器。
- P - 处理器,执行Go代码所需的资源。 M必须有一个关联的P来执行Go代码,但是它可以被阻止,或者在没有相关P的系统调用中。