資源簡(jiǎn)介
經(jīng)典的cannon算法,主要用于矩陣相乘的并行求解問(wèn)題。這個(gè)實(shí)現(xiàn)簡(jiǎn)單易懂,里面有詳細(xì)注釋。
代碼片段和文件信息
#include?
#include?
#include?
#include?
#include?
#include?
/*?全局變量聲明?*/
float?**A?**B?**C;??????????????/*?總矩陣C?=?A?*?B?*/
float?*a?*b?*c?*tmp_a?*tmp_b;?/*?a、b、c表分塊,tmp_a、tmp_b表緩沖區(qū)?*/
int?dg?dl?dl2p?sp;????????????/*?dg:總矩陣維數(shù);dl:矩陣塊維數(shù);dl2=dl*dl;p:處理器個(gè)數(shù);sp=sqrt(p)?*/
int?my_rank?my_row?my_col;??????/*?my_rank:處理器ID;(my_rowmy_col):處理器邏輯陣列坐標(biāo)?*/
MPI_Status?status;
/*
?*函數(shù)名:?get_index
?*功能:處理器邏輯陣列坐標(biāo)至rank號(hào)的轉(zhuǎn)換
?*輸入:坐標(biāo)、邏輯陣列維數(shù)
?*輸出:rank號(hào)
?*/
int?get_index(int?row?int?col?int?sp)
{
???return?((row+sp)%sp)*sp?+?(col+sp)%sp;
}
/*
?*函數(shù)名:random_A_B
?*功能:隨機(jī)生成矩陣A和B
?*/
void?random_A_B()
{
???int?ij;
????srand((unsigned?int)time(NULL));?????/*設(shè)隨機(jī)數(shù)種子*/
/*隨機(jī)生成AB并初始化C*/
????for(i=0;?i ??????for(j=0;?j ??{
????A[i][j]?=?rand();
????????B[i][j]?=?rand();
????????C[i][j]?=?0.0;
??}
}
/*?函數(shù)名:scatter_A_B
?*?功能:rank為0的處理器向其他處理器發(fā)送A、B矩陣的相關(guān)塊
?*/
void?scatter_A_B()
{
???int?ijkl;
???int?p_iminp_imaxp_jminp_jmax;
???for(k=0;?k
???{
??/*計(jì)算相應(yīng)處理器所分得的矩陣塊在總矩陣中的坐標(biāo)范圍*/
??p_jmin?=?(k?%?sp????)?*?dl;
?? ??p_jmax?=?(k?%?sp?+?1)?*?dl-1;
??p_imin?=?(k?-?(k?%?sp))/sp?*?dl;
??p_imax?=?((k?-?(k?%?sp))/sp?+1)?*dl?-1;
??????l?=?0;
??????/*rank=0的處理器將AB中的相應(yīng)塊拷至tmp_atmp_b,準(zhǔn)備向其他處理器發(fā)送*/
??????for(i=p_imin;?i<=p_imax;?i++)
??????{
?????? ??for(j=p_jmin;?j<=p_jmax;?j++)
?????? ??{
??????????????tmp_a[l]?=?A[i][j];
??????tmp_b[l]?=?B[i][j];
??????l++;
??????????}
??????}
??????/*rank=0的處理器直接將自己對(duì)應(yīng)的矩陣塊從tmp_atmp_b拷至ab*/
??????if(k==0)
??????{
?????????memcpy(a?tmp_a?dl2?*?sizeof(float));
?memcpy(b?tmp_b?dl2?*?sizeof(float));
??????}?else???/*rank=0的處理器向其他處理器發(fā)送tmp_atmp_b中相關(guān)的矩陣塊*/
??????{
??????????MPI_Send(tmp_a?dl2?MPI_FLOAT?k?1?MPI_COMM_WORLD);
??MPI_Send(tmp_b?dl2?MPI_FLOAT?k?2?MPI_COMM_WORLD);
??????}
???}
}
/*
?*函數(shù)名:init_alignment
?*功能:矩陣A和B初始對(duì)準(zhǔn)
?*/
void?init_alignment()
{
???/*將A中坐標(biāo)為(ij)的分塊A(ij)向左循環(huán)移動(dòng)i步*/
???MPI_Sendrecv(a?dl2?MPI_FLOAT?get_index(my_rowmy_col-my_rowsp)?1
????????????tmp_a?dl2?MPI_FLOAT?get_index(my_rowmy_col+my_rowsp)?1?MPI_COMM_WORLD?&status);
???memcpy(a?tmp_a?dl2?*?sizeof(float)?);
???/*將B中坐標(biāo)為(ij)的分塊B(ij)向上循環(huán)移動(dòng)j步*/
???MPI_Sendrecv(b?dl2?MPI_FLOAT?get_index(my_row-my_colmy_colsp)?1
????????????tmp_b?dl2?MPI_FLOAT?get_index(my_row+my_colmy_colsp)?1?MPI_COMM_WORLD?&status);
???memcpy(b?tmp_b?dl2?*?sizeof(float)?);
}
/*
?*函數(shù)名:main_shift
?*功能:分塊矩陣左移和上移,并計(jì)算分塊c
?*/
void?main_shift()
{
???int?ijkl;
???for(l=0;?l ???{
?????/*矩陣塊相乘,c+=a*b?*/
?????for(i=0;?i
???????for(j=0;?j
?????????for(k=0;?k
???????????c[i*dl+j]?+=?a[i*dl+k]*b[k*dl+j];
??????/*?將分塊a左移1位?*/
??????MPI_Send(a??dl2?MPI_FLOAT?get_index(my_row?my_col-1?sp)?1?MPI_COMM_WORLD);
??????MPI_Recv(a??dl2?MPI_FLOAT?get_index(my_row?my_col+1?sp)?1?MPI_COMM_WORLD?&status);
?
評(píng)論
共有 條評(píng)論