⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cannon.cpp

📁 本程序采用vc2005结合openmp实现了并行矩阵相乘的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 + -