我正在使用 MPI 进行练习,以按照本指令中的类似步骤计算分布在几个不同文件中的单词的频率。
但是我在第 2 步遇到了一个问题。在我的实现中,我首先根据单词的哈希码将本地计数的单词计数对发送到相应的处理器中。同时,每个处理器可能需要接收从其他处理器发送的字数对。因此,一个处理器必须同时发送和接收。
例如:
在处理器 1 中,有字数对:
猫:3
狗:4
狐狸:2
在处理器 2 中,有字数对:
鹿:2
猫:2
狐狸:1
红色:3
等等。假设单词“cat”被计算发送到处理器 2,单词“deer”、“fox”、“red”应该被发送到处理器 1。所以每个处理器的伪代码将是:
for each word-count pair:
compute the word hash code
MPI_Issend it to corresponding processor according to the hash code
while (true):
MPI_Recv word-count pair
combine the counts of the same word in this processor
MPI_Waitall
Do some other things
注意第二个循环永远不会停止,所以我需要添加一个终止条件。我实现这一点的方法是从管理处理器发送一个等级为 0 的信号到每个工作处理器。所以第二个循环变成:
while (true):
MPI_Recv word-count pair
determine sender from the receive status
if (sender != manager)
combine the counts of the same word in this processor
else
break
但是这个算法被证明是不稳定的。虽然它在大多数运行中都会得到预期的结果,但它可能会陷入死锁。我对失败的猜测是,一些工作人员可能在收到来自其他工作处理器的所有字数对之前过早地收到了来自管理器的终止信号,因此来自这些工作人员的相应 MPI_Issend 将不得不无限期地等待,从而出现死锁。
我希望有人可以对我的实施提出一些改进建议。或者,如果有人对此步骤有更好的算法,那也将不胜感激!感谢您的关注!
更新:
为了防止经理在任何工作人员完成接收字数对之前发送终止信号,我总结了洗牌阶段涉及的所有处理器的总字数,比如。然后,每次处理器收到一个字数对时,它也应该向管理器发送一个信号。因此,在管理器部分,添加了一个循环来接收这些信号,以便管理器仅在工作人员接收到所有字数对时才发送终止信号。这样一来,manager 信号就不会被 worker 发送的内容打断,因此 worker 中的 recv 循环可以正确终止。下面是最终修改后的伪代码:
Manager Part:
for (i = 1 : N)
MPI_Recv signal with tag "recvd"
MPI_Send termination signal to all processors involved in the shuffle stage
Worker Part:
for each word-count pair:
compute the word hash code
MPI_Issend it to corresponding processor according to the hash code
while (true):
MPI_Recv word-count pair
**MPI_Send signal with tag "recvd" to notify the manager that a wcp is received**
if (sender != manager)
combine the counts of the same word in this processor
else
break
MPI_Waitall
Do some other things
尽管该算法成功运行,但我不确定我是否走在正确的轨道上。我是否过度复杂化了这个问题?