gpt4 book ai didi

go - 1600 万个协程 - "GC assist wait"

转载 作者:IT王子 更新时间:2023-10-29 02:32:28 24 4
gpt4 key购买 nike

我正在运行一个计算 mandelbrot 集的 go 程序。为每个像素启动一个 gouroutine 来计算收敛性。对于 pixelLengthx = 1000pixelLengthy = 1000,程序运行良好。如果我为 pixelLengthx = 4000 运行相同的代码,pixelLengthy = 4000,程序将在几十秒后开始打印:

goroutine 650935 [GC assist wait]:
main.converges(0xa2, 0xb6e, 0xc04200c680)
.../fractals/fractals.go:41 +0x17e
created by main.main
.../fractals/fractals.go:52 +0x2af

程序不会终止,只是继续打印。

package main

import (
"image"
"image/color"
"image/draw"
"image/png"
"log"
"math/cmplx"
"os"
"sync"
)

var sidex float64 = 4.0
var sidey float64 = 4.0
var pixelLengthx int = 4000
var pixelLengthy int = 4000
var numSteps int = 100

func converges(wg *sync.WaitGroup, i, j int, m *image.RGBA) {
wht := color.RGBA{255, 50, 128, 255}

plx := float64(pixelLengthx)
ply := float64(pixelLengthy)
fi := float64(i)
fj := float64(j)

c := complex((fi-plx/2)/plx*sidex, (fj-ply/2)/ply*sidey)
zn := complex(0, 0)
for k := 0; k < numSteps; k++ {
zn = cmplx.Pow(zn, 2) + c
}

if cmplx.Abs(zn) > 0.1 {
m.Set(i, j, wht)
}

wg.Done()
}

func main() {
err := Main()
if err != nil {
log.Fatal(err)
}
}

func Main() error {
m := image.NewRGBA(image.Rect(0, 0, pixelLengthx, pixelLengthy))
blk := color.RGBA{0, 0, 0, 255}
draw.Draw(m, m.Bounds(), &image.Uniform{blk}, image.ZP, draw.Src)

numGoroutines := pixelLengthx * pixelLengthy
wg := &sync.WaitGroup{}
wg.Add(numGoroutines)

for x := 0; x < pixelLengthx; x++ {
for y := 0; y < pixelLengthy; y++ {
go converges(wg, x, y, m)
}
}

wg.Wait()

f, err := os.Create("img.png")
if err != nil {
return err
}
defer f.Close()

err = png.Encode(f, m)
if err != nil {
return err
}

return nil
}

这是怎么回事?为什么程序甚至会打印一些东西?

我使用的是 go 版本 go1.8 windows/amd64。

Memory usage during program execution.

最佳答案

goroutine 是轻量级的,但你过于自信了。我认为你应该像下面这样制作 worker 。

package main

import (
"image"
"image/color"
"image/draw"
"image/png"
"log"
"math/cmplx"
"os"
"sync"
)

var sidex float64 = 4.0
var sidey float64 = 4.0
var pixelLengthx int = 4000
var pixelLengthy int = 4000
var numSteps int = 100

func main() {
err := Main()
if err != nil {
log.Fatal(err)
}
}

type req struct {
x int
y int
m *image.RGBA
}

func converges(wg *sync.WaitGroup, q chan *req) {
defer wg.Done()

wht := color.RGBA{255, 50, 128, 255}
plx := float64(pixelLengthx)
ply := float64(pixelLengthy)

for r := range q {

fi := float64(r.x)
fj := float64(r.x)

c := complex((fi-plx/2)/plx*sidex, (fj-ply/2)/ply*sidey)
zn := complex(0, 0)
for k := 0; k < numSteps; k++ {
zn = cmplx.Pow(zn, 2) + c
}

if cmplx.Abs(zn) > 0.1 {
r.m.Set(r.x, r.y, wht)
}
}
}

const numWorker = 10

func Main() error {
q := make(chan *req, numWorker)
var wg sync.WaitGroup
wg.Add(numWorker)
for i := 0; i < numWorker; i++ {
go converges(&wg, q)
}

m := image.NewRGBA(image.Rect(0, 0, pixelLengthx, pixelLengthy))
blk := color.RGBA{0, 0, 0, 255}
draw.Draw(m, m.Bounds(), &image.Uniform{blk}, image.ZP, draw.Src)

for x := 0; x < pixelLengthx; x++ {
for y := 0; y < pixelLengthy; y++ {
q <- &req{x: x, y: y, m: m}
}
}
close(q)

wg.Wait()

f, err := os.Create("img.png")
if err != nil {
return err
}
defer f.Close()

err = png.Encode(f, m)
if err != nil {
return err
}

return nil
}

关于go - 1600 万个协程 - "GC assist wait",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44825550/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com