我现在正在学习 Go,有一个实际的目的。我需要编写一个程序,在其中需要处理包含数百万个浮点值的数组。在 C++ 中,通过创建指针并在多个处理线程之间划分所有元素的索引,可以轻松解决此任务。
例如,我有一个数组
[x,x,x,x,x,x,x,x,x,x,x,x,x,x,x]
。
线程号 1 将获取 0-1 的区域,线程号 2 将获取 2-3 的区域,依此类推。但仅限于数百万的规模,并且线程将是例如16/32/64。与 CUDA 中的原理大致相同。
Go 中是否可以做类似的事情? 谢谢!
演示代码:
import "fmt"
func main() {
var numbers [10000000]float64= [10000000]float64{}
//prepare numbers
f:= func(first int, last int){
//magic is here (read/write)
}
go f(0, 999999)
go f(1000000, 1999999)
and so on...
}
我才刚刚开始学习
是的,你可以做到。这是一种方法,工作人员不传递固定范围,而是进行自己的迭代。请注意使用 sync.WaitGroup 来确保 main 等待所有工作线程完成。
package main
import (
"fmt"
"sync"
)
func main() {
const num_workers = 3
var numbers = []int{1, 3, 5, 9, 12, 14, 15, 16, 17, 20, 22, 100, 101, 103, 99, 55, 1039, 938}
var wg sync.WaitGroup
for i := 0; i < num_workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := i; j < len(numbers); j += num_workers {
fmt.Printf("worker: %d, input: %d\n", i, numbers[j])
}
}()
}
wg.Wait()
}
示范.
但是 Go 中更惯用的方式是使用通道。工作人员根据需要从频道中提取号码。
package main
import (
"fmt"
"sync"
)
func main() {
const num_workers = 3
var numbers = []int{1, 3, 5, 9, 12, 14, 15, 16, 17, 20, 22, 100, 101, 103, 99, 55, 1039, 938}
inputs := make(chan int)
var wg sync.WaitGroup
for i := 0; i < num_workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for input := range inputs {
fmt.Printf("worker: %d, input: %d\n", i, input)
}
}()
}
// main feeds the numbers into the channel.
for _, num := range numbers {
inputs <- num
}
close(inputs)
wg.Wait()
}
这支持不断变化的工人数量,工人可以按照自己的节奏前进。这些数字不需要被放入内存中,通道可以从流中馈送。