3.21 Go之多核并行化
并发和并行的概念
首先了解
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
    It's a lonely road!!!
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号