多处理器编程的艺术 引言 习题1-8

习题1

哲学家就餐问题是由并发处理的先驱E.W.Dijkstra所提出,主要用于阐述死锁和无饥饿概念。假设五个哲学家一生只在思考和就餐。他们围坐在一个大圆桌旁,桌上有一大盘米饭。然而只有五根可用的筷子。所有的哲学家都在思考。若某个哲学家饿了,则拿起身边的两根筷子。如果他能够拿到这两根筷子,则可以就餐。当这个哲学家吃完后,又放下自己生变的两根筷子。如果他能够拿到这两根筷子,则可以就餐。当这个哲学家吃完后,又放下筷子继续思考。

1. 试编写模仿哲学家就餐行为的程序,其中给每一个哲学家为一个线程而筷子则是共享对象。注意,必须防止出现两个哲学家同时使用一根筷子的情形。

2. 修改所编写的程序,不允许出现死锁情况,也就是说,保证不会出现这样的情况:每个哲学家都已拥有一根筷子,并且在等待获得另一个人手中的筷子。

3. 修改所编写的程序使得不会出现饥饿现象。

4. 编写能够保证任意n个哲学家无饥饿就餐的程序。

解答:

这里筷子属于两个哲学家的共享资源,所以在代码中,定义为全局变量。

之后的思路就简单了,这里的锁相关函数没有实现,这里就当做伪代码来看吧。


一个哲学家需要先看左手边的筷子,当左边的筷子没有人使用时拿起。

右边同理。

这时,哲学家有三个状态。

①没有拿着筷子

②拿到了一根筷子

③幸运的拿到了两根筷子

这时,当处于③状态时,就可以开心的吃米饭了。吃完以后,将筷子放下,让别人使用。

当处于②状态时,一直拿着这根筷子会制造饥饿。所以,在看到只能拿到一只筷子时,就再将它放下,可供其他人使用。

①状态,就只能等两边的人把筷子放下来了。


这个过程应该就能满足以上四个条件了。


int Chopsticks[poilosophers]; //需要提前知道哲学家的人数,用动态数组在指定的初始化函数进行分配也行
void selectChopsticks(int poilosopherId, int poilosophers){
	int l_chopstick = poilosopherId, r_chopstick = poilosopherId + 1;
	if (r_chopstick == poilosophers){
		r_chopstick -= poilosophers; //保证环状
	}

	int getChopstickNum = 0, eated = 0;
	while (1){
		lock();
		if (Chopsticks[l_chopstick] == 0){
			Chopsticks[l_chopstick] = poilosopherId;
		}
		unlock();

		lock();
		if (Chopsticks[r_chopstick] == 0){
			Chopsticks[r_chopstick] = poilosopherId;
		}
		unlock();

		if (Chopsticks[l_chopstick] = poilosopherId && Chopsticks[r_chopstick] == poilosopherId) {
			eated = 1;
		}

		if (Chopsticks[l_chopstick] == poilosopherId){
			Chopsticks[l_chopstick] = 0;
		}

		if (Chopsticks[r_chopstick] == poilosopherId){
			Chopsticks[r_chopstick] = 0;
		}

		if (eated) break;
	}
}

习题2

下面各种方法满足安全性还是活性?指出所关心的“坏事”和“好事”。

1. 按到达顺序为赞助人服务。

2. 升上去的东西必须降下来。

3. 如果有两个或多个进程在等待进入自己的临界区,则至少有一个会成功。

4. 如果发生一个中断,则在一秒内输出一条信息。

5. 如果发生一个中断,则要输出一条信息。

6.生活费决不下降

7. 有两件事是肯定的:死亡和税

8.你总是能够告诉一个哈佛人。

解答:

1.活性,好事

2.活性,好事

3.活性,好事

4.安全性,坏事

5.活性,好事

6.安全性,坏事

7.活性,好事

8.活性,好事

这里…… 是我自行判断的,不确保正确性。翻译是没有问题的,这里可能是对一些假设做一些属性上判断。


习题3

在生产者-消费者问题中,假设Bob能够看到Alice窗台上的啤酒罐是竖直还是翻倒的。请基于啤酒罐-绳子协议来设计一种生产者-消费者协议,使得即使Bob无法看到Alice窗台上啤酒罐的状态,也能够正常工作(即实际中断位是如何工作的)。

解答:

因为没有办法看到啤酒罐的状态,所以无法判断宠物是否在院中。

不过,这里Bob肯定能看到食物槽中是否有食物。


所以,这里需要Bob依次做下面的事情:

①窗口看食物槽中是否还有食物

是:②  否:③

②进入院子,向食物槽中添加食物

③做会儿自己想做的事情,比如:看会电视。

④10~20分钟后,再做①


Alice同样需要做一些事情:

①检查食物是否吃完

是:②   否:③

②将宠物们召唤回屋,过一段时间再做①

③自行决定是否叫宠物们回屋,过段时间再做①


这里食物槽就是中断位,两人通过食物槽来决定自己的动作,从而避免书中提到的一些人与动物的冲突。


习题4

假如你是最近被捕的P个囚犯之一。监狱长是一个疯狂的计算机科学家,他给出了一下告示:

你们今天可以在一起商量一个策略,但是从今天之后,你们将会被隔开,关在不同的房间,互相间无法再进行交流。

我们已建造了一种“开关房间”,里面有一个灯开关,这个开关只能为开或关,且没有和任何东西相连。

我将不时的从你们中间随机选择一位到“开关房间”里来。这名囚犯可以拨动开关(从开到关,或相反),也可保持开关的状态不变。其他人这是都不能进入房间。

每一名囚犯都将任意多次地进入开关房间。更确切的说,对于任意的N,你们中的每个人最终至少能进入这个房间N次。

任何时刻,任意一名囚犯都可以宣布:"我们所有的人都已经至少到过开关房间一次了。"如果该断言是对的,我将释放你们。如果错了,我就把你们全部送去喂鳄鱼。谨慎抉择吧!

(1)在开关初始状态为 关 的情况下,设计一个可以成功取胜的策略。

(2)在不知道开关初始状态的情况下,设计一个可以成功取胜的策略。

解答:

其实①就是一个特解,这里将两个方式结合在一起来说。

这里,可以由第一个进入房间的人进行统计。

但这里就有个问题,如何确定这第一个人是谁?这个很难确定。

不过问题并非无解,在一天商量的时间内,我们大家定了了协议:

①在看到开关屋开关为 关 的状态时,开始计数。

②在第一次看到开关为 开 的状态时,拨动,将其换为 关。

③当其中某人计数达到P时,召唤监狱长。


在(1)中,因为我们知道初始状态为关,直接满足我们的协议。

而(2)中,我们则需要考虑开的情况,从而确定第一个人。


当初始状态为开时,第一个进去的人会将其关闭,第二个人进去时的情况就是①的情况了。

感觉也没有什么难得,就是获得释放的时间可能要迟一些了。


类似的问题还有很多有趣的讨论,有兴趣的同学可以去这些地方看看:

http://tieba.baidu.com/p/625765933

100个囚犯和灯泡的那些事儿


习题5

上题中的监狱长又有了另外一个想法。他命令囚犯站成一排,每个人都戴一顶红色或蓝色的帽子。没有人知道自己所戴帽子的颜色,也不知道他后面所有人帽子的颜色,但能看到前面所有人帽子的颜色。监狱长从队伍的后面开始询问每个囚犯,让他们猜测自己帽子的颜色。囚犯们只能回答“红色”或“蓝色”。如果他打错了,就会送去喂鳄鱼。如果他答对了,则会释放。每个囚犯都能听到后面所有人的回答,但不知道答案是否正确。

囚犯们在站队只前可以商讨一个策略(监狱长是听着的)。一旦站好队之后,每个人除了能回答“红色”和“蓝色”以外,再无法以任何形式进行交流。

设计一个能够保证P个囚犯中至少有P-1个会释放的策略。

解答:

第一眼看到这个题,就想起看耶鲁的博弈课中的那个场景,不过对比本题来说是两个问题。

这个题着实难解…… 我也是查了很多资料才找到一个符合题目的算法。


一下就来说说这个算法:

因为能听到后面人的回答,并能看到前面人头上帽子的颜色。

这样的话,可以通过帽子的奇偶性来进行解决。

在商量的时候,我们建立这样协议:

①数出自己前面带蓝帽子人的数量(为B)

②记住自己后面人回答“蓝色”的数量(为b)

③将B与b进行加和。和为偶数的时候,回答“蓝色”;和为奇数的时候,回答“红色”。


表达式也写一下:

B = blueAhead = 前面带蓝帽子的数量

b = blueBehind = 后面回答“蓝色”的数量

if  B + b 是偶数:

    回答 "蓝色"

else 

    回答 “红色”


这里验证一下,举个两个例子:

这里用“颜色-序号”来代表一个囚徒的帽子颜色和提问顺序(从小到大)

【红-0 】【蓝-1】【 红-2】【 红-3】【 蓝-4】【 红-5】【蓝-6】【蓝-7】 

0)4 + 0 = 4:蓝(死亡)

1)3 + 1 = 4:蓝(存活)

2)3 + 2 = 5:红(存活)

3)3 + 2 = 5:红(存活)

4)2 + 2 = 4:蓝(存活)

5)2 + 3 = 5:红(存活)

6)1 + 3 = 4:蓝(存活)

7)0 + 4 = 4:蓝(存活)

共8人,存活7人。

②下面多加几个人,看看结果

【红-0 】【蓝-1】【 红-2】【 红-3】【 蓝-4】【 红-5】【蓝-6】【蓝-7】 【红-8】【红-9】【蓝-10】

0)5 + 0 = 5:红(存活)

1)4 + 0 = 4:蓝(存活)

2)4 + 1 = 5:红(存活)

3)4 + 1 = 5:红(存活)

4)3 + 1 = 4:蓝(存活)

5)3 + 2 = 5:红(存活)

6)2 + 2 = 4:蓝(存活)

7)1 + 3 = 4:蓝(存活)

8)1 + 4 = 5:红(存活)

9)1 + 4 = 5:红(存活)

10) 0 + 4 = 4:蓝(存活)

共10人,存活10人。


有兴趣的同学可以去这里看看:

how-many-of-a-hundred-hatted-prisoners-can-save-themselves-from-the-king


习题6

使用Amdahl定律解决下面问题:

①假定在一个程序中包含有一个无法并行化的方法M,其执行时间该为程序总时间的40%,若在一台n处理器的多核机器上运行此程序,总加速比的上限应为多少?

②假定方法M占整个程序执行时间的30%。要使程序的总运行时间比原来提高2倍,M的加速比应为多少?

③假定方法M的速度可以提高3倍。要使程序的总加速比为原来的2倍,那么在程序的总运行时间中,M应占多大的比例?

解答:

①S = 1/(0.4 + 0.6/n) = n/(0.4n + 0.6),当n趋近与无穷,S = 1/0.4 = 2.5。所以,上限为2.5

②这个应该是用加速比来反推p的值,然后再对M的加速比进行计算。

将原式变形,得p =[(1-S)n]/[(1-n)S]。

带入S=2,得p = n/[2(n -1)] => 1-p = (n - 2)/[2(n-1)]。

这时计算出在新程序中M的运行时间为 1/2 * (1 - p) = (n - 2)/ [4(n - 1)]

计算加速比P =0.3/(1-p) = [6(n-2)]/[5(n-1)]。

当n趋近于无穷时,P=1.2

③这里我假设原始程序执行的时间是1,也就是M没有提高3倍前,然后加速比就是1.

当M提速3倍后,程序执行的时间是1/2,加速比也就是2了。

根据定律可得 2 = 1 / (1-p'+p'/n)=>p'=n/[2(n-1)]。

当n趋近于无穷时,p'=0.5

也就是M应占50%的比例。


以下是我找到的一些参考资料,因为没有看太懂batch那个,所以不确定,这里的回答是否正确。

无论正确与否吧,希望能给其他同学提供一个思路。

https://github.com/schuay/advanced_multiprocessor_programming/blob/master/exercises_batch_1/exercises.tex

https://groups.google.com/forum/#!topic/art-of-multiprocessor-programming/adGb3ifKNXI


习题7

在两个处理器上运行时,程序可获得加速比为S2。使用Amdahl定律推导出在n个处理器上运行时程序的加速比Sn,要求用n和S2来表示。

解答:

这里根据S2反推p,然后再计算Sn。

S2 =   1/(1-p+p/2) => p = 2(1-1/S2)

总时间T = 1 - p + p/n = 1 - p(1 - 1/n) = 1 - 2(1-1/S2)(1-1/n)

因为Sn = 1/T,所以Sn = 1 / [1 - 2(1-1/S2)(1-1/n)]


习题8

现有一台每秒可执行5亿万条指令的单处理器和一台有10个处理器的多处理器机器,其中每个处理器每秒可执行1亿万条指令。针对一个特定的应用,使用Amdahl定律来解释应该购买哪台机器。

解答:

对Amdahl定律进行变形,S = 1 / (1 - p + p/n) = 1 / [1 - p(1 - 1/n)]。

从这个等式中可以看出来,加速比与p有绝对的关系。

当p趋近与0时,其加速比就为1,也就是没有任何加速

当p趋近于1时,其加速比就是n,完全进行并行加速。

具体的例子可以参考书中粉刷房屋的例子。


不过,在这个题目中,再完全并行的情况下,其能执行的指令数并不一样。

那这里就需要有个讨论:

①10个处理器不完全使用的情况

②应用的指令数小于5亿万条。

这里②的情况比较简单,这里p无论是多少,我都会选择第一台机器。

而①的情况就有些复杂,根据等式其依旧有加速比(这里不去分割1s内具体指令的执行情况),也就是肯定要比第一台机器用的时间少。

所以,应该还会选择第二台机器。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值