gpt4 book ai didi

multithreading - 使用 Goroutine 实际上需要更长的时间来执行

转载 作者:IT王子 更新时间:2023-10-29 00:41:02 25 4
gpt4 key购买 nike

我确定我做错了什么,我有一个 Go 程序可以解析 OBJ 格式的 3D 模型并输出一个 json 对象。当我在不添加 goroutine 的情况下运行它时,我得到以下输出:

$ go run objParser.go ak47.obj extincteur_obj.obj 
--Creating ak47.json3d from ak47.obj
--Exported 85772 faces with 89088 verticies
--Creating extincteur_obj.json3d from extincteur_obj.obj
--Exported 150316 faces with 151425 verticies
Parsed 2 files in 8.4963s

然后我添加了 goroutines 并得到了这个输出:

$ go run objParser.go ak47.obj extincteur_obj.obj 
--Creating ak47.json3d from ak47.obj
--Creating extincteur_obj.json3d from extincteur_obj.obj
--Exported 85772 faces with 89088 verticies
--Exported 150316 faces with 151425 verticies
Parsed 2 files in 10.23137s

考虑到解析的交错,它的打印顺序是我所期望的,但我不知道为什么它实际上需要更长的时间!代码很长,我剪掉了我能剪掉的,但它仍然很长,对此感到抱歉!

package main

func parseFile(name string, finished chan int) {
var Verts []*Vertex
var Texs []*TexCoord
var Faces []*Face

var objFile, mtlFile, jsonFile *os.File
var parseMaterial bool

// Set up files and i/o
inName := name
outName := strings.Replace(inName, ".obj", ".json3d", -1)
parseMaterial = false

fmt.Printf("--"+FgGreen+"Creating"+Reset+" %s from %s\n", outName, inName)

var err error
var part []byte
var prefix bool

if objFile, err = os.Open(inName); err != nil {
fmt.Println(FgRed+"!!Failed to open input file!!"+Reset)
return
}

if jsonFile, err = os.Create(outName); err != nil {
fmt.Println(FgRed+"!!Failed to create output file!!"+Reset)
return
}

reader := bufio.NewReader(objFile)
writer := bufio.NewWriter(jsonFile)
buffer := bytes.NewBuffer(make([]byte, 1024))

// Read the file in and parse out what we need
for {
if part, prefix, err = reader.ReadLine(); err != nil {
break
}

buffer.Write(part)
if !prefix {
line := buffer.String()
if(strings.Contains(line, "v ")) {
Verts = append(Verts, parseVertex(line))
} else if(strings.Contains(line, "vt ")) {
Texs = append(Texs, parseTexCoord(line))
} else if(strings.Contains(line, "f ")) {
Faces = append(Faces, parseFace(line, Verts, Texs))
} else if(strings.Contains(line, "mtllib ")) {
mtlName := strings.Split(line, " ")[1]
if mtlFile, err = os.Open(mtlName); err != nil {
fmt.Printf("--"+FgRed+"Failed to find material file: %s\n"+Reset, mtlName)
parseMaterial = false
} else {
parseMaterial = true
}
}
buffer.Reset()
}
}

if err == io.EOF {
err = nil
}

objFile.Close()

// Write out the data
writer.WriteString("{\"obj\":[\n");

// Write out the verts
writer.WriteString("{\"vrt\":[\n");
for i, vert := range Verts {
writer.WriteString(vert.String())
if i < len(Verts) - 1 { writer.WriteString(",") }
writer.WriteString("\n")
}

// Write out the faces
writer.WriteString("],\"fac\":[\n")
for i, face := range Faces {
writer.WriteString(face.String(true))
if i < len(Faces) - 1 { writer.WriteString(",") }
writer.WriteString("\n")
}

// Write out the normals
writer.WriteString("],\"nrm\":[")
for i, face := range Faces {


writer.WriteString("[")
for j, vert := range face.verts {
length := math.Sqrt((vert.X * vert.X) + (vert.Y * vert.Y) + (vert.Z * vert.Z))
x := vert.X / length
y := vert.Y / length
z := vert.Z / length
normal := fmt.Sprintf("[%f,%f,%f]", x, y, z)
writer.WriteString(normal)
if(j < len(face.verts)-1) { writer.WriteString(",") }
}
writer.WriteString("]")




//writer.WriteString("[0, 1, 0]")
if i < len(Faces) - 1 { writer.WriteString(",") }
writer.WriteString("\n")
}

// Write out the tex coords
writer.WriteString("],\"tex\":[")
for i, face := range Faces {
writer.WriteString("[")
writer.WriteString(face.tex[0].String())
writer.WriteString(",")
writer.WriteString(face.tex[1].String())
writer.WriteString(",")
writer.WriteString(face.tex[2].String())
writer.WriteString("]")
if i < len(Faces) - 1 { writer.WriteString(",") }
writer.WriteString("\n")
}

// Close obj block
writer.WriteString("]}]");

if parseMaterial {
writer.WriteString(",mat:[{");
reader := bufio.NewReader(mtlFile)

// Read the file in and parse out what we need
for {
if part, prefix, err = reader.ReadLine(); err != nil {
break
}

buffer.Write(part)
if !prefix {
line := buffer.String()
if(strings.Contains(line, "map_Kd ")) {
parts := strings.Split(line, " ")
entry := fmt.Sprintf("\"t\":\"%s\",", parts[1])
writer.WriteString(entry)

width, height := 256, 256
var imageFile *os.File
if imageFile, err = os.Open(parts[1]); err != nil {
fmt.Printf("--"+FgRed+"Failed to find %s, defaulting to 256x256"+Reset+"\n", parts[1])
return
} else {
var config image.Config
imageReader := bufio.NewReader(imageFile)
config, err = jpeg.DecodeConfig(imageReader)
width, height = config.Width, config.Height
fmt.Printf("--"+FgGreen+"Verifing"+Reset+" that %s is %dpx x %dpx\n", parts[1], width, height)
}

size := fmt.Sprintf("\"w\":%d,\"h\":%d,", width, height)
writer.WriteString(size)

} else if(strings.Contains(line, "Kd ")) {
parts := strings.Split(line, " ")
entry := fmt.Sprintf("\"r\":%s, \"g\":%s, \"b\":%s,", parts[1], parts[2], parts[3])
writer.WriteString(entry)
}
buffer.Reset()
}
}

if err == io.EOF {
err = nil
}

writer.WriteString("\"res\":100,\"uv\":true}]");
}

// Close json
writer.WriteString("}");
writer.Flush()
jsonFile.Close()

fmt.Printf("--"+FgGreen+"Exported"+Reset+" %d faces with %d verticies\n", len(Faces), len(Verts))

finished <- -1
}

func main(){
// Verify we were called correctly
if len(os.Args) < 2 {
fmt.Println("Usage: go run objParser.go <OBJ File>");
return
}

files := len(os.Args)
finished := make(chan int)

now := time.Now()

for i := 1; i < files; i++ {
go parseFile(os.Args[i], finished)
}

for i := 1; i < files; i++ {
<- finished
}

fmt.Printf("Parsed %d files in %s\n", files-1, time.Since(now))
}

最佳答案

您应该将 GOMAXPROCS 环境变量设置为可用处理器的最大数量。或者使用函数 GOMAXPROCS在执行时。

关于multithreading - 使用 Goroutine 实际上需要更长的时间来执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12482910/

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