限制并发量

分享
源码

今天调试了一下golang编译工具,发现了一个很有"奇怪"的地方

简化问题

假设有1000个任务,1000个并发协程,设置n(cpu核数)个物理处理器(task)并发完成,每个协程只要完成了当前任务采取完成下一个

代码

原始代码,go作者无所畏惧的使用协程

func parseFiles(filenames []string) uint {
	var noders []*noder
	// Limit the number of simultaneously open files.
	sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)

	for _, filename := range filenames {
		go func(filename string) {
			sem <- struct{}{}
			defer func() { <-sem }()
                        ... 
		}(filename)
	}

针对问题代码

package main

import (
	"fmt"
	"math/rand"
	"os"
	"os/signal"
	"runtime"
	"time"
)

func main() {

	c := make(chan os.Signal)
	signal.Notify(c, os.Interrupt)

	rand.Seed(time.Now().UnixNano())
	task := make([]func(), 1000)
	for i := 0; i < 1000; i++ {
		task[i] = func() {
			r := rand.Intn(100)
			time.Sleep(time.Duration(r) * time.Millisecond)
			fmt.Printf("Task cost %d\n", r)
		}
	}

	sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)

	for i := 0; i < len(task); i++ {
		f := task[i]
		go func(f func()) {
			sem <- struct{}{}
			defer func() { <-sem }()
			f()
		}(f)
	}

	<-c
}

如果控制10个协程,应该怎么写呢

package main

import (
	"fmt"
	"math/rand"
	"os"
	"os/signal"
	"runtime"
	"sync"
	"time"
)

func main() {
	c := make(chan os.Signal)
	signal.Notify(c, os.Interrupt)
	exit := make(chan bool)

	sem := make(chan func(), runtime.GOMAXPROCS(0))
	task := make([]func(), 1000, 1000)

	rand.Seed(time.Now().UnixNano())
	for i := 0; i < len(task); i++ {
		task[i] = func() {
			r := rand.Intn(100)
			time.Sleep(time.Duration(r) * time.Millisecond)
			fmt.Printf("task cost %d\n", r)
		}
	}

	wg := &sync.WaitGroup{}
	for i := 0; i < runtime.GOMAXPROCS(0); i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for {
				select {
				case f := <-sem:
					f()
				case <-exit:
					fmt.Printf("Gracefully exit....\n")
					return
				}
			}
		}()
	}

	go func() {
		for i := 0; i < len(task); i++ {
			sem <- task[i]
		}
	}()

	<-c
	close(exit)
	wg.Wait()
}

阅读更多

CPU、ANE、GPU 连接同一块统一内存的简约概念插画

用一个矩阵乘法看懂 ANE、GPU 与统一内存

最近看 Kapitsa 的 ANE 实现时,我想先弄明白一个很小的问题:如果只计算两个矩阵相乘,数据究竟怎样进入 Apple Neural Engine,答案又从哪里回来? 于是把例子收进一个 main.mm 文件:输入是两个 2×2 矩阵,计算图内嵌在文件里,乘法交给 ANE,最后打印结果。本文先把硬件和内存关系画清楚,再顺着这个例子读代码。 1. ANE 是什么,它和 GPU 有什么区别? ANE(Apple Neural Engine)是苹果的神经网络加速器,可以归入 NPU。它与 GPU 是并列的计算单元,不是 GPU 内部的一种核心。 它们都能做大量乘加运算,但面向的软件接口和硬件取舍不同: 计算单元 在这里怎样理解 常见工作

By chainhelen