OpenMP平行計算程式設計-n以內的完數的個數

kewlgrl發表於2016-10-17

1.問題描述

一個數如果恰好等於它的因子之和,這個數就稱為“完數”。例如6=1+2+3,再如8的因子和是7(即1+2+4),8不是完數。輸入一個數n,程式設計找出n以內的所有完數及其個數。

2.演算法設計

2.1 序列演算法設計

序列演算法步驟如下

①因為1不算入一個完數,所以令數i=2,初始化答案值ans=0;

②因為1是任何數的一個因數,所以可初始化因數之和sum=1;

③令數k=2;

④如果數i能整除數k,說明k是i的一個因數,則sum += k;

⑤若k<=i/2(控制範圍保證i%k能進行計算),++k,轉到④,否則轉到⑥;

⑥若sum = i,++ans;

⑦若i <=n,++i,轉到②,否則轉到⑧;

⑧函式返回答案值ans。

2.2 並行演算法設計

並行演算法步驟如下

①因為1不算入一個完數,所以令數i=2,初始化答案值ans=0;

②“#pragmaomp parallel for”

②因為1是任何數的一個因數,所以可初始化因數之和sum=1;

“#pragmaomp parallel for”

③令數k=2;

“#pragmaomp critical”

④如果數i能整除數k,說明k是i的一個因數,則sum += k;

⑤若k<=i/2(控制範圍保證i%k能進行計算),++k,轉到④,否則轉到⑥;

⑥若sum = i,++ans;

⑦若i <=n,++i,轉到②,否則轉到⑧;

⑧函式返回答案值ans。

 

2.3 理論加速比分析

若p個處理器上資料量為n,則S=np/(n+2plogp)。

本機測試中,p=4:若n=10000,則S=3.9981;若n=100000,則S=3.9998。


/*問題描述:一個數如果恰好等於它的因子之和,這個數就稱為“完數”。例如6=1+2+3,再如8的因子和是7(即1+2+4),8不是完數。程式設計找出n以內的所有完數。
*/
// test.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <ctime>
#include <omp.h>
#include <windows.h>
using namespace std;

int OMP_Perfect(long long n)       //平行計算n以內的完數個數
{
	int ans = 0;                  // n以內的完數個數
	long long i, k;                      //迴圈變數
#pragma omp parallel for
	for (i = 2; i <= n; i++)  //1不算入一個完數。
	{
		long long sum = 1;                 //數的因數之和,1是任何數的一個因數。
#pragma omp parallel for reduction(+:sum)              //解決sum資料衝突
		for (k = 2; k <= i / 2; k++)  //k<=i/2是要保證i%k能進行計算。
			if (i%k == 0)
				sum += k;       //因數之和
		if (sum == i)       //找到一個完數
			++ans;                 //函式返回答案值ans
	}
	return ans;
}
int Perfect(long long n)
{
	int ans = 0;                  // n以內的完數個數
	long long i, k;                      //迴圈變數
	for (i = 2; i <= n; i++)  //1不算入一個完數。
	{
		long long sum = 1;                 //數的因數之和,1是任何數的一個因數。
		for (k = 2; k <= i / 2; k++)  //k<=i/2是要保證i%k能進行計算。
			if (i%k == 0)
				sum += k;       //因數之和
		if (sum == i)       //找到一個完數
			++ans;                 //函式返回答案值ans
	}
	return ans;
}
int main()
{
	long long n;
	cin >> n;
	printf("%lld以內的完數有:\n", n);
	clock_t t1, t2;
	t1 = clock();
	printf("Sum= %d\n", OMP_Perfect(n)); //輸出平行計算出的n以內的完數個數
	t2 = clock();
	printf("parallel time: %d\n", t2 - t1);//輸出平行計算時間
	t1 = clock();
	printf("Sum= %d\n", Perfect(n)); //輸出序列計算出的n以內的完數個數
	t2 = clock();
	printf("serail time: %d\n", t2 - t1); //輸出序列計算時間
	system("pause");
	return 0;
}





相關文章