MPI 기반 매트릭스 곱 하기 summa 알고리즘 구현 (원본 프로그램 첨부)
24321 단어 SUM
서광 4000 병행 기 는 국가 스마트 컴퓨터 연구 개발 센터 가 개발 한 분포 저장 구조 와 정보 전송 체 제 를 바탕 으로 하 는 대규모 병행 컴퓨터 시스템 이다.본 고 는 전형 적 인 매트릭스 곱셈 알고리즘 인 SUMMA 알고리즘 이 서광 4000 과 같은 대규모 병렬 기 에서 의 실현 을 논의 했다.후속 단계 에서 작 가 는 다른 행렬 곱셈 병렬 산법 의 성능 을 계속 분석 하고 비교 할 것 이다.
SUMMA 알고리즘 은 먼저 A, B, C 를 같은 크기 의 행렬 로 나 누 어 mesh 에 대응 합 니 다.r × mesh_c 의 2 차원 mesh 에서.그러나 SUMMA 알고리즘 은 행렬 곱셈 을 일련의 순위 nb 수정 으로 분해 합 니 다. 즉, 각 프로세서 의 A 와 B 는 각각 nb 크기 의 열 블록 과 줄 블록 으로 분해 되 어 곱 합 니 다. 앞에서 말 한 블록 사 이 즈 는 nb 의 크기 를 말 합 니 다.알고리즘 에서 방송 은 논리 프로세서 행 링 이나 열 링 의 흐름 선 전송 을 실현 하여 계산 과 통신 의 중첩 에 이 르 렀 다. 구체 적 인 설명 은 알고리즘 1 과 같다.
알고리즘 1. 2 차원 mesh 의 SUMMA 알고리즘
C= 0
for i= 0 t o k-1 step nb do
cur col = i×c/ n
cur row = i×r / m
if my col = cur rol A i mod (k/c) nb , A′
if my row = cur row B i mod (k/r) nb , B ′
C= A′×B ′
end for
SUMMA 알고리즘 의 핵심 사상 은 각 프로세서 가 같은 줄 프로세서 에서 A 매트릭스 블록 의 모든 열 과 같은 열 프로세서 에서 B 매트릭스 블록 의 모든 줄 을 수집 한 다음 에 행렬 을 곱 한 후에 누적 하여 C 매트릭스 의 블록 행렬 을 만 드 는 것 이다.마지막 으로 rank = 0 의 프로세서 가 다른 프로세서 의 데 이 터 를 수집 하여 최종 행렬 C 를 형성한다.
SUMMA 알고리즘 은 cannon 알고리즘 에 비해 SUMMA 알고리즘 은 m * l 의 A 매트릭스 와 l * n 의 B 매트릭스 상승 (m, l, n 은 같 지 않 음) 을 계산 할 수 있 고 cannon 알고리즘 은 n * n 의 A 매트릭스 와 n * n 의 B 매트릭스 상승 만 실현 할 수 있어 한계 가 크다.그러나 수준 이 제한 되 어 있 고 매트릭스 블록 을 잘 나 누 기 위해 이 MPI 가 구현 하 는 SUMMA 알고리즘 은 입력 한 매트릭스 비트 (m, l, n) 를 프로세서 개수 (사용자 가 정의) 의 정수 배 로 해 야 합 니 다. 그렇지 않 으 면 오 류 를 알려 줍 니 다.임 의 차원 의 행렬 상승 을 어떻게 실현 하 는 지 에 대해 서 는 위대 한 절차 원숭이 들 의 많은 지 도 를 바 랍 니 다.
원본 코드 가 너무 길 기 때문에 여 기 는 일부 MPI 원본 코드 만 첨부 되 어 있 습 니 다. 모든 원본 코드 의 방문객 이 메 일 로 저 에 게 연락 할 수 있 고 연락 처 는 맨 아래 에 있 습 니 다.
/*summa */
void My_summa(const int my_rank, int *a, int *b)
{
int k, i, j;
int *c;
int len_c;
int dest, tag;
int my_rank_row, my_rank_col;
int *a_col_send, *b_row_send, *a_col_recv, *b_row_recv;
MPI_Status status_a, status_b;
my_rank_row = my_rank / mesh_c;
my_rank_col = my_rank % mesh_c;
a_col_send = (int *)malloc((m / mesh_r) * sizeof(int));
b_row_send = (int *)malloc((n / mesh_c) * sizeof(int));
a_col_recv = (int *)malloc((m / mesh_r) * sizeof(int));
b_row_recv = (int *)malloc((n / mesh_c) * sizeof(int));
/* A */
for (k = 0; k < l / mesh_c; ++k)
{
for (i = 0; i < m / mesh_r; ++i)
{
a_col_send[i] = a[i * (l / mesh_c) + k];
}
for (i = 0; i < mesh_c; ++i)
{
dest = my_rank_row * mesh_c + i;
tag = my_rank_col * (l / mesh_c) + k;
MPI_Send(a_col_send, m / mesh_r, MPI_INT, dest, tag, MPI_COMM_WORLD);
}
}
/* B */
for (k = 0; k < l / mesh_r; ++k)
{
for (i = 0; i < n / mesh_c; ++i)
{
b_row_send[i] = b[k * (n / mesh_c) + i];
}
for (i = 0; i < mesh_r; ++i)
{
dest = my_rank_col + i * mesh_c;
tag = my_rank_row * (l / mesh_r) + k;
MPI_Send(b_row_send, n / mesh_c, MPI_INT, dest, tag, MPI_COMM_WORLD);
}
}
/* C */
len_c = (m / mesh_r) * (n / mesh_c);
c = (int *)malloc(len_c * sizeof(int));
for (i = 0; i < len_c; ++i)
{
c[i] = 0;
}
for (k = 0; k < l; ++k)
{ /* A B */
MPI_Recv(a_col_recv, m / mesh_r, MPI_INT, my_rank_row * mesh_c + k / (l / mesh_c), k,
MPI_COMM_WORLD, &status_a);
MPI_Recv(b_row_recv, n / mesh_c, MPI_INT, k / (l / mesh_r) * mesh_c + my_rank_col, k,
MPI_COMM_WORLD, &status_b);
/* C , C */
for (i = 0; i < m / mesh_r; ++i)
{
for (j = 0; j < n / mesh_c; ++j)
{
c[i * (n / mesh_c) + j] += a_col_recv[i] * b_row_recv[j];
}
}
}
/* C 0 */
MPI_Send(c, len_c, MPI_INT, 0, 99, MPI_COMM_WORLD);
free(c);
free(a_col_send), free(b_row_send), free(a_col_recv), free(b_row_recv);
}
/*0 C */
void Collect_C()
{
int k, i, j;
int len_c, id_recv;
int *c_recv;
int c_imin, c_imax, c_jmin, c_jmax;
MPI_Status status;
len_c = (m / mesh_r) * (n / mesh_c);
c_recv = (int *)malloc(len_c * sizeof(int));
/* C C */
for (k = 0; k < num_procs; ++k)
{
MPI_Recv(c_recv, len_c, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
id_recv = status.MPI_SOURCE;
c_imin = (id_recv / mesh_c) * (m / mesh_r);
c_imax = c_imin + m / mesh_r - 1;
c_jmin = (id_recv % mesh_c) * (n / mesh_c);
c_jmax = c_jmin + n / mesh_c - 1;
for (i = c_imin; i <= c_imax; ++i)
{
for (j = c_jmin; j <= c_jmax; ++j)
{
C[i][j] = c_recv[(i - c_imin) * (n / mesh_c) + (j - c_jmin)];
}
}
}
free(c_recv);
}
/* */
void Print(char *str, int **matrix, int m, int n)
{
int i, j;
printf("%s", str);
for (i = 0; i < m; ++i)
{
for (j = 0; j < n; ++j)
{
printf("%-6d", matrix[i][j]);
}
printf("
");
}
printf("
");
}
컴 파일: mpicc summa.c -o summa -lm 주: p0 나타 나 면18495: p4_error: Child process exited while making connection to remote process on node2: 0 Killed by signal 2. 이러한 오류, 해결 방법: 홈 디 렉 터 리 에 직접 입력: source / home / guest /. bashrc 실행: mpirun -np 9 summa 9 6 12
실행 결과:
Allocate_A_B_C cheers!
Random_A_B cheers!
Scatter_A_B cheers!
Collect_C cheers!
random matrix A:
54 9 90 76 54 45
52 70 1 99 64 31
40 34 34 31 7 16
82 26 18 70 29 44
64 58 29 71 98 89
42 5 50 84 81 4
29 86 26 83 85 42
66 77 76 0 8 35
69 91 13 87 13 43
random matrix B:
83 77 1 12 0 51 53 94 56 3 78 90
60 8 28 38 43 65 81 9 42 9 61 50
97 30 41 10 17 54 53 52 84 6 17 84
58 70 79 66 26 57 8 38 17 36 76 60
1 9 21 43 19 83 94 16 13 87 78 83
94 32 35 78 90 4 62 48 75 93 67 53
Matrix C = A * B:
22444 14176 12709 12738 8969 17193 16835 15749 16331 12402 19294 24297
17333 13092 12303 14998 9607 18335 17209 11844 10776 12807 22936 21159
11967 7117 5542 5707 4419 8498 8574 7892 8342 3843 9746 11445
18337 13631 9227 11451 7755 13417 13420 14114 12063 9723 18818 19131
24187 14962 13659 19104 14705 21137 24925 16584 17612 20247 28026 28207
13965 11511 10709 10533 5148 16694 13815 11273 9543 10914 17401 20205
18936 11620 13315 16285 11693 20427 21139 11382 13086 15306 23702 23355
20768 9170 6731 7552 7905 13279 16685 12657 16043 5298 14106 18693
21549 14014 11801 14071 10513 16346 16301 13559 13651 9366 21661 20430
Print cheers!
successful run time is 0.109375
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
leetcode || 112、Path Sumproblem: Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.