GoLang程序在使用GOMAXPROCS(4)时仍然在单个线程上执行。

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

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 (
	&quot;fmt&quot;
	&quot;runtime&quot;
	&quot;time&quot;
)

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 := &amp;men[id]
	for {
		runtime.Gosched()
		for j := guy.cur_num + 1; j &lt; N; j++ {
			guy.cur_num = j
			girl := &amp;women[guy.pref[guy.cur_num]]
			girl.phone &lt;- guy.id
			msg := &lt;-guy.phone
			if msg == 1 {
				guy.cur_eng = guy.pref[guy.cur_num]
				break
			}
		}
		select {
		case &lt;-guy.phone:
			guy.cur_eng = -1
		}
	}
}

func woman(id int, termi chan bool) {
	girl := &amp;women[id]
	for {

		runtime.Gosched()
		select {
		case msg := &lt;-girl.phone:
			if msg &gt;= 0 {
				if girl.cur_eng == -1 {
					men[msg].phone &lt;- 1
					girl.cur_eng = msg
					termi &lt;- true
				} else if girl.pref[girl.cur_eng] &lt; girl.pref[msg] {
					men[msg].phone &lt;- 0
				} else {
					men[msg].phone &lt;- 1
					men[girl.cur_eng].phone &lt;- -10
					girl.cur_eng = msg
				}
			}
		}
	}
}

func main() {
	runtime.GOMAXPROCS(8)
	for i := 0; i &lt; N; i++ {
		men[i] = human{pref: [N]int{}, phone: make(chan int), cur_eng: -1, cur_num: -1, id: i}
		for j := 0; j &lt; N; j++ {
			fmt.Scanf(&quot;%d\n&quot;, &amp;(men[i].pref[j]))
		}
	}
	for i := 0; i &lt; N; i++ {
		women[i] = human{pref: [N]int{}, phone: make(chan int), cur_eng: -1, cur_num: -1, id: i}
		for j := 0; j &lt; N; j++ {
			t := 0
			fmt.Scanf(&quot;%d\n&quot;, &amp;t)
			women[i].pref[t] = j
		}
	}
	termi := make(chan bool)
	for i := 0; i &lt; N; i++ {
		go man(i)
		go woman(i, termi)
	}
	for i := 0; i &lt; N; i++ {
		&lt;-termi
	}
	time.Sleep(100 * time.Millisecond)
	for i := 0; i &lt; N; i++ {
		fmt.Printf(&quot;%d %d\n&quot;, 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).

huangapple
  • 本文由 发表于 2015年11月26日 18:28:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/33936193.html
匿名

发表评论

匿名网友

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

确定