Go语言多核并行化

作者: adm 分类: go 发布时间: 2023-05-13

并发和并行的概念
首先了解什么是并发什么是并行

Go当中实现多核多线程并发
注意:

注意区分什么是goroutine在并发和并行章节已经提到了.

获取当前操作系统CPU的核心数:

示例代码:

package main
​
import (
    "fmt"
    "runtime"
)
​
/*
调用runtime包下的函数获取到当前操作系统的cpu核心数
 */
func main() {
    cpuNum := runtime.NumCPU()
    fmt.Println("cpu核心数为:", cpuNum)
​
    /* 循环调用函数开启线程--->使用go关键字 */
    for i := 0; i < 5; i++ {
        go func(index int) {
            sum := 0
            for j := 0; j < 10000; j++ {
                sum += 1
            }
            fmt.Printf("线程%d, sum值为:%d\n", index, sum)
        }(i)
    }
}

注意:

在调用的时候不能直接使用传统的go run命令,需要使用go run -race命令才能看到goroutine当中的结果

模拟并行计算任务
计算 N 个整型数的总和。
将所有整型数分成 M 份,M 即 CPU 的个数。让每个 CPU 开始计算分给它的那份计算任务,最后将每个 CPU 的计算结果再做一次累加,
得到所有 N 个整型数的总和
示例代码:

package main
​
import "runtime"
​
type Vector []float64
​
// Op函数是一个公共累加函数
func (v Vector) Op(num float64) float64 {
    num = 1
    return num
}
​
// 该类型实现的函数(执行运算函数)
func (v Vector) DoSome(i, n int, u Vector, c chan int) {
    // 循环开启协程
    for ;  i < n ; i++ {
        v[i] += u.Op(v[i])
    }
    // 将结果传输回到channel当中
    c <- 1
}
​
// 设置Cpu数量
var Ncpu = runtime.NumCPU()
const NCPU = 8 // 这里注意常量和变量的区别,变量的声明和赋值不能够传递给常量
​
// 该类型分配的函数(分配cpu函数)
func (v Vector) DoAll(u Vector) {
    // 声明任务完成的通道,该通道是个缓冲通道,缓冲通道
    /*
    这里注意make和new的区别
    make:返回的是创建的对象本身
    new:返回的是创建的对象的指针
     */
    c := make(chan int, NCPU)
​
    // 循环调用DoSome函数执行计算过程
    for i := 0; i < NCPU; i++ {
        go v.DoSome(i*len(v)/NCPU, (i+1)*len(v)/NCPU, u, c)
    }
​
    // 等待所有cpu完成任务将数据放入缓冲通道
    for i := 0; i < NCPU; i++ {
        <-c // 匿名接收
    }
}

注意:

实际上所有这些goroutine都运行在同一个CPU核心上,在一个goroutine得到时间片执行的时候,其他goroutine都会处于等待状态。

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!