資源簡介
經典的cannon算法,主要用于矩陣相乘的并行求解問題。這個實現簡單易懂,里面有詳細注釋。
代碼片段和文件信息
#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表緩沖區?*/
int?dg?dl?dl2p?sp;????????????/*?dg:總矩陣維數;dl:矩陣塊維數;dl2=dl*dl;p:處理器個數;sp=sqrt(p)?*/
int?my_rank?my_row?my_col;??????/*?my_rank:處理器ID;(my_rowmy_col):處理器邏輯陣列坐標?*/
MPI_Status?status;
/*
?*函數名:?get_index
?*功能:處理器邏輯陣列坐標至rank號的轉換
?*輸入:坐標、邏輯陣列維數
?*輸出:rank號
?*/
int?get_index(int?row?int?col?int?sp)
{
???return?((row+sp)%sp)*sp?+?(col+sp)%sp;
}
/*
?*函數名:random_A_B
?*功能:隨機生成矩陣A和B
?*/
void?random_A_B()
{
???int?ij;
????srand((unsigned?int)time(NULL));?????/*設隨機數種子*/
/*隨機生成AB并初始化C*/
????for(i=0;?i ??????for(j=0;?j ??{
????A[i][j]?=?rand();
????????B[i][j]?=?rand();
????????C[i][j]?=?0.0;
??}
}
/*?函數名:scatter_A_B
?*?功能:rank為0的處理器向其他處理器發送A、B矩陣的相關塊
?*/
void?scatter_A_B()
{
???int?ijkl;
???int?p_iminp_imaxp_jminp_jmax;
???for(k=0;?k
???{
??/*計算相應處理器所分得的矩陣塊在總矩陣中的坐標范圍*/
??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中的相應塊拷至tmp_atmp_b,準備向其他處理器發送*/
??????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的處理器直接將自己對應的矩陣塊從tmp_atmp_b拷至ab*/
??????if(k==0)
??????{
?????????memcpy(a?tmp_a?dl2?*?sizeof(float));
?memcpy(b?tmp_b?dl2?*?sizeof(float));
??????}?else???/*rank=0的處理器向其他處理器發送tmp_atmp_b中相關的矩陣塊*/
??????{
??????????MPI_Send(tmp_a?dl2?MPI_FLOAT?k?1?MPI_COMM_WORLD);
??MPI_Send(tmp_b?dl2?MPI_FLOAT?k?2?MPI_COMM_WORLD);
??????}
???}
}
/*
?*函數名:init_alignment
?*功能:矩陣A和B初始對準
?*/
void?init_alignment()
{
???/*將A中坐標為(ij)的分塊A(ij)向左循環移動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中坐標為(ij)的分塊B(ij)向上循環移動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)?);
}
/*
?*函數名:main_shift
?*功能:分塊矩陣左移和上移,并計算分塊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);
?
- 上一篇:北京2013-2018年期間空氣質量歷史數據
- 下一篇:數據結構二叉樹家譜管理系統
評論
共有 條評論