FOX算法的MPI实现

2023-11-11

算法描述如下:
将待相乘的矩阵A和B分成p个方块Ai,j和Bi,j(0≤j,i≤√p-1),每块大小为(n/√p)×(n/√p),并将他们分配给√p×/√p,个处理器。开始时处理器Pi,j存放有Ai,j和Bi,j,并负责计算块Ci,j。然后Fox算法执行以下√p次迭代,即可完成:
选中对角块Ai,j,并将其向所在行的√p-1个处理器进行一到多播送;
各处理器将所收到的A阵的块和B阵原有的块进行乘加运算;
*③*B阵的块向上循环1步;
如果Ai,j是本次播送的块,则下次应选块Ai,(j+1)mod√p向同行的√p-1个处理器播送,然后转第②步。
如上所述,算法需要多次用到各种数组,为编程方便,定义如下结构体:
typedef struct {
int n_bar;
#define Order(A) ((A)->n_bar)
float entries[MAX];
#define Entry(A,i,j) ((((A)->entries) + ((A)->n_bar)(i) + (j)))
} LOCAL_MATRIX_T;
同样,由于矩阵划分成子矩阵进行并行相乘时,会用到很多通信子域,这里也定义如下结构体
typedef struct {
int p;
MPI_Comm comm;
MPI_Comm row_comm;
MPI_Comm col_comm;
int q;
int my_row;
int my_col;
int my_rank;
} GRID_INFO_T;
整个算法主要用到读取数据、划分数据、子矩阵运算、写入结果等部分,因此定义如下函数:
LOCAL_MATRIX_T* Local_matrix_allocate(int n_bar);
void Free_local_matrix(LOCAL_MATRIX_T** local_A);
void Read_matrix(char* prompt, LOCAL_MATRIX_T* local_A,
GRID_INFO_T* grid, int n);
void Print_matrix(char* title, LOCAL_MATRIX_T* local_A,
GRID_INFO_T* grid, int n);
void write_matrix(LOCAL_MATRIX_T* local_A,
GRID_INFO_T* grid, int n);
void Set_to_zero(LOCAL_MATRIX_T* local_A);
void Local_matrix_multiply(LOCAL_MATRIX_T* local_A,
LOCAL_MATRIX_T* local_B, LOCAL_MATRIX_T* local_C);
void Build_matrix_type(LOCAL_MATRIX_T* local_A);
MPI_Datatype local_matrix_mpi_t;

LOCAL_MATRIX_T* temp_mat;
void Print_local_matrices(char* title, LOCAL_MATRIX_T* local_A,
GRID_INFO_T* grid);
完整代码如下:

/ fox.c – uses Fox’s algorithm to multiply two square matrices
*
* Created by Wangcan
*/
#include “stdio.h”
#include “mpi.h”
#include “math.h”
#include “stdlib.h”

typedef struct {
int p; /* Total number of processes */
MPI_Comm comm; /* Communicator for entire grid */
MPI_Comm row_comm; /* Communicator for my row */
MPI_Comm col_comm; /* Communicator for my col */
int q; /* Order of grid */
int my_row; /* My row number */
int my_col; /* My column number */
int my_rank; /* My rank in the grid comm */
} GRID_INFO_T;

#define MAX 65536
typedef struct {
int n_bar;
#define Order(A) ((A)->n_bar)
float entries[MAX];
#define Entry(A,i,j) ((((A)->entries) + ((A)->n_bar)(i) + (j)))
} LOCAL_MATRIX_T;
FILE* fp;
/* Function Declarations */
LOCAL_MATRIX_T* Local_matrix_allocate(int n_bar);
void Free_local_matrix(LOCAL_MATRIX_T** local_A);
void Read_matrix(char* prompt, LOCAL_MATRIX_T* local_A,
GRID_INFO_T* grid, int n);
void Print_matrix(char* title, LOCAL_MATRIX_T* local_A,
GRID_INFO_T* grid, int n);
void write_matrix(LOCAL_MATRIX_T* local_A,
GRID_INFO_T* grid, int n);
void Set_to_zero(LOCAL_MATRIX_T* local_A);
void Local_matrix_multiply(LOCAL_MATRIX_T* local_A,
LOCAL_MATRIX_T* local_B, LOCAL_MATRIX_T* local_C);
void Build_matrix_type(LOCAL_MATRIX_T* local_A);
MPI_Datatype local_matrix_mpi_t;

LOCAL_MATRIX_T* temp_mat;
void Print_local_matrices(char* title, LOCAL_MATRIX_T* local_A,
GRID_INFO_T* grid);

/***********************************************/
main(int argc, char* argv[]) {
int p;
int my_rank;
GRID_INFO_T grid;
LOCAL_MATRIX_T* local_A;
LOCAL_MATRIX_T* local_B;
LOCAL_MATRIX_T* local_C;
int n;
int n_bar;
double start,finish,s_t,f_t;

void Setup_grid(GRID_INFO_T*  grid);
void Fox(int n, GRID_INFO_T* grid, LOCAL_MATRIX_T* local_A,
         LOCAL_MATRIX_T* local_B, LOCAL_MATRIX_T* local_C);

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

Setup_grid(&grid);
if (my_rank == 0) {
    printf("What's the order of the matrices?\n");
    scanf("%d", &n);
}

MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
n_bar = n/grid.q;
srand((unsigned) time(NULL));
local_A = Local_matrix_allocate(n_bar);
Order(local_A) = n_bar;
Read_matrix("Enter A", local_A, &grid, n);

// Print_matrix(“We read A =”, local_A, &grid, n);
fp = fopen(“/home/guest/16011011/commonpart/question3/dataInA.txt”,”w”);
write_matrix(local_A,&grid,n);
fclose(fp);

local_B = Local_matrix_allocate(n_bar);
Order(local_B) = n_bar;
Read_matrix("Enter B", local_B, &grid, n);

// Print_matrix(“We read B =”, local_B, &grid, n);
fp = fopen(“/home/guest/16011011/commonpart/question3/dataInB.txt”,”w”);
write_matrix(local_B,&grid,n);
fclose(fp);

Build_matrix_type(local_A);
temp_mat = Local_matrix_allocate(n_bar);

local_C = Local_matrix_allocate(n_bar);
Order(local_C) = n_bar;
start=MPI_Wtime();
Fox(n, &grid, local_A, local_B, local_C);
finish=MPI_Wtime();
MPI_Reduce(&start,&s_t,1,MPI_DOUBLE,MPI_MIN,0,MPI_COMM_WORLD);
MPI_Reduce(&finish,&f_t,1,MPI_DOUBLE,MPI_MIN,0,MPI_COMM_WORLD);
fp = fopen("/home/guest/SC16011011/commonpart/question3/dataOutC.txt","w");
write_matrix(local_C,&grid,n);
fclose(fp);
if(my_rank==0)
    printf("time= %f\n",f_t-s_t);

// Print_matrix(“The product is”, local_C, &grid, n);

Free_local_matrix(&local_A);
Free_local_matrix(&local_B);
Free_local_matrix(&local_C);

MPI_Finalize();

} /* main */

/***********************************************/
void Setup_grid(
GRID_INFO_T* grid /* out */) {
int old_rank;
int dimensions[2];
int wrap_around[2];
int coordinates[2];
int free_coords[2];

/* Set up Global Grid Information */
MPI_Comm_size(MPI_COMM_WORLD, &(grid->p));
MPI_Comm_rank(MPI_COMM_WORLD, &old_rank);

/* We assume p is a perfect square */
grid->q = (int) sqrt((double) grid->p);
dimensions[0] = dimensions[1] = grid->q;

/* We want a circular shift in second dimension. */
/* Don't care about first                        */
wrap_around[0] = wrap_around[1] = 1;
MPI_Cart_create(MPI_COMM_WORLD, 2, dimensions,
    wrap_around, 1, &(grid->comm));
MPI_Comm_rank(grid->comm, &(grid->my_rank));
MPI_Cart_coords(grid->comm, grid->my_rank, 2,
    coordinates);
grid->my_row = coordinates[0];
grid->my_col = coordinates[1];

/* Set up row communicators */
free_coords[0] = 0;
free_coords[1] = 1;
MPI_Cart_sub(grid->comm, free_coords,
    &(grid->row_comm));

/* Set up column communicators */
free_coords[0] = 1;
free_coords[1] = 0;
MPI_Cart_sub(grid->comm, free_coords,
    &(grid->col_comm));

} /* Setup_grid */

/***********************************************/
void Fox(
int n /* in */,
GRID_INFO_T* grid /* in */,
LOCAL_MATRIX_T* local_A /* in */,
LOCAL_MATRIX_T* local_B /* in */,
LOCAL_MATRIX_T* local_C /* out */) {

LOCAL_MATRIX_T*  temp_A; /* Storage for the sub-    */
                         /* matrix of A used during */
                         /* the current stage       */
int              stage;
int              bcast_root;
int              n_bar;  /* n/sqrt(p)               */
int              source;
int              dest;
MPI_Status       status;

n_bar = n/grid->q;
Set_to_zero(local_C);

/* Calculate addresses for circular shift of B */
source = (grid->my_row + 1) % grid->q;
dest = (grid->my_row + grid->q - 1) % grid->q;

/* Set aside storage for the broadcast block of A */
temp_A = Local_matrix_allocate(n_bar);

for (stage = 0; stage < grid->q; stage++) {
    bcast_root = (grid->my_row + stage) % grid->q;
    if (bcast_root == grid->my_col) {
        MPI_Bcast(local_A, 1, local_matrix_mpi_t,
            bcast_root, grid->row_comm);
        Local_matrix_multiply(local_A, local_B,
            local_C);
    } else {
        MPI_Bcast(temp_A, 1, local_matrix_mpi_t,
            bcast_root, grid->row_comm);
        Local_matrix_multiply(temp_A, local_B,
            local_C);
    }
    MPI_Sendrecv_replace(local_B, 1, local_matrix_mpi_t,
        dest, 0, source, 0, grid->col_comm, &status);
} /* for */

} /* Fox */

/***********************************************/
LOCAL_MATRIX_T* Local_matrix_allocate(int local_order) {
LOCAL_MATRIX_T* temp;

temp = (LOCAL_MATRIX_T*) malloc(sizeof(LOCAL_MATRIX_T));
return temp;

} /* Local_matrix_allocate */

/***********************************************/
void Free_local_matrix(
LOCAL_MATRIX_T** local_A_ptr /* in/out */) {
free(*local_A_ptr);
} /* Free_local_matrix */

/***********************************************/
/* Read and distribute matrix:
* foreach global row of the matrix,
* foreach grid column
* read a block of n_bar floats on process 0
* and send them to the appropriate process.
*/
void Read_matrix(
char* prompt /* in */,
LOCAL_MATRIX_T* local_A /* out */,
GRID_INFO_T* grid /* in */,
int n /* in */) {

int        mat_row, mat_col;
int        grid_row, grid_col;
int        dest;
int        coords[2];
float*     temp;
MPI_Status status;

if (grid->my_rank == 0) {
    temp = (float*) malloc(Order(local_A)*sizeof(float));
    printf("%s\n", prompt);
    fflush(stdout);
    for (mat_row = 0;  mat_row < n; mat_row++) {
        grid_row = mat_row/Order(local_A);
        coords[0] = grid_row;
        for (grid_col = 0; grid_col < grid->q; grid_col++) {
            coords[1] = grid_col;
            MPI_Cart_rank(grid->comm, coords, &dest);
            if (dest == 0) {
                for (mat_col = 0; mat_col < Order(local_A); mat_col++)
                   // scanf("%f",
                     //(local_A->entries)+mat_row*Order(local_A)+mat_col);
         *((local_A->entries)+mat_row*Order(local_A)+mat_col)=rand()%10;
            } else {
                for(mat_col = 0; mat_col < Order(local_A); mat_col++)
                    //scanf("%f", temp + mat_col);
    *(temp+mat_col)=rand()%10;
                MPI_Send(temp, Order(local_A), MPI_FLOAT, dest, 0,
                    grid->comm);
            }
        }
    }
    free(temp);
} else {
    for (mat_row = 0; mat_row < Order(local_A); mat_row++)
        MPI_Recv(&Entry(local_A, mat_row, 0), Order(local_A),
            MPI_FLOAT, 0, 0, grid->comm, &status);
}

} /* Read_matrix */

/***********************************************/
void Print_matrix(
char* title /* in */,
LOCAL_MATRIX_T* local_A /* out */,
GRID_INFO_T* grid /* in */,
int n /* in */) {
int mat_row, mat_col;
int grid_row, grid_col;
int source;
int coords[2];
float* temp;
MPI_Status status;

if (grid->my_rank == 0) {
    temp = (float*) malloc(Order(local_A)*sizeof(float));
    printf("%s\n", title);
    for (mat_row = 0;  mat_row < n; mat_row++) {
        grid_row = mat_row/Order(local_A);
        coords[0] = grid_row;
        for (grid_col = 0; grid_col < grid->q; grid_col++) {
            coords[1] = grid_col;
            MPI_Cart_rank(grid->comm, coords, &source);
            if (source == 0) {
                for(mat_col = 0; mat_col < Order(local_A); mat_col++)
                    printf("%4.1f ", Entry(local_A, mat_row, mat_col));
            } else {
                MPI_Recv(temp, Order(local_A), MPI_FLOAT, source, 0,
                    grid->comm, &status);
                for(mat_col = 0; mat_col < Order(local_A); mat_col++)
                    printf("%4.1f ", temp[mat_col]);
            }
        }
        printf("\n");
    }
    free(temp);
} else {
    for (mat_row = 0; mat_row < Order(local_A); mat_row++)
        MPI_Send(&Entry(local_A, mat_row, 0), Order(local_A),
            MPI_FLOAT, 0, 0, grid->comm);
}

} /* Print_matrix */

/***********************************************/
void write_matrix(
LOCAL_MATRIX_T* local_A,/in/
GRID_INFO_T* grid, /in/
int n /in/){
int mat_row, mat_col;
int grid_row, grid_col;
int source;
int coords[2];
float* temp;
MPI_Status status;
if (grid->my_rank == 0) {
temp = (float*) malloc(Order(local_A)*sizeof(float));
for (mat_row = 0; mat_row < n; mat_row++) {
grid_row = mat_row/Order(local_A);
coords[0] = grid_row;
for (grid_col = 0; grid_col < grid->q; grid_col++) {
coords[1] = grid_col;
MPI_Cart_rank(grid->comm, coords, &source);
if (source == 0) {
for(mat_col = 0; mat_col < Order(local_A); mat_col++)
fprintf(fp,”%4.1f “, Entry(local_A, mat_row, mat_col));
} else {
MPI_Recv(temp, Order(local_A), MPI_FLOAT, source, 0,
grid->comm, &status);
for(mat_col = 0; mat_col < Order(local_A); mat_col++)
fprintf(fp,”%4.1f “, temp[mat_col]);
}
}
fprintf(fp,”\n”);
}
free(temp);
} else {
for (mat_row = 0; mat_row < Order(local_A); mat_row++)
MPI_Send(&Entry(local_A, mat_row, 0), Order(local_A),
MPI_FLOAT, 0, 0, grid->comm);
}

  }/*write_matrix*/

/***********************************************/
void Set_to_zero(
LOCAL_MATRIX_T* local_A /* out */) {

int i, j;

for (i = 0; i < Order(local_A); i++)
    for (j = 0; j < Order(local_A); j++)
        Entry(local_A,i,j) = 0.0;

} /* Set_to_zero */

/***********************************************/
void Build_matrix_type(
LOCAL_MATRIX_T* local_A /* in */) {
MPI_Datatype temp_mpi_t;
int block_lengths[2];
MPI_Aint displacements[2];
MPI_Datatype typelist[2];
MPI_Aint start_address;
MPI_Aint address;

MPI_Type_contiguous(Order(local_A)*Order(local_A),
    MPI_FLOAT, &temp_mpi_t);

block_lengths[0] = block_lengths[1] = 1;

typelist[0] = MPI_INT;
typelist[1] = temp_mpi_t;

MPI_Address(local_A, &start_address);
MPI_Address(&(local_A->n_bar), &address);
displacements[0] = address - start_address;

MPI_Address(local_A->entries, &address);
displacements[1] = address - start_address;

MPI_Type_struct(2, block_lengths, displacements,
    typelist, &local_matrix_mpi_t);
MPI_Type_commit(&local_matrix_mpi_t);

} /* Build_matrix_type */

/***********************************************/
void Local_matrix_multiply(
LOCAL_MATRIX_T* local_A /* in */,
LOCAL_MATRIX_T* local_B /* in */,
LOCAL_MATRIX_T* local_C /* out */) {
int i, j, k;

for (i = 0; i < Order(local_A); i++)
    for (j = 0; j < Order(local_A); j++)
        for (k = 0; k < Order(local_B); k++)
            Entry(local_C,i,j) = Entry(local_C,i,j)
                + Entry(local_A,i,k)*Entry(local_B,k,j);

} /* Local_matrix_multiply */

/***********************************************/
void Print_local_matrices(
char* title /* in */,
LOCAL_MATRIX_T* local_A /* in */,
GRID_INFO_T* grid /* in */) {

int         coords[2];
int         i, j;
int         source;
MPI_Status  status;

if (grid->my_rank == 0) {
    printf("%s\n", title);
    printf("Process %d > grid_row = %d, grid_col = %d\n",
        grid->my_rank, grid->my_row, grid->my_col);
    for (i = 0; i < Order(local_A); i++) {
        for (j = 0; j < Order(local_A); j++)
            printf("%4.1f ", Entry(local_A,i,j));
        printf("\n");
    }
    for (source = 1; source < grid->p; source++) {
        MPI_Recv(temp_mat, 1, local_matrix_mpi_t, source, 0,
            grid->comm, &status);
        MPI_Cart_coords(grid->comm, source, 2, coords);
        printf("Process %d > grid_row = %d, grid_col = %d\n",
            source, coords[0], coords[1]);
        for (i = 0; i < Order(temp_mat); i++) {
            for (j = 0; j < Order(temp_mat); j++)
                printf("%4.1f ", Entry(temp_mat,i,j));
            printf("\n");
        }
    }
    fflush(stdout);
} else {
    MPI_Send(local_A, 1, local_matrix_mpi_t, 0, 0, grid->comm);
}

} /* Print_local_matrices */
*

参考代码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FOX算法的MPI实现 的相关文章

  • qt操作第三方软件

    QT控制第三方软件方法 背景需求 实现思路 获取句柄方法 QT通过获取的信息操作 例子 控件ID为0或者控件ID和操作句柄相同怎么办 得到窗体x y height width 模拟键盘鼠标操作 附录 键值对照表 背景需求 通过前辈们写的软体
  • Shell--基础--06--传递参数

    Shell 基础 06 传递参数 1 介绍 我们可以在执行 Shell 脚本时 向脚本传递参数 1 1 脚本内获取参数的格式 格式为 n n 代表一个数字 0 执行的文件名 1 为执行脚本的第一个参数 2 为执行脚本的第二个参数 以此类推
  • AI时代,重新理解阿里云

    如果说 在数字化时代 阿里云给外界的标签是基于算力 数据等要素的基建角色 那么 在如今的智能化时代 基于自身强大的云计算能力和长期以往的AI技术积累 它的这种底座底色显然再一次被夯实 彰显 作者 皮爷 出品 产业家 宜昌城东大道 左侧是中国
  • DirectX编程:利用 DirectSound 录音

    DirectX编程 利用 DirectSound 录音 转载 http www cnblogs com stg609 archive 2008 10 24 1318931 html 花了一阵子 把DirectX安装后自带的帮助文件中的那部分

随机推荐

  • ES时间分组统计查询

    创建索引 PUT test 索引结构 PUT test mapping properties insertTime type date id type text fields keyword type keyword ignore abov
  • halcon之Blob分析实战

    Blob分析 Blob Analysis 在计算机视觉中的Blob是指图像中的具有相似颜色 纹理等特征所组成的一块连通区域 Blob分析 Blob Analysis 是对图像中相同像素的连通域进行分析 该连通域称为Blob 其过程其实就是将
  • 【数据结构】栈

    文章目录 1 栈的概念及结构 2 栈的实现 2 1栈的实现思路 2 2概念理解题 2 3栈的结构体定义 2 4函数接口 功能 2 5头文件Stack h 2 6函数实现Stack c 2 7测试函数Test c 2 8有效的括号 利用栈实现
  • Oracl之动态Sql编写总结

    一 概述 在通常的sql操作中 sql语句基本上都是固定的 如 SELECT t empno t ename FROM scott emp t WHERE t deptno 20 但有的时候 从应用的需要或程序的编写出发 都可能需要用到动态
  • 【抽样技术】CH2 简单随机抽样补充——比率估计与回归估计

    目录 一 概述 1 问题的提出 2 比率估计与回归估计的作用和使用条件 3 辅助变量的特点 4 相关符号 二 比率估计量 编辑 编辑 1 问题的提出 2 定义 3 比估计与简单估计的比较 4 比率估计的思想 5 比率估计量及其性质 1 引理
  • 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

    import java util Arrays 问题 顺时针螺旋输出数组 题目特征 保持一种模式前进 遇到一定条件转换另一种模式前进 思路 用一个二维数组来不同取值来控制前进 设置变动的边界为改变的条件 public class Test1
  • [1160]ModuleNotFoundError: No module named setuptools_rust

    报错信息 Traceback most recent call last File line 1 in File tmp pip build my9sai1o cryptography setup py line 14 in from se
  • 复现iis 文件解析漏洞

    1 开启IIS服务 开始 管理工具 Internet信息服务 IIS 管理器 2 点击Internet信息服务 IIS 管理器 查看自己web网站中的文件和IIS服务的开始 停止 暂停按钮 查看IIS服务是否开启 若未开启请开启 HLY 本
  • 如何查看某个端口被占用

    查看8080端口是否被占用可以使用如下命令 Windows netstat ano find 8080 Linux netstat ano grep 8080 netstat命令详解 Netstat用于显示与IP TCP UDP和ICMP协
  • IPFS: NAT traversal(NAT穿越)

    IPFS是一个p2p网络 那么一定绕不开的一个问题就是NAT穿越 之前的文章里面也提到过IPFS网络连通性使用的ICE NAT穿越框架 本文简单介绍一下什么是NAT 为什么有NAT技术 NAT主要用来缓解全球的IPv4地址不够用的情况 IP
  • springboot整合rabbitMq(未完成)

    1 下载安装如下软件 erlang语言和rabbitmq服务 2 配置环境变量 erl安装目录 bin rabbit安装目录 sbin 3 安装插件 打开cmd窗口 进入sbin的cmd窗口 输入rabbitmq plugins enabl
  • python3 学习笔记(三):函数与模块

    python3 学习笔记 python 优雅 明确 简单 函数与模块 1 函数 组织好的 可重复使用的 用来实现某一功能的代码段 1 定义 def function x pass 其中 def为关键字 function 为函数名 x为形参
  • C语言基础知识--weak关键字

    目录 一 C语言弱函数定义 weak关键字 1 weak关键字简介 2 weak关键字使用示例 二 总结 一 C语言弱函数定义 weak关键字 1 weak关键字简介 使用 attribute weak 修饰函数 告诉编译器此函数为同名函数
  • 修改服务器404页面,Apache服务器404页面设置具体步骤

    在网站运营过程中 由于某些原因有时候要对网页进行删除 也就意味以后用户或者用户访问删除页面都是访问不了的 如果用户和搜索引擎访问错误页面返回值不是404的话 那么就很不友好 大大增加跳出率 404页面就是引导用户从错误的页面访问到正确的页面
  • 经典算法题收集一

    1 题目一 有 n个人围成一圈 顺序排号 从第一个人开始报数 从 1 到 3 报数 凡报到 3 的人退出圈子 问最后留下的是原来第几号的那位 其实这是一个约瑟夫环问题 这个问题最本质其实就是循环链表的问题 围成一个圈之后 报数即是循环链表的
  • Oracle小数连接字符串时开头的0不见的问题

    小数在连接成字符串的时候 如果小数的开头是0 几的话 前面的 0 会被省略掉 在excel中也有这个特点 具体是为什么不清楚 如 select 0 8 from dual 结果 8 可以用下面的方式避免 防止导致查询到的最终结果不合适 se
  • leetcode分类刷题:基于数组的双指针(四、小的移动)

    leetcode上有些题是真的太难了 正常读题之后完全想不到要用双指针来求解 本次博客总结的题目是双指针初始时位于数组两端 哪个元素小就移动哪个指针 11 盛最多水的容器 1 这道题放在42 接雨水的相似题目里 可能是因为它们都有相似的双指
  • Android 10.0系统启动之init进程-[Android取经之路]

    原文链接 https blog csdn net yiranfeng article details 103549394 摘要 init进程是linux系统中用户空间的第一个进程 进程号为1 当bootloader启动后 启动kernel
  • CTFshow 击剑杯 部分WP

    摆烂了摆烂了 太难了 聪明的师傅已经组队打起月赛了 试试能不能苟住前5 苟住了 复现的后面再补充吧 文章目录 1 Misc 中文识别带师 2 Web 简单的验证码 easyPOP 3 Pwn pwn01 My sword is ready
  • FOX算法的MPI实现

    算法描述如下 将待相乘的矩阵A和B分成p个方块Ai j和Bi j 0 j i p 1 每块大小为 n p n p 并将他们分配给 p p 个处理器 开始时处理器Pi j存放有Ai j和Bi j 并负责计算块Ci j 然后Fox算法执行以下