资源简介

经典的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);

 

评论

共有 条评论