Golang 并行化

huangapple go评论94阅读模式
英文:

Golang Parallel

问题

我是你的中文翻译助手,以下是你提供的内容的翻译:

我刚开始学习Golang,试图理解并发和并行。我阅读了下面提到的关于并发和并行的文章,并执行了相同的程序。但是输出结果不同(混合了字母和字符)。看起来并发是正常工作的,但并行没有。

文章中提到要添加**runtime.GOMAXPROCS(4)**来实现并行。

为什么我没有得到并行输出?

我使用的是4核CPU系统和GO的1.8.2版本

https://www.goinggo.net/2014/01/concurrency-goroutines-and-gomaxprocs.html

我知道如果添加Sleep,我可以看到并行输出,根据并发的概念。但是并行性是指如果系统有多个CPU,那么每个线程将在一个CPU上运行,从而成为并行进程。
我的问题是,为什么尽管我的系统有4个核心并且添加了runtime.GOMAXPROCS(4),但我没有得到并行输出。

Go程序

package main

import (
    "fmt"
    "runtime"
    "sync"
)

func main() {
    runtime.GOMAXPROCS(2)

    var wg sync.WaitGroup
    wg.Add(2)

    fmt.Println("Starting Go Routines")
    go func() {
        defer wg.Done()

        for char := 'a'; char < 'a'+26; char++ {
            fmt.Printf("%c ", char)
        }
    }()

    go func() {
        defer wg.Done()

        for number := 1; number < 27; number++ {
            fmt.Printf("%d ", number)
        }
    }()

    fmt.Println("Waiting To Finish")
    wg.Wait()

    fmt.Println("\nTerminating Program")
}

我的输出

Starting Go Routines
Waiting To Finish
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 a
b c d e f g h i j k l m n o p q r s t u v w x y z
Terminating Program

期望的输出(不完全相同,但是并行输出)

Starting Go Routines
Waiting To Finish
a b 1 2 3 4 c d e f 5 g h 6 i 7 j 8 k 9 10 11 12 l m n o p q 13 r s 14
t 15 u v 16 w 17 x y 18 z 19 20 21 22 23 24 25 26
Terminating Program
英文:

I am new to Golang and trying to understand Concurrency and Parallel. I read below mentioned article about Concurrency and Parallel. I have executed same program. But not getting the same ( mixed letter & character ) output. Getting first all letters then characters. it seems like concurrency is working not Parallel is not.

Article says add runtime.GOMAXPROCS(4) to make parallel.

Why I am not getting parallel out ?

I am using 4 core CPU system and GO version 1.8.2

https://www.goinggo.net/2014/01/concurrency-goroutines-and-gomaxprocs.html

I know that if we add Sleep then i can see parallel output, as per Concurrency concept . But Parallelism says if system has more than one CPU, then each thread will run in one CPU and it becomes Parallel process.
My question here is Why I am not getting parallel output though my system has 4 core and added runtime.GOMAXPROCS(4), .

Go Program

package main

import (
    &quot;fmt&quot;
    &quot;runtime&quot;
    &quot;sync&quot;
)

func main() {
    runtime.GOMAXPROCS(2)

    var wg sync.WaitGroup
    wg.Add(2)

    fmt.Println(&quot;Starting Go Routines&quot;)
    go func() {
        defer wg.Done()

        for char := ‘a’; char &lt; ‘a’+26; char++ {
            fmt.Printf(&quot;%c &quot;, char)
        }
    }()

    go func() {
        defer wg.Done()

        for number := 1; number &lt; 27; number++ {
            fmt.Printf(&quot;%d &quot;, number)
        }
    }()

    fmt.Println(&quot;Waiting To Finish&quot;)
    wg.Wait()

    fmt.Println(&quot;\nTerminating Program&quot;)
}

My Output

Starting Go Routines
Waiting To Finish
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 a
b c d e f g h i j k l m n o p q r s t u v w x y z
Terminating Program

Expected Output ( not the same , But Parallel output )

Starting Go Routines
Waiting To Finish
a b 1 2 3 4 c d e f 5 g h 6 i 7 j 8 k 9 10 11 12 l m n o p q 13 r s 14
t 15 u v 16 w 17 x y 18 z 19 20 21 22 23 24 25 26
Terminating Program

答案1

得分: 0

在我看来,这段代码可能存在两个问题。

第一个问题是:

runtime.GOMAXPROCS(2)

使用这行代码,你只允许两个工作线程,但是你启动了三个 Go 协程(主协程占用一个)。但是主要问题是 Go 协程完成得太快了。通过添加

time.Sleep(100000)

可以解决这个问题。

package main

import (
	"fmt"
	"runtime"
	"sync"
	"time"
)

func main() {
	runtime.GOMAXPROCS(3)

	var wg sync.WaitGroup
	wg.Add(2)

	fmt.Println("Starting Go Routines")
	go func() {
		defer wg.Done()
		for char := 'a'; char < 'a'+26; char++ {
			for i := 0; i < 10000; i++ {
				_ = i * 2
			}
			fmt.Printf("%c ", char)
		}
	}()

	go func() {
		defer wg.Done()
		for number := 1; number < 27; number++ {
			for i := 0; i < 10000; i++ {
				_ = i * 2
			}
			fmt.Printf("%d ", number)
		}
	}()

	fmt.Println("Waiting To Finish")
	wg.Wait()

	fmt.Println("\nTerminating Program")
}

在这种情况下,我尝试不使用 sleep 函数,因为它们会改变调度器中的线程状态。我得到了以下结果:

Starting Go Routines
Waiting To Finish
1 2 3 4 a 5 b 6 c d 7 8 e f 9 g h 10 i j 11 k 12 l m 13 n 14 o p q 15 r 16 s 17 t u 18 v 19 w 20 x y 21 z 22 23 24 25 26 
Terminating Program
英文:

In my opinion there are two troubles can be in this code.
First idea:

 runtime.GOMAXPROCS(2)

Using this row you allow only two workers, but you starting three Go Routines (Main takes one).

But the main problem that Go Routines finished too fast. Adding

time.Sleep(100000)

will solve this problem.
package main

import (
	&quot;fmt&quot;
	&quot;runtime&quot;
	&quot;sync&quot;
)

func main() {
	runtime.GOMAXPROCS(3)

	var wg sync.WaitGroup
	wg.Add(2)

	fmt.Println(&quot;Starting Go Routines&quot;)
	go func() {
		defer wg.Done()
		for char := &#39;a&#39;; char &lt; &#39;a&#39;+26; char++ {
			for i := 0; i &lt; 10000; i++ {
				_ = i * 2
			}
			fmt.Printf(&quot;%c &quot;, char)
		}
	}()

	go func() {
		defer wg.Done()
		for number := 1; number &lt; 27; number++ {
			for i := 0; i &lt; 10000; i++ {
				_ = i * 2
			}
			fmt.Printf(&quot;%d &quot;, number)
		}
	}()

	fmt.Println(&quot;Waiting To Finish&quot;)
	wg.Wait()

	fmt.Println(&quot;\nTerminating Program&quot;)
}

In this case I've tried not to use sleep function, because they change thread status in scheduler. And I have this as a result.

Starting Go Routines
Waiting To Finish
1 2 3 4 a 5 b 6 c d 7 8 e f 9 g h 10 i j 11 k 12 l m 13 n 14 o p q 15 r 16    s 17 t u 18 v 19 w 20 x y 21 z 22 23 24 25 26 
Terminating Program

答案2

得分: 0

由于在上面的示例中,for循环的条件是27,程序执行速度很快,无法看到并行性。我编写了一个不同的示例,并增加了条件,然后我可以看到并行输出。

package main

import (
	"fmt"
	"runtime"
	"sync"
)

var wg sync.WaitGroup

func init() {
	fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!", runtime.NumCPU())

}
func main() {
	fmt.Println(" Welcome to concurrency")
	wg.Add(2)
	go one()
	go two()
	fmt.Println("Waiting To Finish")
	wg.Wait()
	fmt.Println("\nTerminating Program")

}

func one() {
	for i := 0; i < 200; i++ {
		fmt.Println("one", i)
	}
	defer wg.Done()
}

func two() {
	for i := 0; i < 200; i++ {
		fmt.Println("Two:", i)
	}
	defer wg.Done()
}

更新于8/28/2015:Go 1.5将默认值GOMAXPROCS设置为与您的计算机上的CPU数量相同。我已删除了runtime.GOMAXPROCS(4)

英文:

Since for loop has condition 27 in my above example, program execution was fast and not able to see parallelism. I have written different example and increased the condition then I could see the Parallel output.

package main

import (
	&quot;fmt&quot;
	&quot;runtime&quot;
	&quot;sync&quot;
)

var wg sync.WaitGroup

func init() {
	fmt.Println(&quot;!!!!!!!!!!!!!!!!!!!!!!!!!!!!&quot;, runtime.NumCPU())

}
func main() {
	fmt.Println(&quot; Welcome to concurrency&quot;)
	wg.Add(2)
	go one()
	go two()
	fmt.Println(&quot;Waiting To Finish&quot;)
	wg.Wait()
	fmt.Println(&quot;\nTerminating Program&quot;)

}

func one() {
	for i := 0; i &lt; 200; i++ {
		fmt.Println(&quot;one&quot;, i)
	}
	defer wg.Done()
}

func two() {
	for i := 0; i &lt; 200; i++ {
		fmt.Println(&quot;Two:&quot;, i)
	}
	defer wg.Done()
}

UPDATE 8/28/2015: Go 1.5 is set to make the default value of GOMAXPROCS the same as the number of CPUs on your machine. I have removed the runtime.GOMAXPROCS(4)

答案3

得分: 0

这是因为你的算法没有进行足够的操作以展现并行性。尝试增加for循环语句的次数,例如。

英文:

That's because your algorithm doesn't do operations enough to allow to see parallelism. Try to raise the number of loops for the for statements, for example.

huangapple
  • 本文由 发表于 2017年8月21日 00:49:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/45784588.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定