英文:
GoLang program executing on single thread even with GOMAXPROCS(4)
问题
在下面的GoLang程序中,我正在尝试为N个男人和N个女人实现稳定婚姻问题,使用2*N个goroutine(每个男人和女人一个)。
该程序紧密遵循程序定义,因为每个goroutine(读作“每个男人”)通过通道向所需的女人goroutine发送消息,女人goroutine会拒绝/接受他的提议。我期望该程序在设置runtime.GOMAXPROCS(4)
后可以轻松地在多个线程上调度,但它仍然以(几乎)相同的时间运行(运行Linux命令time
仍然显示CPU使用率为100%
,而不是预期的400%
)
package main
import (
"fmt"
"runtime"
"time"
)
const N = 500
type human struct {
pref [N]int
phone chan int
cur_eng int
cur_num int
id int
}
var men = [N]human{}
var women = [N]human{}
func man(id int) {
guy := &men[id]
for {
runtime.Gosched()
for j := guy.cur_num + 1; j < N; j++ {
guy.cur_num = j
girl := &women[guy.pref[guy.cur_num]]
girl.phone <- guy.id
msg := <-guy.phone
if msg == 1 {
guy.cur_eng = guy.pref[guy.cur_num]
break
}
}
select {
case <-guy.phone:
guy.cur_eng = -1
}
}
}
func woman(id int, termi chan bool) {
girl := &women[id]
for {
runtime.Gosched()
select {
case msg := <-girl.phone:
if msg >= 0 {
if girl.cur_eng == -1 {
men[msg].phone <- 1
girl.cur_eng = msg
termi <- true
} else if girl.pref[girl.cur_eng] < girl.pref[msg] {
men[msg].phone <- 0
} else {
men[msg].phone <- 1
men[girl.cur_eng].phone <- -10
girl.cur_eng = msg
}
}
}
}
}
func main() {
runtime.GOMAXPROCS(8)
for i := 0; i < N; i++ {
men[i] = human{pref: [N]int{}, phone: make(chan int), cur_eng: -1, cur_num: -1, id: i}
for j := 0; j < N; j++ {
fmt.Scanf("%d\n", &(men[i].pref[j]))
}
}
for i := 0; i < N; i++ {
women[i] = human{pref: [N]int{}, phone: make(chan int), cur_eng: -1, cur_num: -1, id: i}
for j := 0; j < N; j++ {
t := 0
fmt.Scanf("%d\n", &t)
women[i].pref[t] = j
}
}
termi := make(chan bool)
for i := 0; i < N; i++ {
go man(i)
go woman(i, termi)
}
for i := 0; i < N; i++ {
<-termi
}
time.Sleep(100 * time.Millisecond)
for i := 0; i < N; i++ {
fmt.Printf("%d %d\n", i, men[i].cur_eng)
}
}
编辑:我制作的程序的串行实现在这里。时间比较显示两者几乎以相同的时间运行(串行为1.27秒,上述程序为1.30秒)。
此外,对于并行实现,我按照这里的理解进行了算法设计(由于不知道如何使用MPI,所以我使用了goroutine)。如果可能,请随时提出替代实现(并行)的建议。
上述程序需要以下输入文件:https://drive.google.com/file/d/0B6jsnt965ZwrWlV1OE9LLVA1LUk/view?usp=sharing
英文:
In the following GoLang program, I am trying to implement the stable marriage problem for N men and N women, using 2*N goroutines (1 for each man and woman).
The program closely follows the program definition as each goroutine (read "each man") sends a message via channel to the desired woman goroutine who in turn rejects/accepts his proposal. I expected the program to easily be scheduled on multiple threads on setting runtime.GOMAXPROCS(4)
however it still runs in (almost) the exact same time (and running linux command time
still shows CPU usage at 100%
instead of expected 400%
)
package main
import (
"fmt"
"runtime"
"time"
)
const N = 500
type human struct {
pref [N]int
phone chan int
cur_eng int
cur_num int
id int
}
var men = [N]human{}
var women = [N]human{}
func man(id int) {
guy := &men[id]
for {
runtime.Gosched()
for j := guy.cur_num + 1; j < N; j++ {
guy.cur_num = j
girl := &women[guy.pref[guy.cur_num]]
girl.phone <- guy.id
msg := <-guy.phone
if msg == 1 {
guy.cur_eng = guy.pref[guy.cur_num]
break
}
}
select {
case <-guy.phone:
guy.cur_eng = -1
}
}
}
func woman(id int, termi chan bool) {
girl := &women[id]
for {
runtime.Gosched()
select {
case msg := <-girl.phone:
if msg >= 0 {
if girl.cur_eng == -1 {
men[msg].phone <- 1
girl.cur_eng = msg
termi <- true
} else if girl.pref[girl.cur_eng] < girl.pref[msg] {
men[msg].phone <- 0
} else {
men[msg].phone <- 1
men[girl.cur_eng].phone <- -10
girl.cur_eng = msg
}
}
}
}
}
func main() {
runtime.GOMAXPROCS(8)
for i := 0; i < N; i++ {
men[i] = human{pref: [N]int{}, phone: make(chan int), cur_eng: -1, cur_num: -1, id: i}
for j := 0; j < N; j++ {
fmt.Scanf("%d\n", &(men[i].pref[j]))
}
}
for i := 0; i < N; i++ {
women[i] = human{pref: [N]int{}, phone: make(chan int), cur_eng: -1, cur_num: -1, id: i}
for j := 0; j < N; j++ {
t := 0
fmt.Scanf("%d\n", &t)
women[i].pref[t] = j
}
}
termi := make(chan bool)
for i := 0; i < N; i++ {
go man(i)
go woman(i, termi)
}
for i := 0; i < N; i++ {
<-termi
}
time.Sleep(100 * time.Millisecond)
for i := 0; i < N; i++ {
fmt.Printf("%d %d\n", i, men[i].cur_eng)
}
}
EDIT: The serial implementation of the program I made is here. The time comparison shows both running in almost identical time (1.27s for serial, 1.30s for above one).
Also, the algorithm followed for the parallel implementation was made according to this as well as I could understand (I used goroutines as I didn't know how to use MPI).
Please feel free to suggest an alternative implementation (parallel) if possible.
The program above needs the following as input file : https://drive.google.com/file/d/0B6jsnt965ZwrWlV1OE9LLVA1LUk/view?usp=sharing
答案1
得分: 2
我认为您提供的输入文件需要花费相当长的时间才能被程序读取(通过每行的scanf)。
英文:
I think the input file you provided would take that much time to be read by the program(via scanf per line).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论