保存并行化goroutine的结果

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

Saving results from a parallelized goroutine

问题

我正在尝试在Go语言中并行化一个操作,并以一种可以迭代求和的方式保存结果。

我已经成功设置了参数,以确保没有死锁发生,并且我已经确认操作在函数内部正确地工作和保存。但是,当我迭代我的结构体切片并尝试求和操作的结果时,它们都保持为0。我尝试过通过引用、指针和通道(导致死锁)传递参数。

我只找到了这个例子来帮助:https://golang.org/doc/effective_go.html#parallel。但是这个例子似乎已经过时了,因为Vector已经被弃用了?我也没有找到任何关于这个函数(在例子中)是如何构造的参考(在名称之前使用func (u Vector))。我尝试用切片替换它,但是得到了编译时错误。

任何帮助将不胜感激。这是我代码的关键部分:

type job struct {
  a int
  b int
  result *big.Int
}

func choose(jobs []Job, c chan int) {
  temp := new(big.Int)
  for _,job := range jobs {
    job.result = //在job.a和job.b上执行操作
    //fmt.Println(job.result)
  }
  c <- 1
}

func main() {
  num := 100 //可以非常大(所以我们需要big.Int)
  n := num
  k := 0
  const numCPU = 6 //runtime.NumCPU
  count := new(big.Int)

  // 创建一个二维切片的作业,每个核心一个
  jobs := make([][]Job, numCPU)

  for (float64(k) <= math.Ceil(float64(num / 2))) {
    // 每个核心添加一个作业,交替进行,以便
    // 作业集在难度上相似
    for i := 0; i < numCPU; i++ {
      if !(float64(k) <= math.Ceil(float64(num / 2))) {
        break
      }
      jobs[i] = append(jobs[i], Job{n, k, new(big.Int)})
      n -= 1
      k += 1
    }
  }

  c := make(chan int, numCPU)
  for i := 0; i < numCPU; i++ {
    go choose(jobs[i], c)
  }

  // 清空通道
  for i := 0; i < numCPU; i++ {
    <-c
  }
  // 计算完成

  for i := range jobs {
    for _,job := range jobs[i] {
      //fmt.Println(job.result)
      count.Add(count, job.result)
    }
  }

  fmt.Println(count)
}

这是在Go Playground上运行的代码:https://play.golang.org/p/X5IYaG36U-

英文:

I am trying to parallelize an operation in golang and save the results in a manner that I can iterate over to sum up afterwords.

I have managed to set up the parameters so that no deadlock occurs, and I have confirmed that the operations are working and being saved correctly within the function. When I iterate over the Slice of my struct and try and sum up the results of the operation, they all remain 0. I have tried passing by reference, with pointers, and with channels (causes deadlock).

I have only found this example for help: https://golang.org/doc/effective_go.html#parallel. But this seems outdated now, as Vector as been deprecated? I also have not found any references to the way this function (in the example) was constructed (with the func (u Vector) before the name). I tried replacing this with a Slice but got compile time errors.

Any help would be very appreciated. Here is the key parts of my code:

type job struct {
a int
b int
result *big.Int
}
func choose(jobs []Job, c chan int) {
temp := new(big.Int)
for _,job := range jobs {
job.result = //perform operation on job.a and job.b
//fmt.Println(job.result)
}
c &lt;- 1
}
func main() {
num := 100 //can be very large (why we need big.Int)
n := num
k := 0
const numCPU = 6 //runtime.NumCPU
count := new(big.Int)
// create a 2d slice of jobs, one for each core
jobs := make([][]Job, numCPU)
for (float64(k) &lt;= math.Ceil(float64(num / 2))) {
// add one job to each core, alternating so that
// job set is similar in difficulty
for i := 0; i &lt; numCPU; i++ {
if !(float64(k) &lt;= math.Ceil(float64(num / 2))) {
break
}
jobs[i] = append(jobs[i], Job{n, k, new(big.Int)})
n -= 1
k += 1
}
}
c := make(chan int, numCPU)
for i := 0; i &lt; numCPU; i++ {
go choose(jobs[i], c)
}
// drain the channel
for i := 0; i &lt; numCPU; i++ {
&lt;-c
}
// computations are done
for i := range jobs {
for _,job := range jobs[i] {
//fmt.Println(job.result)
count.Add(count, job.result)
}
}
fmt.Println(count)
}

Here is the code running on the go playground https://play.golang.org/p/X5IYaG36U-

答案1

得分: 2

只要[]Job切片一次只被一个goroutine修改,就没有理由不能直接修改作业。

for i, job := range jobs {
    jobs[i].result = temp.Binomial(int64(job.a), int64(job.b))
}

https://play.golang.org/p/CcEGsa1fLh

你还应该使用WaitGroup,而不是依赖于自己在通道中计数令牌。

英文:

As long as the []Job slice is only modified by one goroutine at a time, there's no reason you can't modify the job in place.

for i, job := range jobs {
jobs[i].result = temp.Binomial(int64(job.a), int64(job.b))
}

https://play.golang.org/p/CcEGsa1fLh

You should also use a WaitGroup, rather than rely on counting tokens in a channel yourself.

huangapple
  • 本文由 发表于 2016年11月17日 05:30:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/40642699.html
匿名

发表评论

匿名网友

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

确定