我正在为我的并行课程做一个小项目,我尝试了使用带缓冲通道、无缓冲通道、使用指向切片的指针的无缓冲通道等。此外,我还尝试尽可能优化它(不是当前状态),但我仍然得到相同的结果:增加goroutine的数量(甚至是1个)会降低整个程序的运行速度,有人能告诉我我做错了什么吗?在这种情况下,并行性增强是可能的吗?
下面是部分代码:
func main() {
rand.Seed(time.Now().UnixMicro())
numAgents := 2
fmt.Println("Please pick a number of goroutines: ")
fmt.Scanf("%d", &numAgents)
numFiles := 4
fmt.Println("How many files do you want?")
fmt.Scanf("%d", &numFiles)
start := time.Now()
numAssist := numFiles
channel := make(chan []File, numAgents)
files := make([]File, 0)
for i := 0; i < numAgents; i++ {
if i == numAgents-1 {
go generateFiles(numAssist, channel)
} else {
go generateFiles(numFiles/numAgents, channel)
numAssist -= numFiles / numAgents
}
}
for i := 0; i < numAgents; i++ {
files = append(files, <-channel...)
}
elapsed := time.Since(start)
fmt.Printf("Function took %s\n", elapsed)
}
func generateFiles(numFiles int, channel chan []File) {
magicNumbersMap := getMap()
files := make([]File, 0)
for i := 0; i < numFiles; i++ {
content := randElementFromMap(&magicNumbersMap)
length := rand.Intn(400) + 100
hexSlice := getHex()
for j := 0; j < length; j++ {
content = content + hexSlice[rand.Intn(len(hexSlice))]
}
hash := getSHA1Hash([]byte(content))
file := File{
content: content,
hash: hash,
}
files = append(files, file)
}
channel <- files
}
我们的期望是通过增加goroutine的数量程序会运行得更快,但是当goroutine的数量达到一定值时,我会得到相同的执行时间或者稍微慢一点.
编辑:使用的所有函数:
import (
"crypto/sha1"
"encoding/base64"
"fmt"
"math/rand"
"time"
)
type File struct {
content string
hash string
}
func getMap() map[string]string {
return map[string]string{
"D4C3B2A1": "Libcap file format",
"EDABEEDB": "RedHat Package Manager (RPM) package",
"4C5A4950": "lzip compressed file",
}
}
func getHex() []string {
return []string{
"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "A", "B",
"C", "D", "E", "F",
}
}
func randElementFromMap(m *map[string]string) string {
x := rand.Intn(len(*m))
for k := range *m {
if x == 0 {
return k
}
x--
}
return "Error"
}
func getSHA1Hash(content []byte) string {
h := sha1.New()
h.Write(content)
return base64.URLEncoding.EncodeToString(h.Sum(nil))
}
1条答案
按热度按时间kpbwa7wx1#
简单地说-文件生成代码并不复杂到足以证明并行执行的合理性。所有的上下文切换和通过通道移动数据吃掉了并行处理的所有好处。
如果你在
generateFiles
函数的循环中加入类似time.Sleep(time.Millisecond * 10)
的东西,就好像它在做一些更复杂的事情一样,你会看到你所期望的结果--更多的goroutine运行得更快,但是同样,只有到了一定程度,额外的并行处理工作会超过好处。还要注意程序最后一位的执行时间:
直接取决于goroutine的数量,因为所有的goroutine几乎同时完成,所以这个循环几乎不会和你的工作线程并行执行,它运行的时间只是简单地加到总时间上。
接下来,当您多次追加
files
切片时,它必须增长几倍并将数据复制到新位置,您可以通过最初创建一个切片来填充所有结果元素(幸运的是,您确切地知道需要多少)来避免这种情况。