比较两个地图的元素 – 我这样做对吗?

huangapple go评论77阅读模式
英文:

Compare elements of 2 maps - Am I doing this right?

问题

刚刚在周末开始使用Go,并且我不确定我是否正确使用了Go的特性,或者我是否根本没有按照"Go风格"来做。

这段代码的目的是迭代一个名为non_placed_alleles的映射的元素,并将每个元素与同样存储在映射中的placed_alleles的所有元素进行比较。我试图为non_placed_alleles中的每个元素使用一个go协程,因为比较非常耗时,需要很长时间。

以下是主函数的一部分:

runtime.GOMAXPROCS(8) // 同时运行8个协程?我有10个CPU
c := make(chan string)
for name, alleles := range non_placed_alleles {
    go get_best_places(name, alleles, &placed_alleles, c) 
    // 传递placed_alleles的指针,因为我们只读取,不写入 - 应该是安全的?
}
for channel_item := range c {
    fmt.Println("这个返回了 ", channel_item)
} 
// 这也会崩溃并显示"所有的协程都在休眠",但是所有的结果都被打印出来

以下是被调用的函数:

func get_best_places(name string, alleles []string, placed_alleles *map[string] []string, c chan string) {
    var best_partner string
    // 迭代placed_alleles的所有元素,找到最佳"伴侣"
    for other_key, other_value := range *placed_alleles {
        best_partner := compare_magic() // 省略了因为无聊
    }
    c <- best_partner
}

有没有办法使这个代码"更好"?更快?我是否正确使用了指针和go协程?

英文:

just started working with Go over the weekend and I'm unsure whether I used Go's peculiarities right, or whether I haven't done this "Go-like" at all.

The code is supposed to iterate over elements of a map called non_placed_alleles and compare each of these with all elements in placed_alleles, which are stored in a map as well. I'm trying to use one go-routine for each of the elements in non_placed_alleles as the comparison is quite costly and takes forever.

Here's a bit from the main-function:

runtime.GOMAXPROCS(8) // For 8 consecutive routines at once? got 10 CPUs
c := make(chan string)
for name, alleles := range non_placed_alleles {
    go get_best_places(name, alleles, &amp;placed_alleles, c) 
    // pointer to placed_alleles as we only read, not write - should be safe?
}
for channel_item := range c {
    fmt.Println(&quot;This came back &quot;, channel_item)
} 
// This also crashes with &quot;all goroutines are sleeping&quot;, 
// but all results are printed

And here's the called function:

func get_best_places(name string, alleles []string, placed_alleles *map[string] []string, c chan string) {
    var best_partner string
    // Iterate over all elements of placed_alleles, find best &quot;partner&quot;
    for other_key, other_value := range *placed_alleles {
        best_partner := compare_magic() // omitted because boring
    }
    c &lt;- best_partner
}

Is there any way to make this "better"? Faster? Have I used the pointer-magic and goroutines correctly?

答案1

得分: 2

一些观察:

  • 你可能想要使用带缓冲的通道

    c := make(chan string, someNumber) // someNumber >= goroutines cca

  • 死锁是由于遍历一个没有人关闭的通道引起的(这就是range语句的终止方式)。在Go中,用于协调任务的机制因任务而异。在这种情况下,有些人可能会使用sync.WaitGroup。请仔细检查上述链接下方的示例代码,以获取有关正确使用WaitGroup的提示。另一种选择是使用其他任何一种计算已启动与已完成的工作线程数量的方法(WaitGroup封装了这一点,但我倾向于认为它有点过度设计)。

  • 在这种情况下不需要传递指向映射的指针。在Go中,映射具有完全的引用语义(在底层它只是一个指针)。

英文:

Some observations:

  • You probably want to use a bufered channel

    c := make(chan string, someNumber) // someNumber &gt;= goroutines cca

  • The deadlock stems from ranging a channel which no one closes (that's how the range statement terminates). Machinery to coordinate stuff in Go varies per task. Some would perhaps use in this case a sync.WaitGroup. Please check thoroughly the example code located bellow the preceding link for hints about proper use of WaitGroup. An alternative is some/any other kind/way of counting the started vs finished workers (which WaitGroup encapsulates, but I tend to see it as an overkill).

  • No need to pass pointers to map in this case. Maps in Go have full reference semantics (it's just a pointer under the hood anyway).

huangapple
  • 本文由 发表于 2013年2月11日 18:57:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/14810819.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定