我有一个很大的 N*1 名字数组
我目前正在使用 goroutine 来计算名称之间的编辑距离
问题是 [B] [C] 的结果不同,可能像
ABC BCD 7
ABC BCD 3
姓名有20000条记录
var names []string
将名字分成两 block
nameCount := len(names)
procs := 2
chunkSize := nameCount / procs
channel
ch := make(chan int)
var wg sync.WaitGroup
for i := 0; i < procs; i++ { //create two goroutines
start := i * chunkSize
end := (i+1)*chunkSize - 1
fmt.Println(start, end) //get slice start and end
wg.Add(1)
go func(slices []string, allnames []string) {
for _, slice := range slices {
minDistance = 256
distance := 0
sum := 0
for _, name := range allnames {
distance = calcEditDist(slice, name) //get the LD [A]
sum += 1
if distance > 0 && distance < minDistance {
minDistance = distance
fmt.Println(slice, name, distance) //[B]
fmt.Println(slice, name, calcEditDist(slice, name)) //[C]
} else if distance == minDistance {
fmt.Println(slice, name, distance)
fmt.Println(slice, name, calcEditDist(slice, name))
}
}
// for _, name := range allnames {
// fmt.Println(slice, name)
// }
ch <- sum
// fmt.Println(len(allnames), slice)
break
}
wg.Done()
}(names[start:end], names)
}
我把 calcEditDist 放在了@https://github.com/copywrite/keyboardDistance/blob/master/parallel.go
附言:
如果我声明
var dp [max][max]int
在 calcEditDist 中作为局部变量而不是全局变量,结果是正确的,但是非常慢
更新 1
谢谢所有 friend ,我分三步采纳下面的好建议
1) 我将 dp 缩小到一个更合理的大小,比如 100 甚至更小,完成
2) 我把 dp 声明放在每个 goroutine 中,并像 Nick 说的那样传递它的指针,DONE
3) 稍后我将尝试动态分配 dp,稍后
性能急剧提升,╰(°▽°)╯
最佳答案
正如您在帖子中指出的那样,将 dp
作为全局变量是问题所在。
每次在 CalcEditDistance
中分配它太慢了。
您有两种可能的解决方案。
1) 每个 go-routine 只需要 1 个 dp
数组,所以在 for loop 循环中分配它并传递一个指向它的指针(不要直接传递数组,因为数组按值传递这将涉及大量复制!)
for i := 0; i < procs; i++ { //create two goroutines
start := i * chunkSize
end := (i+1)*chunkSize - 1
fmt.Println(start, end) //get slice start and end
wg.Add(1)
go func(slices []string, allnames []string) {
var dp [max][max]int // allocate
for _, slice := range slices {
minDistance = 256
distance := 0
sum := 0
for _, name := range allnames {
distance = calcEditDist(slice, name, &dp) // pass dp pointer here
更改 calcEditDist 以获取 dp
func CalcEditDist(A string, B string, dp *[max][max]int) int {
lenA := len(A)
lenB := len(B)
2) 重写您的 calcEditDistance
,这样它就不需要庞大的 O(N^2) dp 数组。
如果您仔细研究该函数,它只会访问向上的一行和左侧的一列,因此您实际需要的所有存储空间都是前一行和前一列,您可以以非常低的成本动态分配它们。这也会使其缩放到任意长度的字符串。
不过这需要仔细考虑一下!
关于go - goroutine 中的代码块产生奇怪的错误结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20368711/