📄 cannon.cpp
字号:
#include "omp.h"
#include "conio.h"
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#define N 160
void MoveDataBlockLine_A( int A[][N], int lineNumber ) // A 左移一块
{
int i,j, k, jump=N/4;
int tmp[N/4][N/4];
for( i=0; i<jump; i++ )
for( j=0; j<jump; j++ )
tmp[i][j] = A[i+jump*lineNumber][j]; // 保存块 A(i,0)
for( k=0; k<3; k++ )
{
for( i=0; i<jump; i++ )
for( j=0; j<jump; j++ )
A[i+jump*lineNumber][j+jump*k] = A[i+jump*lineNumber][j+jump*(k+1)];
}
for( i=0; i<jump; i++ )
for( j=0; j<jump; j++ )
A[i+jump*lineNumber][j+jump*3] = tmp[i][j];
}
void MoveDataBlockLine_B( int B[][N], int lineNumber ) // B 上移一块
{
int i,j, k, jump=N/4;
int tmp[N/4][N/4];
for( i=0; i<jump; i++ )
for( j=0; j<jump; j++ )
tmp[i][j] = B[i][j+jump*lineNumber]; // 保存块 b(0,j)
for( k=0; k<3; k++ )
{
for( i=0; i<jump; i++ )
for( j=0; j<jump; j++ )
B[i+jump*k][j+jump*lineNumber] = B[i+jump*(k+1)][j+jump*lineNumber];
}
for( i=0; i<jump; i++ )
for( j=0; j<jump; j++ )
B[i+jump*3][j+jump*lineNumber] = tmp[i][j];
}
void MutiplyBlock( int A[][N], int B[][N], int C[][N], int bi, int bj )
{
int i,j,jump=N/4;
for( i=0; i<jump; i++ )
for( j=0; j<jump; j++ )
C[i+jump*bi][j+jump*bj] += A[i+jump*bi][j+jump*bj] * B[i+jump*bi][j+jump*bj];
}
int main()
{
FILE *fpA, *fpB, *fpC;
int i, j, k, jump=N/4;
int A[N][N], B[N][N], C[N][N];
printf( "\n开始 Cannon 计算 ..." );
fpA = fopen( "A.txt", "w+" );
fpB = fopen( "B.txt", "w+" );
/* 赋初值 */
for( i=0; i<N; i++ )
for( j=0; j<N; j++ )
{
A[i][j] = rand()%100; fprintf( fpA, "\n A[%d][%d] = %d ", i, j, A[i][j] );
B[i][j] = rand()%100; fprintf( fpB, "\n B[%d][%d] = %d ", i, j, B[i][j] );
C[i][j] = 0;
}
fclose(fpA);
fclose(fpB);
// 设置 omp 线程数
omp_set_num_threads( 2 );
if( N % 4 == 0 )
{
#pragma omp parallel shared( A, B, C ) private( i,j )
{
#pragma omp sections
{
// 第一次移动数据
#pragma omp section // 一个线程用来移动A的上半部分 和 B的左半部分
{
printf("\n Sections 1, thread number %d ", omp_get_thread_num() );
MoveDataBlockLine_A( A, 1 );
MoveDataBlockLine_A( A, 2 );
MoveDataBlockLine_A( A, 2 );
MoveDataBlockLine_A( A, 3 );
MoveDataBlockLine_A( A, 3 );
MoveDataBlockLine_A( A, 3 );
}
#pragma omp section // 一个线程用来移动A的下半部分 和 B的右半部分
{
printf("\n Sections 1, thread number %d ", omp_get_thread_num() );
MoveDataBlockLine_B( B, 1 );
MoveDataBlockLine_B( B, 2 );
MoveDataBlockLine_B( B, 2 );
MoveDataBlockLine_B( B, 3 );
MoveDataBlockLine_B( B, 3 );
MoveDataBlockLine_B( B, 3 );
}
}
}
// 开始循环计算
// 先进行计算,然后再移动数据
for( k=0; k<4; k++ )
{
#pragma omp parallel shared( A, B, C ) private( i,j )
{
#pragma omp sections
{
#pragma omp section // 一个线程用来移动A的下半部分 和 B的右半部分
{
printf("\n Setctons 2, thread number %d ", omp_get_thread_num() );
for( i=0; i<2; i++ )
for( j=0; j<4; j++ )
MutiplyBlock( A, B, C, i, j );
MoveDataBlockLine_A( A, 0 );
MoveDataBlockLine_B( B, 0 );
MoveDataBlockLine_A( A, 1 );
MoveDataBlockLine_B( B, 1 );
}
#pragma omp section // 一个线程用来移动A的下半部分 和 B的右半部分
{
printf("\n Setctons 2, thread number %d ", omp_get_thread_num() );
for( i=2; i<4; i++ )
for( j=0; j<4; j++ )
MutiplyBlock( A, B, C, i, j );
MoveDataBlockLine_A( A, 2 );
MoveDataBlockLine_B( B, 2 );
MoveDataBlockLine_A( A, 3 );
MoveDataBlockLine_B( B, 3 );
}
}
}
}
// 显示本次迭代结果
fpC = fopen( "C.txt", "w+" );
for( i=0; i<N; i++ )
for( j=0; j<N; j++ )
{
//printf( "\n C[%d][%d] = %d ", i, j, C[i][j] );
fprintf( fpC, "\n C[%d][%d] = %d ", i, j, C[i][j] );
}
fclose(fpC);
}
else
printf("\n Error! N % 4 != 0 ! ");
printf( "\nCannon 计算完毕 ...\n" );
getchar();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -