2013-12-04 3 views
1

у меня есть большой N * 1 имя массива
я в настоящее время с помощью goroutine для вычисления расстояния редактирования имени среди друг другаблок кода в goroutine производит странное неправильные результаты

на вопрос результаты на [ B], [C], отличаются, может быть, как

ABC BCD 7
ABC BCD 3

есть 20000 записей в именах

var names []string 

имена делятся на две куски

nameCount := len(names) 
procs := 2 
chunkSize := nameCount/procs 

канала

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

PS:
если я объявляю

var dp [max][max]int 

в calcEditDist в качестве локальной переменной вместо глобального, результаты правы, но невероятно медленно

UPDATE 1
Спасибо всем приятель, я беру большой совет ниже в трех шагах
1) Я сжал dp до разумного размера, например, 100 или даже меньше, DONE
2) Я поместил объявление dp в каждую горуту и ​​передал его указатель как Ni ск сказал СДЕЛАНО
3) позже я постараюсь динамически Alloc дп, ПОЗЖЕ

производительность улучшилась круто, ╰ (° ▽ °) ╯

+0

Вы не можете использовать 'dp' как глобальную переменную, если функция должна выполняться одновременно! Он будет разделяться всеми гортанами, а содержание dp будет смешанным. Кроме того, в функции main() файла github вы уверены, что он был выполнен параллельно? 'go parallel' заставит его работать в другой gorutine, но цикл блокируется чтением из канала, поэтому он не будет запускать другой' go parallel', пока предыдущий не завершится. – siritinga

+0

hi siritinga.Github-код был старой версией, я, конечно, решил параллельную проблему. Однако если dp является локальной переменной, массив 1024 * 1024 будет зацикливаться в каждом цикле, это очень медленно, кажется, что функция calc не является безопасным для goroution, любое решение? – XiaoMing

+0

Я не пробовал, но проблема не в том, чтобы выделить миллионную матрицу, это не так много, и вам нужно только сделать это количество процессоров, которые у вас есть, поэтому я полагаю, что это будет 4 или 8 раз. Вы должны опубликовать свою окончательную версию, чтобы люди могли ее проверить. – siritinga

ответ

1

Как вы определили в вашей публикации, имеющие dp как глобальная переменная.

Выделение его каждый раз в CalcEditDistance происходит слишком медленно.

У вас есть два возможных решения.

1) вам понадобится только 1 dp массив для каждой рутинной процедуры, поэтому выделите его в цикле цикла for и передайте указатель на него (не передавайте массив напрямую, поскольку массивы проходят по значению, что будет включать в себя много копирование!)

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 принять ДП

func CalcEditDist(A string, B string, dp *[max][max]int) int { 
     lenA := len(A) 
     lenB := len(B) 

2) переписывают свой calcEditDistance поэтому не нуждается в массивную O (массив дп N^2).

Если вы внимательно изучаете функцию, она всегда обращается к строке вверху и столбцу влево, поэтому все необходимое для хранения - это предыдущая строка и предыдущие столбцы, которые вы могли бы распределить динамически с минимальными затратами. Это также уменьшит масштаб до любой длины строки.

Это потребует немного тщательной мысли!

+0

Очень интересные идеи, особенно динамическое распределение – XiaoMing

Смежные вопросы